Skip to content

Add workflow to promote artifacts upon QA-approval#241

Open
seriAlizations wants to merge 2 commits intorc/ncw-4from
ah/dev/promote-qa-approved-artifacts
Open

Add workflow to promote artifacts upon QA-approval#241
seriAlizations wants to merge 2 commits intorc/ncw-4from
ah/dev/promote-qa-approved-artifacts

Conversation

@seriAlizations
Copy link

  • Resolves: #

Summary

TODO

  • ...

Checklist

@printminion-co printminion-co added this to the ncw-4 milestone Feb 12, 2026
@printminion-co printminion-co force-pushed the ah/dev/promote-qa-approved-artifacts branch from da01fa6 to 5e211e0 Compare February 12, 2026 17:02
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a GitHub Actions workflow to promote QA-approved artifacts from the development branch to the stable branch. The workflow ensures that artifacts are promoted without rebuilding, maintaining the exact same commit SHA throughout the process.

Changes:

  • Adds a new workflow that performs a fast-forward merge from ionos-dev to ionos-stable
  • Implements artifact promotion from snapshot repository to release repository in Artifactory
  • Includes verification steps to ensure the SHA exists in the development branch before promotion

Comment on lines 8 to 12
workflow_dispatch:

env:
REGISTRY: ghcr.io
SHA: ${{ github.sha }}
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using github.sha will always reference the commit that triggered the workflow, not the intended artifact commit. Since this is a workflow_dispatch event (manual trigger), you need to add an input parameter to allow users to specify the SHA of the commit they want to promote. Without this, the workflow cannot promote arbitrary QA-approved commits.

Suggested change
workflow_dispatch:
env:
REGISTRY: ghcr.io
SHA: ${{ github.sha }}
workflow_dispatch:
inputs:
sha:
description: 'Commit SHA to promote from ionos-dev to ionos-stable and copy artifacts for'
required: true
type: string
env:
REGISTRY: ghcr.io
SHA: ${{ inputs.sha }}

Copilot uses AI. Check for mistakes.
run: |
git checkout ionos-stable
git fetch origin ionos-stable ionos-dev
#verify SHA is on ionos-dev
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spacing in comment: should be '# verify' with a space after the hash.

Suggested change
#verify SHA is on ionos-dev
# verify SHA is on ionos-dev

Copilot uses AI. Check for mistakes.
id: verify_sha
run: |
git checkout ionos-stable
git fetch origin ionos-stable ionos-dev
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The checkout and fetch operations are redundant. Since the repository is already checked out in the previous step with fetch-depth: 0, you already have all branches and history. You can simplify this to just git checkout ionos-stable and remove the fetch command.

Suggested change
git fetch origin ionos-stable ionos-dev

Copilot uses AI. Check for mistakes.
Comment on lines 75 to 79
if ! jf rt search "ionos-productivity-ncwserver-snapshot/dev/*/$SHA/*.tar.gz"; then
echo "No artifact with SHA $SHA found."
exit 1
else
echo "Artifact found for SHA $SHA"
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The jf rt search command returns success (exit code 0) even when no artifacts are found; it only fails on errors. This means your conditional logic will not work as intended. You need to capture the output and check if any results were returned, or use --fail-no-op flag if available in your JFrog CLI version.

Suggested change
if ! jf rt search "ionos-productivity-ncwserver-snapshot/dev/*/$SHA/*.tar.gz"; then
echo "No artifact with SHA $SHA found."
exit 1
else
echo "Artifact found for SHA $SHA"
RESULTS="$(jf rt search "ionos-productivity-ncwserver-snapshot/dev/*/$SHA/*.tar.gz")"
if [ -z "$RESULTS" ]; then
echo "No artifact with SHA $SHA found."
exit 1
else
echo "Artifact(s) found for SHA $SHA:"
echo "$RESULTS"

Copilot uses AI. Check for mistakes.
Comment on lines 75 to 86
if ! jf rt search "ionos-productivity-ncwserver-snapshot/dev/*/$SHA/*.tar.gz"; then
echo "No artifact with SHA $SHA found."
exit 1
else
echo "Artifact found for SHA $SHA"
fi

- name: Copy artifact to target
id: copy_artifact
run: |
jf rt copy \
"ionos-productivity-ncwserver-snapshot/dev/*/$SHA/*" \
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The source path pattern uses wildcards that could match multiple artifacts if the directory structure allows. Consider adding explicit error handling or validation to ensure only the expected artifact is copied. Additionally, document the expected directory structure in a comment for future maintainers.

Suggested change
if ! jf rt search "ionos-productivity-ncwserver-snapshot/dev/*/$SHA/*.tar.gz"; then
echo "No artifact with SHA $SHA found."
exit 1
else
echo "Artifact found for SHA $SHA"
fi
- name: Copy artifact to target
id: copy_artifact
run: |
jf rt copy \
"ionos-productivity-ncwserver-snapshot/dev/*/$SHA/*" \
# Expected Artifactory layout:
# ionos-productivity-ncwserver-snapshot/
# dev/<branch-name>/$SHA/<artifact-files>
#
# We search for a single .tar.gz artifact for the given SHA and
# derive its containing directory. This avoids using wildcards
# for the branch component when copying to the release repo.
set -e
SEARCH_RESULT=$(jf rt search --format=json --limit=2 "ionos-productivity-ncwserver-snapshot/dev/*/$SHA/*.tar.gz")
MATCH_COUNT=$(echo "$SEARCH_RESULT" | jq '.results | length')
if [ "$MATCH_COUNT" -eq 0 ]; then
echo "No artifact with SHA $SHA found."
exit 1
fi
if [ "$MATCH_COUNT" -gt 1 ]; then
echo "Multiple artifacts found for SHA $SHA; expected exactly one."
echo "$SEARCH_RESULT"
exit 1
fi
ARTIFACT_REPO=$(echo "$SEARCH_RESULT" | jq -r '.results[0].repo')
ARTIFACT_PATH=$(echo "$SEARCH_RESULT" | jq -r '.results[0].path')
# Derive the directory that contains all artifacts for this SHA
ARTIFACT_DIR_PATH=$(dirname "$ARTIFACT_PATH")
ARTIFACT_DIR="$ARTIFACT_REPO/$ARTIFACT_DIR_PATH"
echo "Using artifact directory: $ARTIFACT_DIR"
# Expose the directory as a step output for the copy step
echo "artifact_dir=$ARTIFACT_DIR" >> "$GITHUB_OUTPUT"
- name: Copy artifact to target
id: copy_artifact
run: |
jf rt copy \
"${{ steps.find_artifact.outputs.artifact_dir }}/*" \

Copilot uses AI. Check for mistakes.
upon QA-approval

Signed-off-by: Aliza Held <aliza.held@strato.de>
Signed-off-by: Aliza Held <aliza.held@strato.de>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 5 comments.


permissions:
contents: write

Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workflow performs stateful operations (pushing ionos-stable and copying to the release repo) but doesn’t define a concurrency group. Two manual promotions running at the same time can race (push conflicts, or copying different SHAs into the release location). Add a concurrency group (and usually cancel-in-progress: false) to serialize promotions.

Suggested change
concurrency:
group: promote-artifact
cancel-in-progress: false

Copilot uses AI. Check for mistakes.
Comment on lines +22 to +27
contents: write

jobs:
promote-git:
# Fast-forward merge SHA from ionos-dev into ionos-stable
# (This ensures commit-hash is identical)
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

permissions: contents: write is granted at the workflow level, so both jobs (including the one that uses external secrets for Artifactory) receive a write-capable GITHUB_TOKEN. For least privilege, set workflow permissions to contents: read (or none) and override to contents: write only on the promote-git job that actually pushes.

Suggested change
contents: write
jobs:
promote-git:
# Fast-forward merge SHA from ionos-dev into ionos-stable
# (This ensures commit-hash is identical)
contents: read
jobs:
promote-git:
# Fast-forward merge SHA from ionos-dev into ionos-stable
# (This ensures commit-hash is identical)
permissions:
contents: write

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +19
REGISTRY: ghcr.io
SHA: ${{ inputs.sha }}
ARTIFACTORY_REPOSITORY_SNAPSHOT: ionos-productivity-ncwserver-snapshot
ARTIFACTORY_REPOSITORY_RELEASE: ionos-productivity-ncwserver-release
CACHE_VERSION: v1.0
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

REGISTRY and CACHE_VERSION are defined in env: but are unused in this workflow. Removing unused env vars makes the workflow easier to understand and avoids confusion about whether registry/caching is involved in promotion.

Suggested change
REGISTRY: ghcr.io
SHA: ${{ inputs.sha }}
ARTIFACTORY_REPOSITORY_SNAPSHOT: ionos-productivity-ncwserver-snapshot
ARTIFACTORY_REPOSITORY_RELEASE: ionos-productivity-ncwserver-release
CACHE_VERSION: v1.0
SHA: ${{ inputs.sha }}
ARTIFACTORY_REPOSITORY_SNAPSHOT: ionos-productivity-ncwserver-snapshot
ARTIFACTORY_REPOSITORY_RELEASE: ionos-productivity-ncwserver-release

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +63
else
git push origin HEAD:ionos-stable
fi

Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git merge --ff-only "$SHA" can exit successfully with "Already up to date." when the provided SHA is behind the current ionos-stable head (i.e., SHA is an ancestor of stable). In that case the branch is not moved to the requested SHA, but the workflow still proceeds to promote artifacts for it, breaking the "git SHA == promoted artifact" guarantee. Add an explicit check that origin/ionos-stable is an ancestor of $SHA before merging, or verify after the merge that HEAD equals $SHA and fail otherwise.

Suggested change
else
git push origin HEAD:ionos-stable
fi
fi
# Ensure that the resulting HEAD is exactly the requested SHA.
# This prevents the case where SHA is behind ionos-stable and
# 'git merge --ff-only' reports "Already up to date" without
# moving the branch to $SHA.
HEAD_SHA="$(git rev-parse HEAD)"
if [ "$HEAD_SHA" != "$SHA" ]; then
echo "Error: After merge, HEAD ($HEAD_SHA) does not match requested SHA ($SHA)."
echo "Refusing to push ionos-stable or promote artifacts for a mismatched commit."
exit 1
fi
git push origin HEAD:ionos-stable

Copilot uses AI. Check for mistakes.
Comment on lines +86 to +100
# Expected Artifactory layout:
# ionos-productivity-ncwserver-snapshot/
# dev/<branch-name>/$SHA/<artifact-files>
#
# We search for a single .tar.gz artifact for the given SHA and
# derive its containing directory. This avoids using wildcards
# for the branch component when copying to the release repo.
set -e
SEARCH_RESULT=$(jf rt search --format=json --limit=2 "${{ env.ARTIFACTORY_REPOSITORY_SNAPSHOT }}/dev/*/$SHA/*.tar.gz")
MATCH_COUNT=$(echo "$SEARCH_RESULT" | jq '.results | length')

if [ "$MATCH_COUNT" -eq 0 ]; then
echo "No artifact with SHA $SHA found."
exit 1
fi
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Artifactory search path and expected file type don’t match the upload layout documented/implemented in build-artifact.yml (it uploads a .zip under .../dev/ncw-<version>/<shortSha>/..., not .tar.gz under .../dev/<branch>/$SHA/). As written, this step will not find any artifacts for valid builds. Align the search with the actual snapshot layout (or search by the stored vcs.revision property) and copy the exact matching build output.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants