Skip to content

Commit 42ec1e5

Browse files
committed
Add reusable end-to-end deploy workflows
1 parent ef148d5 commit 42ec1e5

3 files changed

Lines changed: 289 additions & 0 deletions

File tree

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: Deploy to development (reusable)
2+
3+
# Composes build_and_publish_docker_image_to_container_registry.yml and
4+
# update_kubernetes_deployment.yml into a "publish short-sha image and
5+
# update development kustomize overlay" pipeline.
6+
#
7+
# Scope: single-image services deploying via kustomize to an equinor
8+
# infrastructure repository.
9+
10+
on:
11+
workflow_call:
12+
inputs:
13+
registry:
14+
description: "Container registry for development images."
15+
required: true
16+
type: string
17+
image_name:
18+
description: "Image name (e.g. robotics/sara-anonymizer)."
19+
required: true
20+
type: string
21+
infrastructure_repository:
22+
description: "Target infrastructure repository (kustomize)."
23+
required: true
24+
type: string
25+
path_to_dockerfile:
26+
required: false
27+
type: string
28+
default: "Dockerfile"
29+
path_to_context:
30+
required: false
31+
type: string
32+
default: "."
33+
environment_name:
34+
description: "Optional GitHub Environment to gate the deploy on (e.g. 'Development'). Leave empty to disable the gate."
35+
required: false
36+
type: string
37+
default: ""
38+
secrets:
39+
registry_username:
40+
required: true
41+
registry_password:
42+
required: true
43+
deploy_key:
44+
description: "SSH deploy key for the infrastructure repository."
45+
required: true
46+
47+
permissions:
48+
contents: read
49+
packages: write
50+
51+
jobs:
52+
get-short-sha:
53+
name: Compute short-sha tag
54+
runs-on: ubuntu-latest
55+
environment: ${{ inputs.environment_name }}
56+
outputs:
57+
tag: ${{ steps.get-tag.outputs.tag }}
58+
steps:
59+
- id: get-tag
60+
run: echo "tag=dev.$(echo ${{ github.sha }} | cut -c1-8)" >> "$GITHUB_OUTPUT"
61+
62+
publish:
63+
name: Build and publish image
64+
needs: get-short-sha
65+
permissions:
66+
contents: read
67+
packages: write
68+
uses: ./.github/workflows/build_and_publish_docker_image_to_container_registry.yml
69+
with:
70+
registry: ${{ inputs.registry }}
71+
image_name: ${{ inputs.image_name }}
72+
tag: ${{ needs.get-short-sha.outputs.tag }}
73+
path_to_dockerfile: ${{ inputs.path_to_dockerfile }}
74+
path_to_context: ${{ inputs.path_to_context }}
75+
secrets:
76+
registry_username: ${{ secrets.registry_username }}
77+
registry_password: ${{ secrets.registry_password }}
78+
79+
deploy:
80+
name: Update deployment in development
81+
needs: [publish, get-short-sha]
82+
uses: ./.github/workflows/update_kubernetes_deployment.yml
83+
with:
84+
environment: development
85+
registry: ${{ inputs.registry }}
86+
image_name: ${{ inputs.image_name }}
87+
tag: ${{ needs.get-short-sha.outputs.tag }}
88+
author_email: ${{ github.event.head_commit.author.email }}
89+
author_name: ${{ github.event.head_commit.author.name }}
90+
infrastructure_repository: ${{ inputs.infrastructure_repository }}
91+
secrets:
92+
deploy_key: ${{ secrets.deploy_key }}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
name: Deploy to staging (reusable)
2+
3+
# Composes build_and_publish_docker_image_to_container_registry.yml and
4+
# update_kubernetes_deployment.yml into a "publish release image and
5+
# update staging kustomize overlay" pipeline.
6+
#
7+
# Scope: single-image services deploying via kustomize to an equinor
8+
# infrastructure repository. Publishes both `:<tag>` and `:latest`.
9+
10+
on:
11+
workflow_call:
12+
inputs:
13+
registry:
14+
description: "Container registry for staging images."
15+
required: true
16+
type: string
17+
image_name:
18+
description: "Image name (e.g. robotics/sara-anonymizer)."
19+
required: true
20+
type: string
21+
tag:
22+
description: "Release tag to publish and deploy."
23+
required: true
24+
type: string
25+
infrastructure_repository:
26+
required: true
27+
type: string
28+
author_name:
29+
required: true
30+
type: string
31+
path_to_dockerfile:
32+
required: false
33+
type: string
34+
default: "Dockerfile"
35+
path_to_context:
36+
required: false
37+
type: string
38+
default: "."
39+
secrets:
40+
registry_username:
41+
required: true
42+
registry_password:
43+
required: true
44+
deploy_key:
45+
required: true
46+
47+
permissions:
48+
contents: read
49+
packages: write
50+
51+
jobs:
52+
publish:
53+
name: Build and publish image
54+
permissions:
55+
contents: read
56+
packages: write
57+
uses: ./.github/workflows/build_and_publish_docker_image_to_container_registry.yml
58+
with:
59+
registry: ${{ inputs.registry }}
60+
image_name: ${{ inputs.image_name }}
61+
tag: ${{ inputs.tag }}
62+
secondary_tag: latest
63+
path_to_dockerfile: ${{ inputs.path_to_dockerfile }}
64+
path_to_context: ${{ inputs.path_to_context }}
65+
secrets:
66+
registry_username: ${{ secrets.registry_username }}
67+
registry_password: ${{ secrets.registry_password }}
68+
69+
deploy:
70+
name: Update deployment in staging
71+
needs: publish
72+
uses: ./.github/workflows/update_kubernetes_deployment.yml
73+
with:
74+
environment: staging
75+
registry: ${{ inputs.registry }}
76+
image_name: ${{ inputs.image_name }}
77+
tag: ${{ inputs.tag }}
78+
author_name: ${{ inputs.author_name }}
79+
infrastructure_repository: ${{ inputs.infrastructure_repository }}
80+
secrets:
81+
deploy_key: ${{ secrets.deploy_key }}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
name: Promote to production (reusable)
2+
3+
# Reusable "promote to production" workflow.
4+
#
5+
# Reads the tag currently deployed to staging from the infrastructure
6+
# repository's kustomization, copies that image from the staging registry
7+
# to the production registry (both `:tag` and `:latest`), and updates the
8+
# production deployment.
9+
10+
on:
11+
workflow_call:
12+
inputs:
13+
image_name:
14+
description: "Image name, e.g. robotics/sara-anonymizer."
15+
required: true
16+
type: string
17+
staging_registry:
18+
required: true
19+
type: string
20+
production_registry:
21+
required: true
22+
type: string
23+
infrastructure_repository:
24+
required: true
25+
type: string
26+
author_name:
27+
required: true
28+
type: string
29+
secrets:
30+
staging_registry_username:
31+
required: true
32+
staging_registry_password:
33+
required: true
34+
production_registry_username:
35+
required: true
36+
production_registry_password:
37+
required: true
38+
deploy_key:
39+
required: true
40+
41+
permissions:
42+
contents: read
43+
packages: write
44+
45+
jobs:
46+
get-staging-version:
47+
name: Get version currently in staging
48+
runs-on: ubuntu-latest
49+
outputs:
50+
version_tag: ${{ steps.get.outputs.tag }}
51+
steps:
52+
- name: Checkout infrastructure
53+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6
54+
with:
55+
ref: main
56+
repository: ${{ inputs.infrastructure_repository }}
57+
ssh-key: ${{ secrets.deploy_key }}
58+
59+
- name: Read staging tag from kustomization
60+
id: get
61+
run: |
62+
KUSTOMIZATION=k8s_kustomize/overlays/staging/kustomization.yaml
63+
IMAGE_LINE=$(grep -n "newName: ${{ inputs.staging_registry }}/${{ inputs.image_name }}$" "$KUSTOMIZATION" | cut -d: -f1)
64+
if [ -z "$IMAGE_LINE" ]; then
65+
echo "Error: image ${{ inputs.staging_registry }}/${{ inputs.image_name }} not found in $KUSTOMIZATION"
66+
exit 1
67+
fi
68+
TAG_LINE=$((IMAGE_LINE + 1))
69+
VERSION_TAG=$(sed -n "${TAG_LINE}p" "$KUSTOMIZATION" | awk -F': ' '{print $2}' | tr -d ' ')
70+
if [ -z "$VERSION_TAG" ]; then
71+
echo "Error: could not parse newTag on line ${TAG_LINE} of $KUSTOMIZATION"
72+
exit 1
73+
fi
74+
echo "tag=$VERSION_TAG" >> "$GITHUB_OUTPUT"
75+
76+
copy-image-to-production:
77+
name: Copy staging image to production registry
78+
needs: get-staging-version
79+
runs-on: ubuntu-latest
80+
steps:
81+
- name: Log in to staging registry
82+
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4
83+
with:
84+
registry: ${{ inputs.staging_registry }}
85+
username: ${{ secrets.staging_registry_username }}
86+
password: ${{ secrets.staging_registry_password }}
87+
88+
- name: Log in to production registry
89+
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4
90+
with:
91+
registry: ${{ inputs.production_registry }}
92+
username: ${{ secrets.production_registry_username }}
93+
password: ${{ secrets.production_registry_password }}
94+
95+
- name: Copy image (tag + latest) from staging to production
96+
env:
97+
TAG: ${{ needs.get-staging-version.outputs.version_tag }}
98+
run: |
99+
docker buildx imagetools create \
100+
--tag ${{ inputs.production_registry }}/${{ inputs.image_name }}:${TAG} \
101+
--tag ${{ inputs.production_registry }}/${{ inputs.image_name }}:latest \
102+
${{ inputs.staging_registry }}/${{ inputs.image_name }}:${TAG}
103+
104+
deploy:
105+
name: Update deployment in production
106+
needs: [get-staging-version, copy-image-to-production]
107+
uses: ./.github/workflows/update_kubernetes_deployment.yml
108+
with:
109+
environment: production
110+
registry: ${{ inputs.production_registry }}
111+
image_name: ${{ inputs.image_name }}
112+
tag: ${{ needs.get-staging-version.outputs.version_tag }}
113+
author_name: ${{ inputs.author_name }}
114+
infrastructure_repository: ${{ inputs.infrastructure_repository }}
115+
secrets:
116+
deploy_key: ${{ secrets.deploy_key }}

0 commit comments

Comments
 (0)