Skip to content

Commit bd54d6a

Browse files
authored
Add semver versioning and split build/deploy workflows (#99)
* add new actions * build only on PR * fix uses * use local actions for now * split workflows * fix if * fix default values if not on workflow dispatch * rename * ensure pr build not push * code sync * add .github/workflows/_promote-release.yaml * try .github/workflows/reusable/ * move all to .github/workflows * fix duplicated id * rename back to .github/workflows/build-on-main.yaml * disable input on main * test reusable * retry * revert to local files * test deploy * Revert "test deploy" This reverts commit 12ef2d8.
1 parent 3ee7373 commit bd54d6a

File tree

8 files changed

+461
-105
lines changed

8 files changed

+461
-105
lines changed

.github/actions/build-push-images/action.yaml

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,22 @@ inputs:
2020
description: "Path to docker compose file"
2121
required: false
2222
default: "compose.build.yaml"
23-
23+
artifact-dir:
24+
description: "Directory to store build artifacts"
25+
required: false
26+
artifact-name:
27+
description: "Name of the uploaded artifact"
28+
required: false
2429
outputs:
2530
images:
2631
description: "List of built images"
2732
value: ${{ steps.build.outputs.images }}
33+
artifact-dir:
34+
description: "Directory containing build artifacts"
35+
value: ${{ steps.artifacts.outputs.artifact-dir }}
36+
artifact-name:
37+
description: "Name of the uploaded artifact"
38+
value: ${{ inputs.artifact-name }}
2839

2940
runs:
3041
using: composite
@@ -73,3 +84,24 @@ runs:
7384
docker push "${image_name}":latest
7485
done
7586
echo "Push $TAG as new latest completed."
87+
88+
- name: Prepare build artifacts
89+
if: inputs.artifact-dir
90+
id: artifacts
91+
shell: bash
92+
env:
93+
TAG: ${{ inputs.tag }}
94+
REGISTRY: ${{ inputs.registry }}
95+
ARTIFACT_DIR: ${{ inputs.artifact-dir }}
96+
run: |
97+
mkdir -p $ARTIFACT_DIR
98+
envsubst < compose.yaml > $ARTIFACT_DIR/compose.yaml
99+
echo "artifact-dir=$ARTIFACT_DIR" >> $GITHUB_OUTPUT
100+
101+
- name: Upload build artifacts
102+
if: inputs.artifact-dir
103+
uses: actions/upload-artifact@v6
104+
with:
105+
name: ${{ inputs.artifact-name }}
106+
path: ${{ inputs.artifact-dir }}
107+
if-no-files-found: error
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
name: "Calculate Version"
2+
description: "Calculate semantic version from git history and determine if it is a release"
3+
inputs:
4+
release-branch:
5+
description: "Branch name that triggers releases"
6+
required: false
7+
default: "main"
8+
9+
outputs:
10+
version:
11+
description: "Calculated semantic version"
12+
value: ${{ steps.final-version.outputs.version }}
13+
is-release:
14+
description: "Whether this is a release build (true/false)"
15+
value: ${{ steps.check-release.outputs.is-release }}
16+
already-released:
17+
description: "Whether this version has already been released (true/false). If true, further build/publish steps can be skipped."
18+
value: ${{ steps.check-tag.outputs.already-released }}
19+
20+
runs:
21+
using: composite
22+
steps:
23+
- name: Install GitVersion
24+
uses: gittools/actions/gitversion/[email protected]
25+
with:
26+
versionSpec: "6.x"
27+
28+
- name: Create GitVersion config
29+
shell: bash
30+
run: |
31+
CONFIG_FILE="/tmp/GitVersion.yml"
32+
cat > "$CONFIG_FILE" << 'EOF'
33+
assembly-informational-format: "{MajorMinorPatch}-{PreReleaseLabel}-{ShortSha}"
34+
label: "{BranchName:l}"
35+
major-version-bump-message: '\+semver:\s?(breaking|major)'
36+
minor-version-bump-message: '\+semver:\s?(feature|minor)'
37+
patch-version-bump-message: '.*'
38+
no-bump-message: '\+semver:\s?(none|skip)'
39+
branches:
40+
main:
41+
label: main
42+
increment: None
43+
pull-request:
44+
label: pr{Number}
45+
EOF
46+
echo "GITVERSION_CONFIG=$CONFIG_FILE" >> $GITHUB_ENV
47+
echo "Created GitVersion config:"
48+
cat "$CONFIG_FILE"
49+
50+
- name: Determine Version
51+
id: version
52+
uses: gittools/actions/gitversion/[email protected]
53+
with:
54+
configFilePath: ${{ env.GITVERSION_CONFIG }}
55+
56+
- name: Check if release
57+
id: check-release
58+
shell: bash
59+
run: |
60+
CURRENT_BRANCH="${GITHUB_REF#refs/heads/}"
61+
if [ "$CURRENT_BRANCH" = "${{ inputs.release-branch }}" ]; then
62+
echo "is-release=true" >> $GITHUB_OUTPUT
63+
echo "This is a release build from ${{ inputs.release-branch }}"
64+
else
65+
echo "is-release=false" >> $GITHUB_OUTPUT
66+
echo "This is not a release build (current branch: $CURRENT_BRANCH)"
67+
fi
68+
69+
- name: Set final version
70+
id: final-version
71+
shell: bash
72+
run: |
73+
if [ "${{ steps.check-release.outputs.is-release }}" = "true" ]; then
74+
# If on release branch, use major.minor.patch to create new release
75+
VERSION="${{ steps.version.outputs.majorMinorPatch }}"
76+
elif [[ "${GITHUB_REF}" == refs/tags/* ]]; then
77+
# If on tag, return that tag as current version
78+
VERSION="${{ steps.version.outputs.majorMinorPatch }}"
79+
else
80+
# For other branches, use informational version
81+
VERSION="${{ steps.version.outputs.informationalVersion }}"
82+
fi
83+
echo "version=$VERSION" >> $GITHUB_OUTPUT
84+
echo "Final version: $VERSION"
85+
86+
- name: Check if version already released
87+
id: check-tag
88+
shell: bash
89+
run: |
90+
VERSION="${{ steps.final-version.outputs.version }}"
91+
if git rev-parse "v$VERSION" >/dev/null 2>&1; then
92+
echo "already-released=true" >> $GITHUB_OUTPUT
93+
echo "Version $VERSION has already been released. Build will be skipped."
94+
else
95+
echo "already-released=false" >> $GITHUB_OUTPUT
96+
echo "Version $VERSION has not been released yet."
97+
fi
98+
99+
- name: Show version
100+
shell: bash
101+
run: |
102+
echo "Version: ${{ steps.final-version.outputs.version }}"
103+
echo "Is release: ${{ steps.check-release.outputs.is-release }}"
104+
echo "Version already released: ${{ steps.check-tag.outputs.already-released }}"
105+
echo "### Version: ${{ steps.final-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
106+
echo "**Is release:** ${{ steps.check-release.outputs.is-release }}" >> $GITHUB_STEP_SUMMARY
107+
echo "**Version already released:** ${{ steps.check-tag.outputs.already-released }}" >> $GITHUB_STEP_SUMMARY
Lines changed: 34 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Build easytrade on main
1+
name: Build and push easytrade
22
on:
33
push:
44
branches:
@@ -10,12 +10,6 @@ on:
1010
- src/**
1111
- helm/**
1212
workflow_dispatch:
13-
inputs:
14-
run-tests:
15-
description: "Run integration tests after deployment?"
16-
required: false
17-
type: boolean
18-
default: true
1913

2014
workflow_call:
2115
secrets:
@@ -42,39 +36,49 @@ env:
4236
CONTAINER_REGISTRY: europe-docker.pkg.dev/dynatrace-demoability/docker/easytrade
4337
HELM_REGISTRY: oci://europe-docker.pkg.dev/dynatrace-demoability/helm
4438
HELM_CHART_PATH: helm/easytrade
45-
VERSION: 1.2.${{ github.run_number }}
39+
ARTIFACT_DIR: ./release-artifacts/
4640

4741
jobs:
4842
snyk:
49-
uses: ./.github/workflows/snyk.yaml
43+
uses: ./.github/workflows/reusable-snyk.yaml
5044
permissions:
5145
security-events: write
5246
contents: read
5347
actions: read
5448
secrets:
5549
SNYK_API_TOKEN: ${{ secrets.SNYK_API_TOKEN }}
5650

57-
build-easytrade:
51+
calc-version:
52+
uses: ./.github/workflows/reusable-calc-version.yaml
53+
54+
build-push-easytrade:
55+
if: needs.calc-version.outputs.already-released == 'false'
5856
runs-on: ubuntu-24.04
57+
needs: calc-version
58+
outputs:
59+
artifact-dir: ${{ steps.build-and-push.outputs.artifact-dir }}
60+
artifact-name: ${{ steps.build-and-push.outputs.artifact-name }}
5961
steps:
6062
- name: Checkout repository
6163
uses: actions/checkout@v6
6264

63-
- name: Retrieve gar credentials
65+
- name: Login to Google Artifact Registry
6466
run: |
65-
echo "${{ secrets.GAR_CREDENTIALS }}" | docker login -u _json_key_base64 --password-stdin "${{ env.GAR_ADDRESS }}"
67+
echo "${{ secrets.GAR_CREDENTIALS }}" | \
68+
docker login -u _json_key_base64 --password-stdin "${{ env.GAR_ADDRESS }}"
6669
6770
- name: Set application version
6871
uses: ./.github/actions/set-version
6972
with:
70-
version: ${{ env.VERSION }}
73+
version: ${{ needs.calc-version.outputs.version }}
7174

7275
- name: Build and push easytrade to docker repository
76+
id: build-and-push
7377
uses: ./.github/actions/build-push-images
7478
with:
7579
push: true
76-
push-latest: true
77-
tag: ${{ env.VERSION }}
80+
push-latest: ${{ needs.calc-version.outputs.is-release }}
81+
tag: ${{ needs.calc-version.outputs.version }}
7882
registry: ${{ env.CONTAINER_REGISTRY }}
7983

8084
- name: Build and push Helm chart
@@ -83,78 +87,20 @@ jobs:
8387
chart-path: ${{ env.HELM_CHART_PATH }}
8488
push: true
8589
registry-url: oci://europe-docker.pkg.dev/dynatrace-demoability/helm
86-
version: ${{ env.VERSION }}
90+
version: ${{ needs.calc-version.outputs.version }}
8791
credentials: ${{ secrets.GAR_CREDENTIALS }}
8892

89-
deploy-easytrade:
90-
runs-on: ubuntu-24.04
91-
needs: build-easytrade
92-
steps:
93-
- name: Retrieve kubeconfig
94-
run: |
95-
mkdir ~/.kube
96-
echo "${{ secrets.KUBECONFIG }}" > ~/.kube/config
97-
98-
- name: Checkout infrastructure repo
99-
uses: actions/checkout@v6
100-
with:
101-
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
102-
repository: dynatrace/easytrade-infrastructure
103-
path: easytrade-infrastructure
104-
105-
- name: Deploy easytrade
106-
shell: bash
107-
env:
108-
HELM_CHART_VERSION: ${{ env.VERSION }}
109-
BASE_VALUES_FILE: "./helm-values/aws-base.yaml"
110-
OVERRIDES_VALUES_FILE: "./helm-values/aws-staging.yaml"
111-
DRY_RUN: "false"
112-
DEBUG_MODE: "false"
113-
run: ./deploy.sh
114-
working-directory: ${{ github.workspace }}/easytrade-infrastructure
115-
116-
run-tests:
117-
if: ${{ inputs.run-tests == 'true' }}
118-
runs-on: ubuntu-24.04
119-
needs: deploy-easytrade
120-
steps:
121-
- name: Checkout repository
122-
uses: actions/checkout@v6
123-
124-
- name: Retrieve kubeconfig
125-
run: |
126-
mkdir ~/.kube
127-
echo "${{ secrets.KUBECONFIG }}" > ~/.kube/config
128-
129-
- name: Enable test environment
130-
run: |
131-
kubectl -n ${{ env.NAMESPACE }} set env deployment/easytrade-credit-card-order-service WORK_DELAY=10 WORK_RATE=10
132-
kubectl -n ${{ env.NAMESPACE }} set env deployment/easytrade-third-party-service COURIER_DELAY=10 COURIER_RATE=10 MANUFACTURE_DELAY=10 MANUFACTURE_RATE=10
133-
134-
- name: Wait 3 minutes
135-
run: sleep 3m
136-
137-
- name: Order credit card
138-
uses: ./.github/actions/order-credit-card
139-
with:
140-
namespace: ${{ env.NAMESPACE }}
141-
142-
- name: Wait 12 minutes
143-
run: sleep 12m
144-
145-
- name: Check credit card order
146-
uses: ./.github/actions/check-credit-card-order
147-
with:
148-
namespace: ${{ env.NAMESPACE }}
149-
150-
- name: Run validation
151-
uses: ./.github/actions/run-validation
152-
with:
153-
client_id: ${{ secrets.OQR_CLIENT_ID }}
154-
client_secret: ${{ secrets.OQR_CLIENT_SECRET }}
155-
sso_url: ${{ secrets.SSO_URL }}
156-
tenant_url: ${{ secrets.OQR_URL }}
157-
158-
- name: Disable test environment
159-
run: |
160-
kubectl -n ${{ env.NAMESPACE }} rollout undo deployment/easytrade-credit-card-order-service deployment/easytrade-third-party-service
93+
promote:
94+
if: needs.calc-version.outputs.is-release == 'true'
95+
needs:
96+
- calc-version
97+
- build-push-easytrade
98+
permissions:
99+
contents: write
100+
actions: write
101+
uses: ./.github/workflows/reusable-promote-release.yaml
102+
with:
103+
version: ${{ needs.calc-version.outputs.version }}
104+
trigger-deploy: true
105+
artifact-name: ${{ needs.build-push-easytrade.outputs.artifact-name }}
106+
artifact-dir: ${{ needs.build-push-easytrade.outputs.artifact-dir }}
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,34 @@
1-
name: Build easytrade on branch
1+
name: Build easytrade on PR
2+
23
on:
3-
push:
4+
pull_request:
45
branches:
5-
- "**"
6-
- "!main"
7-
paths:
8-
- .github/**
9-
- kubernetes-manifests/**
10-
- skaffold.yaml
11-
- src/**
12-
- helm/**
13-
6+
- main
147
workflow_call:
158
secrets:
169
SNYK_API_TOKEN:
1710
required: true
18-
GAR_CREDENTIALS:
19-
required: true
2011

2112
env:
2213
CONTAINER_REGISTRY: europe-docker.pkg.dev/dynatrace-demoability/docker/easytrade
2314
HELM_CHART_PATH: helm/easytrade
2415

2516
jobs:
2617
snyk:
27-
uses: ./.github/workflows/snyk.yaml
18+
uses: ./.github/workflows/reusable-snyk.yaml
2819
permissions:
2920
security-events: write
3021
contents: read
3122
actions: read
3223
secrets:
3324
SNYK_API_TOKEN: ${{ secrets.SNYK_API_TOKEN }}
3425

26+
calc-version:
27+
uses: ./.github/workflows/reusable-calc-version.yaml
28+
3529
build-easytrade:
3630
runs-on: ubuntu-24.04
31+
needs: calc-version
3732
steps:
3833
- name: Checkout repository
3934
uses: actions/checkout@v6
@@ -42,17 +37,19 @@ jobs:
4237
uses: ./.github/actions/build-push-images
4338
with:
4439
push: false
45-
tag: dev
40+
tag: ${{ needs.calc-version.outputs.version }}
4641
registry: ${{ env.CONTAINER_REGISTRY }}
4742

4843
build-helm-chart:
4944
runs-on: ubuntu-24.04
45+
needs: calc-version
5046
steps:
5147
- name: Checkout repository
52-
uses: actions/checkout@v4
48+
uses: actions/checkout@v6
5349

5450
- name: Build Helm chart
5551
uses: ./.github/actions/build-push-helm
5652
with:
5753
chart-path: ${{ env.HELM_CHART_PATH }}
5854
push: false
55+
version: ${{ needs.calc-version.outputs.version }}

0 commit comments

Comments
 (0)