Articles
Tutoriels
Guides interactifs
Intégration de Concourse CI et d'Atlassian Open DevOps
De nombreuses équipes utilisent leurs propres outils pour répondre à leurs besoins ou des outils hérités depuis des années. Ces outils sont essentiels au processus de développement qu'elles suivent, mais ils ne disposent pas d'intégrations standard à Jira. Heureusement, il est facile de créer une intégration personnalisée à l'aide des API REST Atlassian reprises dans la documentation dédiée aux développeurs Cloud - Atlassian Developer. Concourse CI est un produit de CI/CD qui, au moment de la rédaction de cet article, n'est pas intégré à l'Atlassian Marketplace. Cet article explique comment créer une intégration de base entre Jira et Concourse CI à l'aide des API REST Atlassian.
Prérequis
Utilisez la documentation nécessaire pour configurer Docker, Docker Compose et Concourse CI. Concourse CI s'exécute sur Docker et fournit un script Docker Compose pour vous aider à vous lancer facilement.
Pour en savoir plus sur l'application de démo ImageLabeller d'Atlassian, cliquez ici. Cet article explique comment utiliser Concourse CI pour déployer le composant SubmitImage d'ImageLabeller sur AWS.
Docker
Configurez Docker et Docker Compose en suivant la documentation associée :
Docker : https://docs.docker.com/get-docker/
Docker Compose : https://docs.docker.com/compose/install/
Concourse CI
Une fois Docker et Docker Compose installés, vous pouvez démarrer Concourse CI en utilisant le fichier docker-compose.yml fourni.
Suivez le guide de démarrage rapide de Concourse CI pour vous lancer, à l'adresse https://concourse-ci.org/quick-start.html#docker-compose-concourse. Ce guide nécessite de transmettre des informations d'identification à Concourse CI en toute sécurité. Il utilise l'intégration Concourse CI AWS Secrets Manager à cette fin.
Intégration de Concourse CI à AWS Secrets Manager
Voici la documentation expliquant comment intégrer Concourse CI à AWS Secrets Manager. Suivez les instructions de la documentation pour activer l'intégration et vous lancer.
Le fichier docker-compose.yml utilisé pour démarrer Concourse CI doit être légèrement modifié pour que l'intégration fonctionne. Prenez le fichier docker-compose.yml par défaut fourni par Concourse CI et ajoutez
CONCOURSE_AWS_SECRETSMANAGER_ACCESS_KEY, CONCOURSE_AWS_SECRETSMANAGER_SECRET_KEY et CONCOURSE_AWS_SECRETSMANAGER_REGION.
version: '3'
services:
concourse-db:
image: postgres
environment:
POSTGRES_DB: concourse
POSTGRES_PASSWORD: concourse_pass
POSTGRES_USER: concourse_user
PGDATA: /database
concourse:
image: concourse/concourse
command: quickstart
privileged: true
depends_on: [concourse-db]
ports: ["8080:8080"]
environment:
CONCOURSE_POSTGRES_HOST: concourse-db
CONCOURSE_POSTGRES_USER: concourse_user
CONCOURSE_POSTGRES_PASSWORD: concourse_pass
CONCOURSE_POSTGRES_DATABASE: concourse
CONCOURSE_EXTERNAL_URL: http://localhost:8080
CONCOURSE_ADD_LOCAL_USER: test:test
CONCOURSE_MAIN_TEAM_LOCAL_USER: test
# instead of relying on the default "detect"
CONCOURSE_WORKER_BAGGAGECLAIM_DRIVER: overlay
CONCOURSE_CLIENT_SECRET: Y29uY291cnNlLXdlYgo=
CONCOURSE_TSA_CLIENT_SECRET: Y29uY291cnNlLXdvcmtlcgo=
CONCOURSE_X_FRAME_OPTIONS: allow
CONCOURSE_CONTENT_SECURITY_POLICY: "*"
CONCOURSE_CLUSTER_NAME: tutorial
CONCOURSE_WORKER_CONTAINERD_DNS_SERVER: "8.8.8.8"
CONCOURSE_WORKER_RUNTIME: "containerd"
CONCOURSE_ENABLE_ACROSS_STEP: "true"
CONCOURSE_ENABLE_PIPELINE_INSTANCES: "true"
CONCOURSE_AWS_SECRETSMANAGER_ACCESS_KEY: <add access key>
CONCOURSE_AWS_SECRETSMANAGER_SECRET_KEY: <add secret key>
CONCOURSE_AWS_SECRETSMANAGER_REGION: <add a region>
Une fois que l'intégration sera configurée et que Concourse CI fonctionnera avec l'intégration activée, ajoutez les secrets suivants à AWS Secrets Manager.
/concourse/main/bitbucket_username
/concourse/main/bitbucket_api_key
/concourse/main/bitbucket_ssh_key
/concourse/main/docker_username
/concourse/main/docker_api_key
/concourse/main/AWS_ACCESS_KEY_ID
/concourse/main/AWS_SECRET_ACCESS_KEY
/concourse/main/AWS_DEFAULT_REGION
Les secrets Bitbucket et Docker devront peut-être être remplacés si le lecteur n'utilise pas Bitbucket pour son code, ni JFrog comme dépôt Docker. Vous pouvez les ajuster aux outils individuels du lecteur en guise d'exercice.
Utiliser Concourse CI
Lancez docker ps -a avant et après avoir lancé docker-compose up -d pour vérifier que Concourse CI a démarré correctement.
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
docker-compose up -d
Creating network "restapiproject_default" with the default driver
Creating restapiproject_concourse-db_1 ... done
Creating restapiproject_concourse_1 ... done
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bd2b5afd0ac7 concourse/concourse "dumb-init /usr/loca…" 3 seconds ago Up 2 seconds 0.0.0.0:8080->8080/tcp restapiproject_concourse_1
bd9005b45636 postgres "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 5432/tcp restapiproject_concourse-db_1
Accédez à http://localhost:8080/ après avoir exécuté « fly -t tutorial login -c http://localhost:8080 -u test -p test ».
fly -t tutorial login -c http://localhost:8080 -u test -p test
logging in to team 'main'
target saved
Aucun pipeline n'est défini pour le moment.
Un pipeline Hello World
Configurez un pipeline Hello World en suivant cette documentation Concourse CI : https://concourse-ci.org/tutorial-hello-world.html. Cette action est nécessaire pour présenter l'interface de ligne de commande Fly et se familiariser avec l'utilisation de Concourse CI depuis la ligne de commande.
La section suivante explique comment déployer un service AWS Lambda écrit en Golang dans une seule région AWS avec Concourse CI et comment rédiger une mise à jour pour un ticket Jira dans le cadre du processus.
Déployer SubmitImage avec Concourse CI
Vous devez suivre trois étapes pour déployer SubmitImage Lambda avec Concourse CI. La première consiste à écrire un script bash simple qui utilise l'API REST Jira Cloud pour écrire un commentaire dans un ticket Jira. Il s'agit de l'intégration la plus simple. La deuxième étape consiste à créer une image Docker avec les outils nécessaires pour développer et déployer un service AWS Lambda en Golang. La dernière étape consiste à écrire deux fichiers de configuration Concourse CI. Le premier, parent.yml, surveille le dépôt SubmitImage à la recherche de nouvelles branches et crée des pipelines pour déployer des commits depuis ces branches. Le deuxième fichier de configuration, child.yml, définit les étapes nécessaires pour déployer un changement.
Étape 1 : Mettre à jour les tickets Jira via l'API REST
Ce script de mise à jour utilise l'API REST de la plateforme Jira Cloud pour écrire un commentaire dans un ticket Jira spécifique. Cinq paramètres doivent être définis à chaque exécution du script. Le nom d'utilisateur Jira, le jeton d'API Jira et l'espace de travail sont généralement les mêmes pour chaque exécution d'un pipeline spécifique. La clé de ticket dépendra du nom de la branche en cours de déploiement. Selon les bonnes pratiques Jira, il convient d'intégrer l'ID du ticket Jira aux noms de branche et de commiter les messages lorsque vous travaillez sur un ticket précis. Cet article part du principe que les bonnes pratiques sont suivies et que les noms de branche sont similaires à l'ID du ticket Jira.
Comment trouver les paramètres
Nom d'utilisateur Jira
Le nom d'utilisateur Jira est l'adresse e-mail utilisée pour se connecter à Jira.
Jeton d'API Jira
Accédez aux paramètres du compte.
Cliquez sur Sécurité.
Cliquez sur Créer et gérer des jetons d'API
Espace de travail
Avec l'URL d'une instance Jira comme https://pmmquickstartguides01.atlassian.net/jira/software/projects/IM/boards/1?selectedIssue=IM-203, l'espace de travail est pmmquickstartguide01.
Clé de ticket
Avec l'URL d'un ticket Jira, comme https://pmmquickstartguides01.atlassian.net/jira/software/projects/IM/boards/1?selectedIssue=IM-203, la clé du ticket Jira est IM-203. Insérez l'ID du ticket Jira dans les messages de commit et les noms de branche afin que l'intégration puisse écrire les mises à jour au bon endroit.
Commentaire
Le commentaire peut être n'importe quoi.
Script de mise à jour
Le script de mise à jour est un script shell Bash simple qui utilise le point de terminaison de l'API REST pour le commentaire du ticket Jira. Voici la documentation de cet appel d'API. Le script peut être modifié pour permettre une intégration plus étroite en suivant le modèle fourni pour effectuer des appels d'API supplémentaires. Copiez ce script dans un fichier appelé concourse-ci-integration.sh et placez-le dans un dépôt Bitbucket ou GitHub nommé updateScript.
#!/usr/bin/env bash
addCommentToIssue() {
printf "addCommentToIssue\n"
local jiraUsername=$1
shift
local jiraApiToken=$1
shift
local workspace=$1
shift
local issueKey=$1
shift
local comment=$1
shift
curl -s --request POST \
--url 'https://'"${workspace}"'.atlassian.net/rest/api/3/issue/'"${issueKey}"'/comment' \
--user "${jiraUsername}"':'"${jiraApiToken}" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
"body": {
"type": "doc",
"version": 1,
"content": [{
"type": "paragraph",
"content": [{
"text": "'"${comment}"'",
"type": "text"
}]
}]
}
}' | jq
}
main() {
printf "main\n"
while getopts ":c:k:o:u:t:w:" opt; do
case $opt in
c)
local comment=$OPTARG
;;
k)
local issueKey=$OPTARG
;;
o)
local op=$OPTARG
;;
u)
local jiraUsername=$OPTARG
;;
t)
local jiraApiToken=$OPTARG
;;
w)
local workspace=$OPTARG
;;
*)
printf "invalid option: -${OPTARG}\n" >&2
exit 1
;;
esac
done
case $op in
ac)
addCommentToIssue ${jiraUsername} ${jiraApiToken} ${workspace} ${issueKey} "${comment}"
;;
*)
printf "invalid op: ${op}\n" >&2
exit 1
;;
esac
}
main "$@"
Étape 2 : Personnaliser un document Dockerfile
Créez un document Dockerfile personnalisé avec les outils nécessaires pour développer et déployer un service AWS Lambda écrit en Golang. Le document Dockerfile installe quelques utilitaires, puis ajoute AWS SAM et Golang. L'image Git clone le script de mise à jour créé à l'étape 1 à partir d'un dépôt Bitbucket. Vous devez remplacer ce dépôt Bitbucket par le dépôt que vous avez créé pour le script de mise à jour. Docker crée ce document Dockerfile et le pushe vers un dépôt Docker.
Dockerfile
# syntax = docker/dockerfile:1.3
FROM ubuntu:20.04
MAINTAINER wmarusiak@atlassian.com
WORKDIR /workspace
RUN apt-get update \
&& apt-get -y upgrade \
&& apt-get -y install curl unzip tar openssh-client git jq
RUN curl https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip -L -o aws-sam-cli.zip \
&& mkdir sam-installation \
&& unzip aws-sam-cli.zip -d sam-installation \
&& ./sam-installation/install \
&& sam --version
RUN curl https://go.dev/dl/go1.18.2.linux-amd64.tar.gz -L -o go.tar.gz \
&& rm -rf /usr/local/go \
&& tar -C /usr/local -xzf go.tar.gz
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan bitbucket.org >> ~/.ssh/known_hosts
RUN --mount=type=ssh git clone git@bitbucket.org:pmmquickstartguides01/updatescript.git
ENV PATH $PATH:/usr/local/go/bin
Étape 3 : Fichiers yaml du pipeline de déploiement de Concourse CI
Créez un dépôt appelé concourse et placez-y deux fichiers. Parent.yml crée un pipeline qui surveille un dépôt à la recherche de nouvelles branches correspondant à une expression régulière. L'expression régulière branch_regex est IM-* qui correspond à toutes les branches commençant par IM-. Parent.yml créera un pipeline en utilisant la configuration de child.yml lorsqu'une branche correspondant à l'expression régulière IM-* sera créée. Vous devriez mettre à jour ce fichier pour renvoyer vers votre propre version du dépôt SubmitImage. Le code SubmitImage est disponible ici. Copiez le code de ce dépôt dans un dépôt disposant des autorisations d'écriture.
parent.yml
resource_types:
- name: git-branches
type: registry-image
source:
repository: aoldershaw/git-branches-resource
resources:
- name: feature-branches
type: git-branches
source:
uri: git@bitbucket.org:pmmquickstartguides01/submitimage.git
branch_regex: IM-*
private_key: ((bitbucket_ssh_key))
- name: examples
type: git
source:
uri: git@bitbucket.org:pmmquickstartguides01/concourse.git
private_key: ((bitbucket_ssh_key))
jobs:
- name: set-feature-pipelines
plan:
- in_parallel:
- get: feature-branches
trigger: true
- get: examples
- load_var: branches
file: feature-branches/branches.json
- across:
- var: branch
values: ((.:branches))
set_pipeline: dev
file: examples/child.yml
vars: {branch: ((.:branch.name))}
Le fichier child.yml définit un pipeline en quatre étapes. Tout d'abord, il exécute « sam-validate » pour vérifier la validité du fichier template.yml AWS CloudFormation. Ensuite, il exécute « sam-build » pour transformer le package SubmitImage en un artefact déployable. Puis il exécute « sam-deploy » pour déployer le code SubmitImage mis à jour sur AWS. Enfin, le pipeline invoque le script de mise à jour créé à l'étape 1 pour écrire un commentaire dans le ticket Jira correspondant.
child.yml
resources:
- name: repo
type: git
source:
uri: git@bitbucket.org:pmmquickstartguides01/submitimage.git
branch: ((branch))
private_key: ((bitbucket_ssh_key))
jobs:
- name: deploy-submit-image
plan:
- get: repo
trigger: true
- task: run-sam-validate
config:
platform: linux
image_resource:
type: registry-image
source:
repository: docker.atl-paas.net/wmarusiak/ubuntuawssam
username: ((docker_username))
password: ((docker_api_key))
inputs: # add the get step as an input to this task
- name: repo
run:
path: sam
args: ["validate", "-t", "repo/template.yml"]
params:
AWS_ACCESS_KEY_ID: ((AWS_ACCESS_KEY_ID))
AWS_SECRET_ACCESS_KEY: ((AWS_SECRET_ACCESS_KEY))
AWS_DEFAULT_REGION: ((AWS_DEFAULT_REGION))
- task: run-sam-build
config:
platform: linux
image_resource:
type: registry-image
source:
repository: docker.atl-paas.net/wmarusiak/ubuntuawssam
username: ((docker_username))
password: ((docker_api_key))
inputs: # add the get step as an input to this task
- name: repo
run:
path: sam
args: ["build", "-t", "repo/template.yml"]
params:
AWS_ACCESS_KEY_ID: ((AWS_ACCESS_KEY_ID))
AWS_SECRET_ACCESS_KEY: ((AWS_SECRET_ACCESS_KEY))
AWS_DEFAULT_REGION: ((AWS_DEFAULT_REGION))
- task: run-sam-deploy
config:
platform: linux
image_resource:
type: registry-image
source:
repository: docker.atl-paas.net/wmarusiak/ubuntuawssam
username: ((docker_username))
password: ((docker_api_key))
inputs: # add the get step as an input to this task
- name: repo
run:
path: sam
args: ["deploy", "-t", "repo/template.yml", "--stack-name", "OpenDevOpsSubmitImage", "--s3-bucket", "open-devops-code-us-west-1-756685045356", "--capabilities", "CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
params:
AWS_ACCESS_KEY_ID: ((AWS_ACCESS_KEY_ID))
AWS_SECRET_ACCESS_KEY: ((AWS_SECRET_ACCESS_KEY))
AWS_DEFAULT_REGION: ((AWS_DEFAULT_REGION))
- task: run-update-script
config:
platform: linux
image_resource:
type: registry-image
source:
repository: docker.atl-paas.net/wmarusiak/ubuntuawssam
username: ((docker_username))
password: ((docker_api_key))
input:
-name: repo
run:
path: /workspace/updatescript/concourse-ci-integration.sh
args: ["-c", "successfully deployed submitImage via concourse-ci", "-k", "((branch))", "-o", "ac", "-u", "((bitbucket_username))", "-t", "((bitbucket_api_key))", "-w", "pmmquickstartguides01"]
Comment démarrer le pipeline parent
Exécutez les trois commandes suivantes depuis le répertoire contenant le fichier parent.yml. La première commande se connecte à l'instance Concourse CI exécutée localement. La deuxième crée un pipeline appelé « wm » basé sur la configuration du fichier parent.yml. La troisième commande met fin à la pause du pipeline wm.
fly -t tutorial login -c http://localhost:8080 -u test -p test
fly -t tutorial set-pipeline -p wm -c parent.yml
fly -t tutorial unpause-pipeline -p wm
Accédez au client web Concourse CI après avoir exécuté ces trois commandes pour vérifier que le pipeline wm est opérationnel.
Après avoir exécuté fly set-pipeline avec le fichier parent.yml, le pipeline wm est disponible. Ce pipeline surveille SubmitImage à la recherche de nouvelles branches de fonctionnalité et crée un pipeline pour chaque branche de fonctionnalité correspondant à l'expression régulière du fichier parent.yml.
Cliquez sur le pipeline wm pour voir les étapes exécutées. Notez que l'étape feature-branches répertorie une branche IM-61. C'est la seule branche existante dans SubmitImage qui correspond à l'expression régulière du fichier parent.yml. Cliquez sur le pipeline de développement qui a été démarré automatiquement pour voir les étapes exécutées.
Notez qu'il y a une étape pour obtenir le dépôt SubmitImage et que la branche est IM-61. Notez également qu'il existe des étapes run-sam-validate, run-sam-build, run-sam-deploy et run-update-script.
Une fois l'exécution du pipeline de développement terminée, revenez au ticket Jira IM-61 et notez qu'un nouveau commentaire enregistré une minute auparavant correspond à la chaîne de commentaires du fichier child.yml.
Conclusion…
Ce guide explique comment configurer un pipeline pour déployer automatiquement un service AWS Lambda en Golang vers une seule région AWS à l'aide de Concourse CI. Il montre également comment utiliser un script shell Bash pour créer une intégration simple à Jira. Le script d'intégration peut être considérablement développé en étudiant plus en détail la documentation de l'API REST Atlassian disponible ici.
Partager cet article
Thème suivant
Lectures recommandées
Ajoutez ces ressources à vos favoris pour en savoir plus sur les types d'équipes DevOps, ou pour les mises à jour continues de DevOps chez Atlassian.