Skip to content
Merged
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
140 changes: 113 additions & 27 deletions .github/workflows/build-artifact.yml
Original file line number Diff line number Diff line change
Expand Up @@ -186,16 +186,30 @@ jobs:
echo "### 🔧 Remote Trigger Configuration" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**DISABLE_REMOTE_TRIGGER value:** \`${{ vars.DISABLE_REMOTE_TRIGGER }}\`" >> $GITHUB_STEP_SUMMARY
echo "**ENABLE_REMOTE_TRIGGER_USER_DEV value:** \`${{ vars.ENABLE_REMOTE_TRIGGER_USER_DEV }}\`" >> $GITHUB_STEP_SUMMARY
if [ "${{ vars.ENABLE_REMOTE_TRIGGER_USER_DEV }}" != "true" ]; then
echo " - 💡 To enable the GitLab trigger for \`*/dev/*\` branches, set repository variable \`ENABLE_REMOTE_TRIGGER_USER_DEV\` to \`true\` at [Settings → Variables → Actions](https://github.com/${{ github.repository }}/settings/variables/actions)." >> $GITHUB_STEP_SUMMARY
fi
echo "**REMOTE_TRIGGER_NC_VERSION:** \`${{ vars.REMOTE_TRIGGER_NC_VERSION }}\`" >> $GITHUB_STEP_SUMMARY
echo "**REMOTE_TRIGGER_RC_BRANCH:** \`${{ vars.REMOTE_TRIGGER_RC_BRANCH }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Event type:** \`${{ github.event_name }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Branch:** \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "🔧 Remote Trigger Configuration"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "DISABLE_REMOTE_TRIGGER = '${{ vars.DISABLE_REMOTE_TRIGGER }}'"
echo "Event type = '${{ github.event_name }}'"
echo "Branch = '${{ github.ref_name }}'"
echo "DISABLE_REMOTE_TRIGGER = '${{ vars.DISABLE_REMOTE_TRIGGER }}'"
echo "ENABLE_REMOTE_TRIGGER_USER_DEV = '${{ vars.ENABLE_REMOTE_TRIGGER_USER_DEV }}'"
if [ "${{ vars.ENABLE_REMOTE_TRIGGER_USER_DEV }}" != "true" ]; then
echo " 💡 To enable the GitLab trigger for '*/dev/*' branches,"
echo " set repository variable ENABLE_REMOTE_TRIGGER_USER_DEV to 'true' at:"
echo " https://github.com/${{ github.repository }}/settings/variables/actions"
fi
echo "REMOTE_TRIGGER_NC_VERSION = '${{ vars.REMOTE_TRIGGER_NC_VERSION }}'"
echo "REMOTE_TRIGGER_RC_BRANCH = '${{ vars.REMOTE_TRIGGER_RC_BRANCH }}'"
echo "Event type = '${{ github.event_name }}'"
echo "Branch = '${{ github.ref_name }}'"
echo ""

if [ "${{ vars.DISABLE_REMOTE_TRIGGER }}" == "true" ]; then
Expand Down Expand Up @@ -230,6 +244,7 @@ jobs:
# Check if branch matches expected patterns: ionos-dev[-v<major>], ionos-stable[-v<major>], rc/* or */dev/*
VALID_BRANCH_PATTERN='^(ionos-dev|ionos-stable)(-v[0-9]+)?$|^rc/.*$|^[^/]+/dev/.*$'
VALID_BRANCH_DESC="'ionos-dev[-v<major>]', 'ionos-stable[-v<major>]', 'rc/*' or '*/dev/*'"
USER_DEV_PATTERN='^[^/]+/dev/.*$'
if [[ ! "${{ github.ref_name }}" =~ $VALID_BRANCH_PATTERN ]]; then
echo "- ❌ Branch must be ${VALID_BRANCH_DESC} (current: \`${{ github.ref_name }}\`)" >> $GITHUB_STEP_SUMMARY
echo " ❌ Branch is '${{ github.ref_name }}' (must be ${VALID_BRANCH_DESC})"
Expand All @@ -239,6 +254,52 @@ jobs:
echo " ✅ Branch is '${{ github.ref_name }}'"
fi

# This block is the shell twin of the version gate in the
# 'trigger-remote-dev-workflow' if: condition. The two are one rule written
# twice — an edit to either must be mirrored in the other, or this summary
# reports an outcome the pipeline does not produce.
if [[ "${{ github.ref_name }}" =~ $USER_DEV_PATTERN ]]; then
# Not version-gated; governed solely by the ENABLE_REMOTE_TRIGGER_USER_DEV opt-in.
if [ "${{ vars.ENABLE_REMOTE_TRIGGER_USER_DEV }}" == "true" ]; then
echo "- ✅ User-dev branch opt-in (\`ENABLE_REMOTE_TRIGGER_USER_DEV='true'\`)" >> $GITHUB_STEP_SUMMARY
echo " ✅ ENABLE_REMOTE_TRIGGER_USER_DEV='true' — '*/dev/*' trigger is opted in"
else
echo "- ❌ User-dev branch requires \`ENABLE_REMOTE_TRIGGER_USER_DEV='true'\` (current: \`${{ vars.ENABLE_REMOTE_TRIGGER_USER_DEV }}\`)" >> $GITHUB_STEP_SUMMARY
echo "- ℹ️ Build & image push will still run — only QA deployment is skipped" >> $GITHUB_STEP_SUMMARY
echo " ❌ '*/dev/*' branch requires ENABLE_REMOTE_TRIGGER_USER_DEV='true' (current: '${{ vars.ENABLE_REMOTE_TRIGGER_USER_DEV }}')"
echo " ℹ️ Build & image push will still run — only QA deployment is skipped"
WILL_TRIGGER=false
fi
else
# Bare ionos-dev/ionos-stable are always exempt; the ionos-(dev|stable)-v* branches
# must end with REMOTE_TRIGGER_NC_VERSION; all other branches reaching here (rc/*)
# must match REMOTE_TRIGGER_RC_BRANCH exactly — the suffix check must NOT apply to
# rc/* or an RC branch could pass by coincidence of name.
NC_VERSION="${{ vars.REMOTE_TRIGGER_NC_VERSION }}"
RC_BRANCH="${{ vars.REMOTE_TRIGGER_RC_BRANCH }}"
BRANCH="${{ github.ref_name }}"

if [ "$BRANCH" == "ionos-dev" ] || [ "$BRANCH" == "ionos-stable" ]; then
echo "- ✅ Version gate: '$BRANCH' is always exempt" >> $GITHUB_STEP_SUMMARY
echo " ✅ Version gate: '$BRANCH' is always exempt"
elif [ -z "$NC_VERSION" ]; then
echo "- ✅ Version gate: not set — all versions allowed" >> $GITHUB_STEP_SUMMARY
echo " ✅ Version gate: not set — all versions allowed"
elif [[ "$BRANCH" == ionos-dev-v* || "$BRANCH" == ionos-stable-v* ]] && [[ "$BRANCH" == *"$NC_VERSION" ]]; then
echo "- ✅ Version gate: branch \`$BRANCH\` matches \`$NC_VERSION\`" >> $GITHUB_STEP_SUMMARY
echo " ✅ Version gate: branch '$BRANCH' matches '$NC_VERSION'"
elif [ -n "$RC_BRANCH" ] && [ "$BRANCH" == "$RC_BRANCH" ]; then
echo "- ✅ Version gate: branch \`$BRANCH\` matches RC whitelist \`$RC_BRANCH\`" >> $GITHUB_STEP_SUMMARY
echo " ✅ Version gate: branch '$BRANCH' matches RC whitelist '$RC_BRANCH'"
else
echo "- ❌ Version gate: branch \`$BRANCH\` does not match version \`$NC_VERSION\` or RC branch \`$RC_BRANCH\`" >> $GITHUB_STEP_SUMMARY
echo "- ℹ️ Build & image push will still run — only QA deployment is skipped" >> $GITHUB_STEP_SUMMARY
echo " ❌ Version gate: branch '$BRANCH' does not match version '$NC_VERSION' or RC branch '$RC_BRANCH'"
echo " ℹ️ Build & image push will still run — only QA deployment is skipped"
WILL_TRIGGER=false
fi
fi

echo "- ℹ️ All dependent jobs must succeed (checked at job runtime)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY

Expand Down Expand Up @@ -1046,30 +1107,49 @@ jobs:

name: Trigger remote workflow
needs: [build-artifact, upload-to-artifactory]
# Trigger remote build on "ionos-dev|ionos-stable|rc/*|*/dev/*" branch *push* defined in the on:push:branches
# Trigger remote build on "ionos-dev|ionos-stable|ionos-*-v*|rc/*|*/dev/*" branch *push*
# defined in the on:push:branches
# Can be disabled via repository variable 'DISABLE_REMOTE_TRIGGER' (set to 'true' to disable)
# Configure at: https://github.com/IONOS-Productivity/ncw-server/settings/variables/actions
#
# NOTE (NSW-944): the per-major lanes — 'ionos-dev-v*' AND 'ionos-stable-v*' — are deliberately
# absent from the condition below while they DO appear in on:push:branches and in the
# upload-to-artifactory condition. That combination is the Nextcloud-major freeze: a per-major
# integration branch produces build artifacts you can pull with check_release.sh, but can never
# trigger a remote deploy.
# NOTE (NSW-944): the Nextcloud-major freeze lives in repository *variables*, not in this
# condition. The per-major lanes are admitted below and then gated on
# REMOTE_TRIGGER_NC_VERSION, so moving the deployed major is a variable edit rather than a
# workflow edit. Until this change the freeze was hard-coded here as exact-equality arms.
#
# The arms below are exact equality on purpose. 'ionos-dev' does not match 'ionos-dev-v32', so
# the freeze holds for every future major without further edits — do not "tidy" these into
# startsWith(), which would silently start deploying the next major.
# Version-gate: only trigger QA deployment for the whitelisted NC major version.
# Set repository variable 'REMOTE_TRIGGER_NC_VERSION' to the deployed version (e.g. "v32").
# Applies only to 'ionos-dev-v*'/'ionos-stable-v*' branches (checked by suffix); lanes for
# other majors still build & push images but will NOT trigger the remote QA workflow.
# Leave unset (empty) to allow all versions.
# The bare 'ionos-dev'/'ionos-stable' lanes are always exempt from this gate.
# RC-gate: rc/* branches are NOT covered by the NC-version suffix check above — the current
# train 'rc/ncw-7' encodes no major at all, and applying a suffix check to rc/* would let a
# branch pass by coincidence of name. Set 'REMOTE_TRIGGER_RC_BRANCH' to the exact RC branch
# that should trigger QA (e.g. "rc/ncw-7", or "rc/ncw-v32-1" in the current naming era).
# Only one RC at a time; when promoting a new RC, update the variable to the new branch name.
# */dev/* branches bypass the version gate entirely and are controlled solely by repository
# variable 'ENABLE_REMOTE_TRIGGER_USER_DEV' (default off — set to 'true' to let user dev
# branches deploy to QA). They still build and still upload to Artifactory when off.
#
# Widen this only at a cutover, when the deployed major is meant to change. Doing so also
# requires widening the BUILD_TYPE stable arm further down, which is exact-match for the same
# reason; otherwise a newly-admitted ionos-stable-v<N> would deploy as BUILD_TYPE=dev.
# Widening the gate at a cutover also requires widening the BUILD_TYPE stable arm further
# down; otherwise a newly-admitted ionos-stable-v<N> would deploy as BUILD_TYPE=dev.
if: |
always() &&
github.event_name == 'push' &&
(github.ref_name == 'ionos-dev' || github.ref_name == 'ionos-stable' || startsWith(github.ref_name, 'rc/') || contains(github.ref_name, '/dev/')) &&
(github.ref_name == 'ionos-dev' || github.ref_name == 'ionos-stable' ||
startsWith(github.ref_name, 'ionos-dev-v') || startsWith(github.ref_name, 'ionos-stable-v') ||
startsWith(github.ref_name, 'rc/') ||
(contains(github.ref_name, '/dev/') && vars.ENABLE_REMOTE_TRIGGER_USER_DEV == 'true')) &&
needs.build-artifact.result == 'success' &&
needs.upload-to-artifactory.result == 'success' &&
vars.DISABLE_REMOTE_TRIGGER != 'true'
vars.DISABLE_REMOTE_TRIGGER != 'true' &&
(contains(github.ref_name, '/dev/') ||
github.ref_name == 'ionos-dev' || github.ref_name == 'ionos-stable' ||
vars.REMOTE_TRIGGER_NC_VERSION == '' ||
((startsWith(github.ref_name, 'ionos-dev-v') || startsWith(github.ref_name, 'ionos-stable-v')) &&
endsWith(github.ref_name, vars.REMOTE_TRIGGER_NC_VERSION)) ||
github.ref_name == vars.REMOTE_TRIGGER_RC_BRANCH)
steps:
- name: Check prerequisites
run: |
Expand Down Expand Up @@ -1140,27 +1220,28 @@ jobs:
# | ref_name | GITLAB_REF | BUILD_TYPE |
# |------------------|--------------|-------------|
# | ionos-dev | main | dev |
# | ionos-dev-v* | main | dev |
# | ionos-stable | main | stable |
# | ionos-stable-v* | main | stable |
# | rc/* | main | rc |
# | */dev/* | main | dev-* |
#
# The per-major lanes — ionos-dev-v* and ionos-stable-v* — have no rows because they
# never reach this job: the if: condition above matches the unsuffixed names by exact
# equality. That is the freeze. Do not add speculative arms for them here; an
# unreachable arm reads as support that does not exist.
# BUILD_TYPE only says which lane a build came from — which major it carries is
# NC_MAJOR below, so the per-major lanes share their unsuffixed lane's BUILD_TYPE.
# The ref name is forwarded verbatim as well, so the downstream release report can
# name the exact RC or branch and link back to it.
#
# GITLAB_REF stays 'main' for every lane and BUILD_TYPE keeps its existing values —
# both are consumed on the GitLab side, so changing either needs a coordinated change
# there first. NC_MAJOR below is additive and cannot break an existing consumer.

BUILD_TYPE="dev"

# Override build type for the stable branch. Exact match, deliberately unlike the
# upload job's stage-prefix arm, which does accept ionos-stable-v<N>: that job's gate
# admits the per-major lanes and this one does not. Widening the gate at a cutover
# must widen this arm in the same change, or a suffixed stable lane would deploy as
# BUILD_TYPE=dev.
if [ "${{ github.ref_name }}" == "ionos-stable" ]; then
# Override build type for the stable branches. Matches the suffixed form too, the same
# way the upload job's stage-prefix arm does: both jobs now admit the per-major lanes,
# and without this arm a suffixed stable lane would deploy as BUILD_TYPE=dev. The dev
# lanes need no arm — ionos-dev and ionos-dev-v<N> both fall through to the default.
if [[ "${{ github.ref_name }}" == "ionos-stable" || "${{ github.ref_name }}" == ionos-stable-v[0-9]* ]]; then
BUILD_TYPE="stable"
# Override build type for rc/* branches
elif [[ "${{ github.ref_name }}" =~ ^rc/ ]]; then
Expand Down Expand Up @@ -1207,6 +1288,8 @@ jobs:
--form "variables[NC_MAJOR]=${NC_MAJOR}" \
--form "variables[BUILD_ID]=${{ github.run_id }}" \
--form "variables[BUILD_TYPE]=${BUILD_TYPE}" \
--form "variables[GITHUB_REF_NAME]=${{ github.ref_name }}" \
--form "variables[GITHUB_REPOSITORY]=${{ github.repository }}" \
--form "variables[SOURCE_BUILD_URL]=${SOURCE_BUILD_URL}" \
"${{ secrets.GITLAB_TRIGGER_URL }}"; then
TRIGGER_SUCCESS=true
Expand Down Expand Up @@ -1469,6 +1552,9 @@ jobs:
echo ""
echo "### Repository Variables"
echo "DISABLE_REMOTE_TRIGGER: ${{ vars.DISABLE_REMOTE_TRIGGER || 'not set' }}"
echo "ENABLE_REMOTE_TRIGGER_USER_DEV: ${{ vars.ENABLE_REMOTE_TRIGGER_USER_DEV || 'not set' }}"
echo "REMOTE_TRIGGER_NC_VERSION: ${{ vars.REMOTE_TRIGGER_NC_VERSION || 'not set' }}"
echo "REMOTE_TRIGGER_RC_BRANCH: ${{ vars.REMOTE_TRIGGER_RC_BRANCH || 'not set' }}"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

Expand Down
Loading