Artykuły
Samouczki
Interaktywne przewodniki
Integracja Concourse-ci i Atlassian Open DevOps
Wiele zespołów wdraża własne narzędzia w celu zaspokojenia swoich potrzeb lub od lat korzysta ze starszych narzędzi. Te narzędzia mają zasadnicze znaczenie dla przyjętego w zespole przebiegu prac programistycznych, ale nie mają gotowych integracji z Jira. Na szczęście niestandardową integrację można łatwo utworzyć przy użyciu interfejsów API REST Atlassian dostępnych na stronie Cloud developer documentation - Atlassian Developer. Concourse-ci to produkt CI/CD, dla którego w momencie pisania tego artykułu w sklepie Atlassian Marketplace nie ma dostępnej integracji. W tym artykule przedstawiono sposób utworzenia podstawowej integracji między Jira i Concourse-ci przy użyciu interfejsów API REST Atlassian.
Wymagania wstępne
Użyj niezbędnej dokumentacji, aby skonfigurować narzędzia Docker, docker-compose i Concourse-ci. Concourse-ci działa na platformie Docker i udostępnia skrypt docker-compose w celu uproszczenia rozpoczęcia pracy.
Przeczytaj o aplikacji demonstracyjnej ImageLabeller firmy Atlassian tutaj. W tym artykule przedstawiono, jak używać Concourse-ci w celu wdrożenia komponentu SubmitImage aplikacji ImageLabeller w AWS.
Docker
Skonfiguruj narzędzia Docker i docker-compose, postępując zgodnie z ich dokumentacją:
Docker: https://docs.docker.com/get-docker/
docker-compose: https://docs.docker.com/compose/install/
Concourse-ci
Po zainstalowaniu narzędzi Docker i docker-compose możesz uruchomić Concourse-ci za pomocą dostarczonego pliku docker-compose.yml.
Aby zacząć korzystać z Concourse-ci, postępuj zgodnie ze skróconym przewodnikiem dostępnym pod adresem https://concourse-ci.org/quick-start.html#docker-compose-concourse. Ten przewodnik wymaga bezpiecznego przekazania poświadczeń do Concourse-ci. W tym celu w przewodniku przedstawiono integrację Concourse-ci z AWS Secrets Manager.
Integracja Concourse-ci z AWS Secrets Manager
Tutaj znajdziesz dokumentację dotyczącą integracji Concourse-ci z AWS Secrets Manager. Postępuj zgodnie ze wskazówkami podanymi w dokumentacji, aby uruchomić integrację i rozpocząć.
Plik docker-compose.yml, który jest używany do uruchomienia Concourse-ci, wymaga nieznacznej modyfikacji, aby integracja zadziałała. Do domyślnego pliku docker-compose.yml dostarczonego przez Concourse-ci dodaj
CONCOURSE_AWS_SECRETSMANAGER_ACCESS_KEY, CONCOURSE_AWS_SECRETSMANAGER_SECRET_KEY i 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>
Po skonfigurowaniu integracji i uruchomieniu Concourse-ci z włączoną integracją dodaj poniższe klucze tajne do 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
Klucze tajne Bitbucket i Docker mogą wymagać zastąpienia, jeśli nie używasz rozwiązania Bitbucket do zarządzania swoim kodem ani JFrog jako repozytorium Docker. Dostosowanie tych ustawień do indywidualnego zestawu narzędzi pozostawiamy jako ćwiczenie.
Praca z Concourse-ci
Uruchom polecenie docker ps -a przed i po uruchomieniu polecenia docker-compose up -d, aby sprawdzić, czy narzędzie Concourse-ci zostało poprawnie uruchomione.
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
Przejdź pod adres http://localhost:8080/ po uruchomieniu polecenia 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
W tej chwili nie ma zdefiniowanych żadnych pipeline'ów.
Pipeline hello world
Skonfiguruj pipeline hello world, postępując zgodnie z tą dokumentacją Concourse-ci: https://concourse-ci.org/tutorial-hello-world.html. Jest to konieczne, aby przedstawić narzędzie fly CLI i przyzwyczaić się do pracy z Concourse-ci z poziomu wiersza polecenia.
W następnej części pokazano, jak wdrożyć platformę AWS Lambda napisaną w języku Golang w pojedynczym regionie AWS za pomocą Concourse-ci i jak napisać aktualizację zgłoszenia Jira w ramach tego procesu.
Wdrożenie SubmitImage za pomocą Concourse-ci
Wdrożenie SubmitImage Lambda przy użyciu Concourse-ci odbywa się w trzech krokach. Pierwszym krokiem jest napisanie prostego skryptu bash wykorzystującego interfejs API REST Jira Cloud w celu napisania komentarza w zgłoszeniu Jira. Jest to najprostsza integracja, którą możemy utworzyć. Drugim krokiem jest utworzenie obrazu Docker z niezbędnymi narzędziami oraz wdrożenie Golang AWS Lambda. Ostatnim krokiem jest napisanie dwóch plików konfiguracyjnych Concourse-ci. Pierwszy plik konfiguracyjny, parent.yml, monitoruje repozytorium SubmitImage pod kątem nowych gałęzi i przygotowuje nowe pipeline'y w celu wdrożenia commitów z tych gałęzi. Drugi plik konfiguracyjny, child.yml, definiuje zestaw kroków niezbędnych do wdrożenia zmiany.
Krok 1 — aktualizowanie zgłoszeń Jira za pośrednictwem interfejsu API REST
Ten skrypt aktualizacji używa interfejsu API REST platformy Jira Cloud do napisania komentarza do konkretnego zgłoszenia Jira. Istnieje pięć wymaganych parametrów, które należy ustawić za każdym razem, gdy uruchamiany jest skrypt. Elementy jiraUsername, jiraApiToken i workspace są zazwyczaj takie same dla każdego uruchomienia określonego pipeline'u. Z kolei issueKey będzie zależeć od nazwy gałęzi, która jest wdrażana. Najlepszą praktyką Jira jest, aby podczas pracy nad konkretnym zgłoszeniem umieszczać identyfikator zgłoszenia Jira w nazwach gałęzi i komunikatach dotyczących commita. W tym artykule przyjęto założenie, że przestrzegane są najlepsze praktyki, a nazwy gałęzi są tożsame z identyfikatorami zgłoszenia Jira.
Jak znaleźć parametry
Nazwa użytkownika Jira
Nazwa użytkownika Jira to adres e-mail używany do logowania się do systemu Jira.
Token API Jira
Przejdź do opcji Ustawienia konta
Kliknij opcję Bezpieczeństwo.
Kliknij Utwórz tokeny API i zarządzaj nimi
Przestrzeń robocza
Dla następującego adresu URL instancji Jira https://pmmquickstartguides01.atlassian.net/jira/software/projects/IM/boards/1?selectedIssue=IM-203 przestrzeń robocza to pmmquickstartguide01.
Klucz zgłoszenia
Dla następującego adresu URL zgłoszenia Jira https://pmmquickstartguides01.atlassian.net/jira/software/projects/IM/boards/1?selectedIssue=IM-203 klucz zgłoszenia Jira to IM-203. Umieść identyfikator zgłoszenia Jira w komunikatach dotyczących commita i nazwach gałęzi, aby integracja mogła zapisywać aktualizacje we właściwej lokalizacji.
Komentarz
Komentarz może mieć dowolną postać.
Skrypt aktualizacji
Skrypt aktualizacji jest prostym skryptem powłoki bash wykorzystującym punkt końcowy interfejsu API REST komentarza do zgłoszenia Jira. Tutaj znajduje się dokumentacja tego wywołania interfejsu API. Skrypt można zmodyfikować w celu zapewnienia ściślejszej integracji, korzystając z podanego wzorca wykonywania dodatkowych wywołań interfejsu API. Skopiuj ten skrypt do pliku o nazwie concourse-ci-integration.sh i umieść go w repozytorium Bitbucket lub GitHub o nazwie 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 "$@"
Krok 2 — niestandardowy plik Dockerfile
Utwórz niestandardowy plik Dockerfile za pomocą narzędzi potrzebnych do skompilowania i wdrożenia platformy AWS Lambda napisanej w języku Golang. Dockerfile instaluje niektóre narzędzia, a następnie dodaje AWS SAM i Golang. System Git obrazu klonuje skrypt aktualizacji utworzony w kroku 1 z repozytorium Bitbucket. Musisz zastąpić to repozytorium Bitbucket jakimkolwiek repozytorium utworzonym do przechowywania skryptu aktualizacji. Docker kompiluje ten plik Dockerfile i wypycha go do repozytorium 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
Krok 3 — pliki yaml pipeline'u wdrażania Concourse-ci
Utwórz nowe repozytorium o nazwie concourse i umieść w nim dwa pliki. Parent.yml tworzy pipeline do monitorowania repozytorium pod kątem nowych gałęzi, które pasują do wyrażenia regularnego. Wyrażenie regularne (branch_regex), które pasuje do wszystkich gałęzi zaczynających się od IM-, to IM-*. Parent.yml utworzy nowy pipeline za pomocą konfiguracji w pliku child.yml, gdy zostanie utworzona nowa gałąź, która pasuje do wyrażenia regularnego IM-*. Zaktualizuj ten plik, aby wskazywał na Twoją wersję repozytorium SubmitImage. Kod SubmitImage znajduje się tutaj. Skopiuj ten kod z repozytorium do repozytorium z uprawnieniami do zapisu.
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))}
Child.yml definiuje pipeline z czterema krokami. Najpierw uruchamia polecenie sam validate, aby sprawdzić, czy plik template.yml usługi AWS CloudFormation jest prawidłowy. Następnie uruchamia polecenie sam build, aby z pakietu SubmitImage utworzyć artefakt możliwy do wdrożenia. W kolejnym etapie uruchamia polecenie sam deploy, aby wdrożyć zaktualizowany kod SubmitImage w AWS. Na końcu pipeline wywołuje skrypt aktualizacji utworzony w kroku 1, aby napisać komentarz w pasującym zgłoszeniu Jira.
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"]
Uruchamianie pipeline'u nadrzędnego
Uruchom trzy ponizsze polecenia z katalogu z plikem parent.yml. Pierwsze polecenie loguje się do lokalnie uruchomionej instancji Concourse-ci. Drugie polecenie tworzy pipeline o nazwie wm na podstawie konfiguracji w pliku parent.yml. Trzecie polecenie wyłącza wstrzymanie pipeline'u 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
Po uruchomieniu tych trzech poleceń przejdź do klienta internetowego Concourse-ci, aby zobaczyć, czy pipeline wm jest uruchomiony.
Po uruchomieniu polecenia fly set-pipeline z użyciem pliku parent.yml jest tworzony pipeline wm. Ten pipeline monitoruje SubmitImage pod kątem nowych gałęzi funkcji i tworzy pipeline dla każdej gałęzi funkcji pasującej do wyrażenia regularnego w pliku parent.yml.
Kliknij pipeline wm, aby zobaczyć kroki, które są uruchomione. Zwróć uwagę, że krok feature-branches zawiera gałąź IM-61. Jest to jedyna gałąź istniejąca obecnie w SubmitImage, która pasuje do wyrażenia regularnego w pliku parent.yml. Kliknij automatycznie włączony pipeline dev, aby zobaczyć uruchomione przez niego kroki.
Zauważ, że jest tam krok pobierania repozytorium SubmitImage i że gałąź to IM-61. Zwróć też uwagę, że są tam kroki run-sam-validate, run-sam-build, run-sam-deploy i run-update-script.
Po zakończeniu działania pipeline'u dev wróć do zgłoszenia Jira IM-61 i zwróć uwagę, że minutę temu zarejestrowano nowy komentarz, który pasuje do ciągu komentarza z pliku child.yml
Wnioski…
W tym przewodniku pokazano, jak skonfigurować pipeline w celu automatycznego wdrożenia Golang AWS Lambda w pojedynczym regionie AWS za pomocą Concourse-ci. Przedstawiono również, jak używać skryptu powłoki bash do napisania prostej integracji z systemem Jira. Skrypt integracji można znacznie rozszerzyć dzięki szczegółowym informacjom zawartym w dokumentacji interfejsu API REST Atlassian dostępnej tutaj.
Udostępnij ten artykuł
Następny temat
Zalecane lektury
Dodaj te zasoby do zakładek, aby dowiedzieć się więcej na temat rodzajów zespołów DevOps lub otrzymywać aktualności na temat metodyki DevOps w Atlassian.