Skip to content

Commit a6ec31e

Browse files
authored
CI adjustments + NewRelic update (#155)
1 parent d10fba2 commit a6ec31e

21 files changed

Lines changed: 292 additions & 204 deletions

File tree

‎.github/workflows/build-image.yml‎

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
name: Build image
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
image:
7+
description: "Dockerfile path, e.g. alpine/3.24/8.2/Dockerfile."
8+
type: string
9+
required: true
10+
tags:
11+
description: "JSON array of image tags; the first one is the primary tag."
12+
type: string
13+
required: true
14+
publish:
15+
description: "Push the multi-arch image to DockerHub and send the release Slack notification."
16+
type: boolean
17+
default: false
18+
release_sha:
19+
description: "Commit SHA to reference in the notification (the merge commit on master)."
20+
type: string
21+
default: ""
22+
23+
env:
24+
IMAGE_REPO: spryker/php
25+
26+
jobs:
27+
build:
28+
name: build (${{ matrix.arch }})
29+
runs-on: ${{ matrix.runner }}
30+
timeout-minutes: 120
31+
strategy:
32+
fail-fast: true
33+
matrix:
34+
include:
35+
- arch: amd64
36+
platform: linux/amd64
37+
runner: ubuntu-24.04
38+
- arch: arm64
39+
platform: linux/arm64
40+
runner: ubuntu-24.04-arm
41+
42+
steps:
43+
- name: Resolve image key
44+
id: key
45+
env:
46+
IMAGE: ${{ inputs.image }}
47+
run: echo "key=$(dirname "$IMAGE" | tr '/' '-')" >> "$GITHUB_OUTPUT"
48+
49+
- name: Set up Docker Buildx
50+
uses: docker/setup-buildx-action@v4
51+
52+
- name: Login to DockerHub
53+
uses: docker/login-action@v4
54+
with:
55+
username: ${{ secrets.DOCKER_USERNAME }}
56+
password: ${{ secrets.DOCKER_PASSWORD }}
57+
58+
- name: Build and push by digest
59+
id: build
60+
uses: docker/build-push-action@v7
61+
env:
62+
DOCKER_BUILD_RECORD_UPLOAD: false
63+
with:
64+
file: ${{ inputs.image }}
65+
platforms: ${{ matrix.platform }}
66+
outputs: type=image,name=${{ env.IMAGE_REPO }},push-by-digest=true,name-canonical=true,push=${{ inputs.publish }}
67+
68+
- name: Export digest
69+
if: inputs.publish
70+
env:
71+
DIGEST: ${{ steps.build.outputs.digest }}
72+
run: |
73+
if ! [[ "$DIGEST" =~ ^sha256:[0-9a-f]{64}$ ]]; then
74+
echo "::error::Unexpected digest '$DIGEST'"
75+
exit 1
76+
fi
77+
mkdir -p "$RUNNER_TEMP/digests"
78+
echo "$DIGEST" > "$RUNNER_TEMP/digests/${{ matrix.arch }}"
79+
80+
- name: Upload digest
81+
if: inputs.publish
82+
uses: actions/upload-artifact@v7
83+
with:
84+
name: digests-${{ steps.key.outputs.key }}-${{ matrix.arch }}
85+
path: ${{ runner.temp }}/digests/${{ matrix.arch }}
86+
if-no-files-found: error
87+
retention-days: 7
88+
overwrite: true
89+
90+
publish:
91+
name: publish
92+
needs: build
93+
if: inputs.publish
94+
runs-on: ubuntu-24.04
95+
timeout-minutes: 30
96+
env:
97+
IMAGE: ${{ inputs.image }}
98+
TAGS_JSON: ${{ inputs.tags }}
99+
PRIMARY_TAG: ${{ fromJSON(inputs.tags)[0] }}
100+
RELEASE_SHA: ${{ inputs.release_sha || github.sha }}
101+
102+
steps:
103+
- name: Check out repository
104+
uses: actions/checkout@v7
105+
with:
106+
fetch-depth: 2
107+
108+
- name: Set up Docker Buildx
109+
uses: docker/setup-buildx-action@v4
110+
111+
- name: Login to DockerHub
112+
uses: docker/login-action@v4
113+
with:
114+
username: ${{ secrets.DOCKER_USERNAME }}
115+
password: ${{ secrets.DOCKER_PASSWORD }}
116+
117+
- name: Detect previous image and set PREV_COMMIT_HASH
118+
id: previous_commit
119+
run: |
120+
PREV_COMMIT_HASH=$(git rev-parse --verify HEAD^1)
121+
HAS_PREVIOUS=false
122+
if docker buildx imagetools inspect "$PRIMARY_TAG" >/dev/null 2>&1; then HAS_PREVIOUS=true; fi
123+
{
124+
echo "IMAGE_KEY=$(dirname "$IMAGE" | tr '/' '-')"
125+
echo "PREV_COMMIT_HASH=$PREV_COMMIT_HASH"
126+
echo "HAS_PREVIOUS=$HAS_PREVIOUS"
127+
} >> "$GITHUB_ENV"
128+
129+
- name: Re-tag images with previous commit hash
130+
if: env.HAS_PREVIOUS == 'true'
131+
run: |
132+
set -euo pipefail
133+
for IMAGE_TAG in $(jq -r '.[]' <<<"$TAGS_JSON"); do
134+
NEW_TAG="${IMAGE_TAG}-${PREV_COMMIT_HASH}"
135+
if ! docker buildx imagetools inspect "$IMAGE_TAG" >/dev/null 2>&1; then
136+
echo "$IMAGE_TAG is not published yet. Skipping retagging."
137+
continue
138+
fi
139+
# On a re-run the tag may already point to the new image, so keep the existing backup.
140+
if docker buildx imagetools inspect "$NEW_TAG" >/dev/null 2>&1; then
141+
echo "$NEW_TAG already exists. Skipping retagging."
142+
continue
143+
fi
144+
docker buildx imagetools create -t "$NEW_TAG" "$IMAGE_TAG"
145+
echo "Re-tagged image: $NEW_TAG"
146+
done
147+
148+
- name: Download digests
149+
uses: actions/download-artifact@v8
150+
with:
151+
pattern: digests-${{ env.IMAGE_KEY }}-*
152+
path: ${{ runner.temp }}/digests
153+
merge-multiple: true
154+
155+
- name: Create and push multi-arch manifest
156+
working-directory: ${{ runner.temp }}/digests
157+
run: |
158+
set -euo pipefail
159+
for ARCH in amd64 arm64; do
160+
if [ ! -s "$ARCH" ]; then
161+
echo "::error::Missing $ARCH digest"
162+
exit 1
163+
fi
164+
done
165+
TAG_ARGS=()
166+
for IMAGE_TAG in $(jq -r '.[]' <<<"$TAGS_JSON"); do TAG_ARGS+=(-t "$IMAGE_TAG"); done
167+
docker buildx imagetools create "${TAG_ARGS[@]}" "$IMAGE_REPO@$(cat amd64)" "$IMAGE_REPO@$(cat arm64)"
168+
docker buildx imagetools inspect "$PRIMARY_TAG"
169+
170+
- name: Pull image for master branch
171+
run: |
172+
echo "Pulling image for master branch"
173+
docker pull "$PRIMARY_TAG"
174+
175+
- name: Current image report
176+
id: manifest
177+
run: |
178+
bash .github/compare-images.sh "$PRIMARY_TAG" > current-image-report.txt || true
179+
cat current-image-report.txt
180+
181+
- name: Previous image report
182+
if: env.HAS_PREVIOUS == 'true'
183+
run: |
184+
bash .github/compare-images.sh "${PRIMARY_TAG}-${PREV_COMMIT_HASH}" > previous-image-report.txt || true
185+
cat previous-image-report.txt
186+
187+
- name: Run the diff and format output
188+
id: diff
189+
if: env.HAS_PREVIOUS == 'true'
190+
run: bash .github/format-output.sh
191+
192+
- name: Determine change status
193+
id: change_status
194+
run: |
195+
if [ -n "${FORMATTED_DIFF}" ]; then
196+
echo "CHANGE_NOTE=:white_check_mark: Image content changed since the previous release." >> "$GITHUB_ENV"
197+
else
198+
echo "CHANGE_NOTE=:information_source: No content changes detected since the previous release." >> "$GITHUB_ENV"
199+
fi
200+
201+
- name: Fetch Job ID
202+
id: fetch_job_id
203+
continue-on-error: true
204+
env:
205+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
206+
CHECK_RUN_ID: ${{ job.check_run_id }}
207+
run: |
208+
set -euo pipefail
209+
if [ -n "$CHECK_RUN_ID" ]; then
210+
JOB=$(gh api "repos/$GITHUB_REPOSITORY/actions/jobs/$CHECK_RUN_ID")
211+
else
212+
JOB=$(gh api --paginate --slurp "repos/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID/jobs?per_page=100" \
213+
| jq -c --arg image "$IMAGE" \
214+
'[.[].jobs[] | select((.name | contains($image + " / ")) and (.name | endswith(" / publish")))][0]')
215+
fi
216+
JOB_ID=$(jq -r '.id' <<<"$JOB")
217+
MANIFEST_STEP=$(jq -r '.steps[] | select(.name=="Current image report") | .number' <<<"$JOB")
218+
DIFF_STEP=$(jq -r '.steps[] | select(.name=="Run the diff and format output") | .number' <<<"$JOB")
219+
echo "Extracted Job ID: $JOB_ID (manifest step $MANIFEST_STEP, diff step $DIFF_STEP)"
220+
{
221+
echo "job_id=$JOB_ID"
222+
echo "manifest_step=$MANIFEST_STEP"
223+
echo "diff_step=$DIFF_STEP"
224+
} >> "$GITHUB_OUTPUT"
225+
226+
- name: Send Slack Notification
227+
uses: slackapi/slack-github-action@v1.24.0
228+
with:
229+
payload: |
230+
{
231+
"attachments": [
232+
{
233+
"color": "good",
234+
"fields": [
235+
{
236+
"title": "New version of ${{ env.PRIMARY_TAG }} has been published",
237+
"value": "${{ env.CHANGE_NOTE }}\n\nYou can check the:\n- *Manifest*: <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/${{ steps.fetch_job_id.outputs.job_id }}#step:${{ steps.fetch_job_id.outputs.manifest_step }}:1|View Manifest>\n- *Diff*: <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/${{ steps.fetch_job_id.outputs.job_id }}#step:${{ steps.fetch_job_id.outputs.diff_step }}:1|View Diff>\n\nThis version was built out of <https://github.com/${{ github.repository }}/commit/${{ env.RELEASE_SHA }}|${{ env.RELEASE_SHA }}>.",
238+
"short": false
239+
}
240+
]
241+
}
242+
]
243+
}
244+
env:
245+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_CE_RELEASE_WEBHOOK }}
246+
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK

0 commit comments

Comments
 (0)