11name : mysterybox-bridge-image
22
33on :
4- pull_request :
5- paths :
6- - " services/mysterybox-bridge/webhook/**"
7- - " .github/workflows/mysterybox-bridge-image.yml"
84 push :
9- branches : ["main"]
105 tags :
116 - " mysterybox-bridge-v*"
12- paths :
13- - " services/mysterybox-bridge/webhook/**"
14- - " .github/workflows/mysterybox-bridge-image.yml"
15- workflow_dispatch :
16- inputs :
17- source_ref :
18- description : " Git ref (branch, tag, or SHA) to build"
19- required : false
20- default : " main"
21- type : string
22- release_version :
23- description : " Optional release SemVer (X.Y.Z) to publish X.Y.Z-g<sha> on manual runs"
24- required : false
25- type : string
26- publish_latest :
27- description : " Also publish :latest (recommended only for main)"
28- required : false
29- default : false
30- type : boolean
317
328permissions :
339 contents : read
3410
3511concurrency :
36- group : mysterybox-bridge-image-${{ github.workflow }}-${{ github. ref }}
37- cancel-in-progress : true
12+ group : mysterybox-bridge-image-${{ github.ref }}
13+ cancel-in-progress : false
3814
3915env :
4016 IMAGE_NAME : quay.io/nebius/mysterybox-bridge
4117 WEBHOOK_DIR : services/mysterybox-bridge/webhook
18+ MAIN_BRANCH : main
4219
4320jobs :
4421 test :
5229 uses : actions/checkout@v6
5330 with :
5431 fetch-depth : 0
55- ref : ${{ inputs.source_ref || github.ref }}
5632
5733 - name : Set up Python
5834 uses : actions/setup-python@v6
7753 build-and-push :
7854 name : mysterybox-bridge-build-and-push
7955 runs-on : ubuntu-latest
80- if : github.event_name != 'pull_request'
8156 needs : [test]
8257 environment :
8358 name : mysterybox-image-publish
@@ -86,52 +61,31 @@ jobs:
8661 uses : actions/checkout@v6
8762 with :
8863 fetch-depth : 0
89- ref : ${{ inputs.source_ref || github.ref }}
9064
91- - name : Authorize workflow_dispatch actor
92- if : github.event_name == 'workflow_dispatch'
93- uses : actions/github-script@v8
94- with :
95- script : |
96- const { owner, repo } = context.repo;
97- const username = context.actor;
98- const response = await github.rest.repos.getCollaboratorPermissionLevel({
99- owner,
100- repo,
101- username,
102- });
103- const permission = response.data.permission;
104- core.info(`workflow_dispatch actor '${username}' permission: ${permission}`);
105- if (permission !== "admin") {
106- core.setFailed(
107- `workflow_dispatch publish is restricted to repository admins; actor '${username}' has '${permission}'.`
108- );
109- }
110-
111- - name : Validate workflow_dispatch inputs
112- if : github.event_name == 'workflow_dispatch'
65+ - name : Resolve tagged release metadata
66+ id : release
11367 env :
114- SOURCE_REF : ${{ inputs.source_ref }}
115- RELEASE_VERSION : ${{ inputs.release_version }}
116- PUBLISH_LATEST : ${{ inputs.publish_latest }}
68+ REF_NAME : ${{ github.ref_name }}
11769 run : |
11870 set -euo pipefail
11971
120- if [[ -n "${RELEASE_VERSION}" && ! "${RELEASE_VERSION }" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
121- echo "::error::release_version must match X.Y.Z "
72+ if [[ ! "${REF_NAME }" =~ ^mysterybox-bridge-v( [0-9]+\.[0-9]+\.[0-9]+) $ ]]; then
73+ echo "::error::Tag '${REF_NAME}' must match mysterybox-bridge-vMAJOR.MINOR.PATCH "
12274 exit 1
12375 fi
12476
125- if [[ "${PUBLISH_LATEST}" == "true" && "${SOURCE_REF}" != "main" && "${SOURCE_REF}" != "refs/heads/main" ]]; then
126- echo "::error::publish_latest=true is only allowed with source_ref=main"
127- exit 1
128- fi
77+ echo "tag=${REF_NAME}" >> "$GITHUB_OUTPUT"
78+ echo "version=${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT"
79+ echo "commit=$(git rev-list -n 1 "${REF_NAME}")" >> "$GITHUB_OUTPUT"
12980
130- - name : Resolve source commit
131- id : source
81+ - name : Ensure tag commit belongs to main history
13282 run : |
13383 set -euo pipefail
134- echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
84+ git fetch origin "${MAIN_BRANCH}" --depth=1
85+ if ! git merge-base --is-ancestor "${{ steps.release.outputs.commit }}" "origin/${MAIN_BRANCH}"; then
86+ echo "::error::Tag commit ${{ steps.release.outputs.commit }} is not in origin/${MAIN_BRANCH} history"
87+ exit 1
88+ fi
13589
13690 - name : Set up Docker Buildx
13791 uses : docker/setup-buildx-action@v4
14498 run : |
14599 set -euo pipefail
146100
147- if [ -z "${QUAY_SECRET:-}" ]; then
101+ if [[ -z "${QUAY_SECRET:-}" ] ]; then
148102 echo "::error::Missing required secret QUAY_MYSTERYBOX"
149103 exit 1
150104 fi
@@ -153,9 +107,11 @@ jobs:
153107 echo "username=${QUAY_SECRET%%:*}" >> "$GITHUB_OUTPUT"
154108 echo "password=${QUAY_SECRET#*:}" >> "$GITHUB_OUTPUT"
155109 else
156- username="${QUAY_USERNAME_VAR:-nebius}"
157- echo "::notice::Using QUAY_MYSTERYBOX as token and username '${username}'."
158- echo "::notice::For robot accounts, prefer secret format 'username:token' or set repo variable QUAY_MYSTERYBOX_USERNAME."
110+ username="${QUAY_USERNAME_VAR:-}"
111+ if [[ -z "${username}" ]]; then
112+ echo "::error::Token-only secret QUAY_MYSTERYBOX requires repo variable QUAY_MYSTERYBOX_USERNAME"
113+ exit 1
114+ fi
159115 echo "username=${username}" >> "$GITHUB_OUTPUT"
160116 echo "password=${QUAY_SECRET}" >> "$GITHUB_OUTPUT"
161117 fi
@@ -167,46 +123,19 @@ jobs:
167123 username : ${{ steps.quay_creds.outputs.username }}
168124 password : ${{ steps.quay_creds.outputs.password }}
169125
170- - name : Resolve image tags
171- id : image_tags
126+ - name : Resolve image metadata
127+ id : image
172128 env :
173- EVENT_NAME : ${{ github.event_name }}
174- REF_NAME : ${{ github.ref_name }}
175- REF_TYPE : ${{ github.ref_type }}
176- SHA : ${{ steps.source.outputs.sha }}
177- RELEASE_VERSION : ${{ inputs.release_version }}
178- PUBLISH_LATEST : ${{ inputs.publish_latest }}
129+ COMMIT : ${{ steps.release.outputs.commit }}
130+ VERSION : ${{ steps.release.outputs.version }}
179131 run : |
180132 set -euo pipefail
181133
182- short_sha="${SHA::7}"
183- tags="${IMAGE_NAME}:sha-${short_sha}"
184-
185- if [[ "${EVENT_NAME}" == "workflow_dispatch" ]]; then
186- if [[ "${PUBLISH_LATEST}" == "true" ]]; then
187- tags="${tags}"$'\n'"${IMAGE_NAME}:latest"
188- fi
189- if [[ -n "${RELEASE_VERSION}" ]]; then
190- tags="${tags}"$'\n'"${IMAGE_NAME}:${RELEASE_VERSION}-g${short_sha}"
191- fi
192- else
193- if [[ "${REF_TYPE}" == "branch" && "${REF_NAME}" == "main" ]]; then
194- tags="${tags}"$'\n'"${IMAGE_NAME}:latest"
195- fi
196-
197- if [[ "${REF_TYPE}" == "tag" ]]; then
198- if [[ "${REF_NAME}" =~ ^mysterybox-bridge-v([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
199- semver="${BASH_REMATCH[1]}"
200- tags="${tags}"$'\n'"${IMAGE_NAME}:${semver}"
201- tags="${tags}"$'\n'"${IMAGE_NAME}:${semver}-g${short_sha}"
202- else
203- echo "::error::Tag '${REF_NAME}' must match mysterybox-bridge-vMAJOR.MINOR.PATCH"
204- exit 1
205- fi
206- fi
207- fi
134+ short_sha="${COMMIT::7}"
135+ tags="${IMAGE_NAME}:sha-${short_sha}"$'\n'"${IMAGE_NAME}:${VERSION}"$'\n'"${IMAGE_NAME}:${VERSION}-g${short_sha}"
208136
209137 {
138+ echo "package_version=${VERSION}"
210139 echo "tags<<EOF"
211140 echo "${tags}"
212141 echo "EOF"
@@ -220,14 +149,17 @@ jobs:
220149 file : ${{ env.WEBHOOK_DIR }}/Dockerfile
221150 push : true
222151 provenance : false
223- tags : ${{ steps.image_tags.outputs.tags }}
152+ tags : ${{ steps.image.outputs.tags }}
153+ build-args : |
154+ MYSTERYBOX_BRIDGE_WEBHOOK_VERSION=${{ steps.image.outputs.package_version }}
224155 cache-from : type=gha
225156 cache-to : type=gha,mode=max
226157
227158 - name : Write publish manifest
228159 env :
229- TAGS : ${{ steps.image_tags .outputs.tags }}
160+ TAGS : ${{ steps.image .outputs.tags }}
230161 IMAGE_DIGEST : ${{ steps.build.outputs.digest }}
162+ PACKAGE_VERSION : ${{ steps.image.outputs.package_version }}
231163 run : |
232164 set -euo pipefail
233165 tags_json="$(printf '%s\n' "${TAGS}" | jq -R -s -c 'split("\n") | map(select(length > 0))')"
@@ -236,7 +168,10 @@ jobs:
236168 --arg event "${GITHUB_EVENT_NAME}" \
237169 --arg ref "${GITHUB_REF}" \
238170 --arg ref_name "${GITHUB_REF_NAME}" \
239- --arg sha "${{ steps.source.outputs.sha }}" \
171+ --arg tag "${{ steps.release.outputs.tag }}" \
172+ --arg version "${{ steps.release.outputs.version }}" \
173+ --arg sha "${{ steps.release.outputs.commit }}" \
174+ --arg package_version "${PACKAGE_VERSION}" \
240175 --arg digest "${IMAGE_DIGEST}" \
241176 --arg run_id "${GITHUB_RUN_ID}" \
242177 --arg run_attempt "${GITHUB_RUN_ATTEMPT}" \
@@ -248,7 +183,10 @@ jobs:
248183 event: $event,
249184 ref: $ref,
250185 ref_name: $ref_name,
186+ tag: $tag,
187+ version: $version,
251188 sha: $sha,
189+ package_version: $package_version,
252190 tags: $tags,
253191 digest: $digest,
254192 run_id: $run_id,
@@ -264,20 +202,22 @@ jobs:
264202
265203 - name : Publish run summary
266204 env :
267- TAGS : ${{ steps.image_tags .outputs.tags }}
205+ TAGS : ${{ steps.image .outputs.tags }}
268206 IMAGE_DIGEST : ${{ steps.build.outputs.digest }}
207+ PACKAGE_VERSION : ${{ steps.image.outputs.package_version }}
269208 run : |
209+ set -euo pipefail
270210 {
271211 echo "### mysterybox-bridge image publish"
272212 echo ""
273- echo "- Actor : \`${GITHUB_ACTOR }\`"
274- echo "- Event : \`${GITHUB_EVENT_NAME }\`"
275- echo "- Ref : \`${GITHUB_REF }\`"
276- echo "- Commit : \`${{ steps.source.outputs.sha } }\`"
213+ echo "- Tag : \`${{ steps.release.outputs.tag } }\`"
214+ echo "- Version : \`${{ steps.release.outputs.version } }\`"
215+ echo "- Commit : \`${{ steps.release.outputs.commit } }\`"
216+ echo "- Package version : \`${PACKAGE_VERSION }\`"
277217 echo "- Digest: \`${IMAGE_DIGEST}\`"
278218 echo ""
279219 echo "#### Tags"
280220 while IFS= read -r tag; do
281- [ -n "${tag}" ] && echo "- \`${tag}\`"
221+ [[ -n "${tag}" ] ] && echo "- \`${tag}\`"
282222 done <<< "${TAGS}"
283223 } >> "$GITHUB_STEP_SUMMARY"
0 commit comments