Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions .github/workflows/promote-artifact.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: Promote QA-approved artifacts to stable branch

# - Takes a commit SHA as input
# - Fast-forward merges it to ionos-stable (no new commits)
# - Promotes the exact artifact from Artifactory (no rebuild)

on:
workflow_dispatch:

env:
REGISTRY: ghcr.io
SHA: ${{ github.sha }}
Comment on lines +8 to +12
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.
ARTIFACTORY_REPOSITORY_SNAPSHOT: ionos-productivity-ncwserver-snapshot
CACHE_VERSION: v1.0

permissions:
contents: write

jobs:
promote-git:
# Fast-forward merge SHA from ionos-dev into ionos-stable
# (This ensures commit-hash is identical)
runs-on: ubuntu-latest
steps:
- name: Checkout server
id: checkout_server
uses: actions/checkout@v5
with:
fetch-depth: 0

- name: Verify SHA is in ionos-dev
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.
#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.
if ! git merge-base --is-ancestor "$SHA" origin/ionos-dev; then
echo "Error: SHA does not exist on ionos-dev: $SHA"
exit 1
fi

- name: Fast-forward merge
id: ff_merge
run: |
# Merge will fail if not possible
if ! git merge --ff-only "$SHA"; then
echo "Fast-forward merge not possible"
exit 1
else
git push origin ionos-stable
fi

promote-artifact:
# Copy specified artifact to the release repo -> No rebuild
# (ionos-productivity-ncwserver-release)
needs: promote-git
runs-on: ubuntu-latest
steps:
- name: Setup JFrog CLI
id: setup_jf
uses: jfrog/setup-jfrog-cli@7c95feb32008765e1b4e626b078dfd897c4340ad # v4.4.1
env:
JF_URL: ${{ secrets.JF_ARTIFACTORY_URL }}
JF_USER: ${{ secrets.JF_ARTIFACTORY_USER }}
JF_ACCESS_TOKEN: ${{ secrets.JF_ACCESS_TOKEN }}

- name: Ping the JF server
run: |
# Ping the server
jf rt ping

- name: Find artifacts matching the SHA
id: find_artifact
run: |
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"
Comment on lines +75 to +79
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.
fi

- name: Copy artifact to target
id: copy_artifact
run: |
jf rt copy \
"ionos-productivity-ncwserver-snapshot/dev/*/$SHA/*" \
Comment on lines +75 to +86
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.
"ionos-productivity-ncwserver-release/$SHA/" \
--flat=false

Loading