Skip to content

IONOS(ci): forward the source ref name to the remote trigger (HDNEXT-… #1181

IONOS(ci): forward the source ref name to the remote trigger (HDNEXT-…

IONOS(ci): forward the source ref name to the remote trigger (HDNEXT-… #1181

name: HiDrive Next Build
# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
# SPDX-FileCopyrightText: 2024 STRATO AG
# SPDX-License-Identifier: AGPL-3.0-or-later
# The HiDrive Next source is packaged as a container image.
# This is a workaround because releases can not be created without tags
# and we want to be able to create snapshots from branches.
on:
pull_request:
paths:
- '.github/workflows/**'
- 'src/**'
- 'apps/**'
- 'apps/**/appinfo/info.xml'
- 'apps-custom/**'
- 'apps-external/**'
- 'IONOS'
- 'package.json'
- 'package-lock.json'
- 'themes/**'
- 'lib/**'
- 'tsconfig.json'
- '**.js'
- '**.ts'
- '**.vue'
- '.gitmodules'
push:
# One converged list, identical on every branch. GitHub evaluates this block
# from the pushed branch's own copy, so the list must cover every live lane:
# the per-major globs, the legacy unsuffixed lanes (retired later), the trains
# in both naming eras, and user dev branches.
branches:
- 'ionos-dev-v*'
- 'ionos-stable-v*'
- ionos-dev
- ionos-stable
- 'rc/**'
- '*/dev/*'
# Concurrency group is intentionally shared between push and pull_request runs
# of the same source branch, so a `*/dev/*` branch with an open PR does not
# produce two parallel runs. Protected lanes (ionos-dev*/ionos-stable*/rc/*) use a
# unique-per-run-id key so consecutive pushes never cancel each other.
concurrency:
group: >-
${{ github.workflow }}-${{
(
startsWith(github.ref, 'refs/heads/ionos-dev') ||
startsWith(github.ref, 'refs/heads/ionos-stable') ||
startsWith(github.ref, 'refs/heads/rc/')
) && github.run_id ||
(github.head_ref || github.ref_name)
}}
cancel-in-progress: true
env:
TARGET_PACKAGE_NAME: hidrive-next.zip
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
ARTIFACTORY_REPOSITORY_SNAPSHOT: ionos-productivity-hdnext-snapshot
# ┌─ NC MAJOR VERSION ──────────────────────────────────────────────────────┐
# │ Branch-name version suffix (e.g. "v30" -> ionos-dev-v30/ionos-stable-v30).│
# │ Kept in the workflow file (not a repo variable) so each branch can carry │
# │ its own version. Used directly in step run: scripts via env.NC_BRANCH_VERSION.
# │ │
# │ GitHub Actions does NOT allow env/vars in `on:`, `concurrency:` or │
# │ job-level `if:`, so the value is ALSO hardcoded in these spots — bump │
# │ them together with the value below: │
# │ - on.push.branches (ionos-dev-v30 / ionos-stable-v30) │
# │ - concurrency.group fromJson (refs/heads/ionos-dev-v30 / ...-stable-v30)│
# │ - upload-to-artifactory if: (github.ref_name checks) │
# │ - push-to-ghcr.io if: (github.ref_name checks) │
# │ - trigger-remote-dev if: (github.ref_name checks) │
# └───────────────────────────────────────────────────────────────────────────┘
NC_BRANCH_VERSION: v31
permissions:
contents: read
jobs:
prepare-matrix:
runs-on: ubuntu-latest
permissions:
contents: read
actions: read
steps:
- name: Check configuration
run: |
echo "### 🔧 Remote Trigger Configuration" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**DISABLE_REMOTE_TRIGGER:** \`${{ vars.DISABLE_REMOTE_TRIGGER }}\`" >> $GITHUB_STEP_SUMMARY
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 "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
echo "⚠️ Remote trigger is DISABLED"
echo " The 'trigger-remote-dev-workflow' job will be SKIPPED"
echo "**Status:** ⚠️ Remote trigger is **DISABLED**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The \`trigger-remote-dev-workflow\` job will be skipped." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "To enable, delete the variable or set it to a value other than 'true' at:" >> $GITHUB_STEP_SUMMARY
echo "https://github.com/${{ github.repository }}/settings/variables/actions" >> $GITHUB_STEP_SUMMARY
else
echo "✅ Remote trigger is ENABLED"
echo " Checking if trigger conditions are met..."
echo "**Status:** ✅ Remote trigger is **ENABLED**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
WILL_TRIGGER=true
echo "**Trigger Conditions Check:**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "${{ github.event_name }}" != "push" ]; then
echo "- ❌ Event must be 'push' (current: \`${{ github.event_name }}\`)" >> $GITHUB_STEP_SUMMARY
echo " ❌ Event type is '${{ github.event_name }}' (must be 'push')"
WILL_TRIGGER=false
else
echo "- ✅ Event is 'push'" >> $GITHUB_STEP_SUMMARY
echo " ✅ Event type is 'push'"
fi
USER_DEV_PATTERN='^[^/]+/dev/.*$'
if [[ "${{ github.ref_name }}" =~ $USER_DEV_PATTERN ]]; then
# */dev/* branches bypass the version gate entirely — they're controlled solely
# by ENABLE_REMOTE_TRIGGER_USER_DEV, matching the real job `if:` condition.
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 " ❌ '*/dev/*' branch requires ENABLE_REMOTE_TRIGGER_USER_DEV='true' (current: '${{ vars.ENABLE_REMOTE_TRIGGER_USER_DEV }}')"
WILL_TRIGGER=false
fi
else
# Version gate check: 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 it
# could match by coincidence of name.
NC_VERSION="${{ vars.REMOTE_TRIGGER_NC_VERSION }}"
RC_BRANCH="${{ vars.REMOTE_TRIGGER_RC_BRANCH }}"
BRANCH="${{ github.ref_name }}"
if [ -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 " ❌ 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"
echo "- ℹ️ Build & image push will still run — only QA deployment is skipped" >> $GITHUB_STEP_SUMMARY
WILL_TRIGGER=false
fi
fi
echo "- ℹ️ All dependent jobs must succeed (checked at job runtime)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "$WILL_TRIGGER" = "true" ]; then
echo "**Expected:** The \`trigger-remote-dev-workflow\` job **WILL RUN** (if all dependent jobs succeed)." >> $GITHUB_STEP_SUMMARY
echo "🎯 Expected: trigger-remote-dev-workflow job WILL RUN (if all dependent jobs succeed)"
else
echo "**Expected:** The \`trigger-remote-dev-workflow\` job **WILL BE SKIPPED** due to unmet conditions above." >> $GITHUB_STEP_SUMMARY
echo "⏭️ Expected: trigger-remote-dev-workflow job WILL BE SKIPPED"
fi
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
hidrive-next-build:
runs-on: ubuntu-latest
needs: [prepare-matrix]
if: |
always() &&
needs.prepare-matrix.result == 'success'
permissions:
contents: read
outputs:
NC_VERSION: ${{ steps.get_nc_version.outputs.NC_VERSION }}
name: hidrive-next-build
steps:
- name: Checkout server
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
with:
submodules: true
- name: Set up node with version from package.json's engines
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: "package.json"
- name: Install Dependencies
run: sudo apt-get update && sudo apt-get install -y make zip unzip
- name: Print dependencies versions
run: make --version && node --version && npm --version
- name: Setup PHP with PECL extension
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # 2.31.1
with:
tools: composer:v2
extensions: gd, zip, curl, xml, xmlrpc, mbstring, sqlite, xdebug, pgsql, intl, imagick, gmp, apcu, bcmath, redis, soap, imap, opcache
env:
runner: self-hosted
- name: Print PHP install
run: php -i && php -m
- name: Build Nextcloud
run: make -f IONOS/Makefile build_nextcloud
- name: Install dependencies & build simplesettings app
env:
CYPRESS_INSTALL_BINARY: 0
PUPPETEER_SKIP_DOWNLOAD: true
run: make -f IONOS/Makefile build_simplesettings_app
- name: Install dependencies & build viewer app
env:
CYPRESS_INSTALL_BINARY: 0
PUPPETEER_SKIP_DOWNLOAD: true
run: make -f IONOS/Makefile build_viewer_app
- name: Install dependencies & build richdocuments app
run: make -f IONOS/Makefile build_richdocuments_app
- name: Install dependencies & build user_oidc app
env:
CYPRESS_INSTALL_BINARY: 0
PUPPETEER_SKIP_DOWNLOAD: true
run: make -f IONOS/Makefile build_user_oidc_app
- name: Install dependencies for external apps nc_ionos_processes
run: make -f IONOS/Makefile build_nc_ionos_processes_app
- name: Build Custom CSS
run: make -f IONOS/Makefile build_nc_theming_app
- name: Install dependencies & build IONOS theme custom elements
env:
CYPRESS_INSTALL_BINARY: 0
PUPPETEER_SKIP_DOWNLOAD: true
run: make -f IONOS/Makefile build_nc-ionos-theme_app
- name: Install and build notify_push app
run: make -f IONOS/Makefile build_notify_push_app
- name: Add config partials
run: make -f IONOS/Makefile add_config_partials
# IONOS Customization: Inject build number for production traceability
# This is specific to IONOS HiDrive Next and not part of upstream Nextcloud
- name: Inject build number
run: |
echo "${{ github.run_number }}" > .buildnumber
echo "✅ Build number injected: ${{ github.run_number }}"
echo "📄 File created: .buildnumber"
cat .buildnumber
- name: Zip dependencies
run: make -f IONOS/Makefile zip_dependencies TARGET_PACKAGE_NAME=${{ env.TARGET_PACKAGE_NAME }}
- name: Get NC version
id: get_nc_version
continue-on-error: false
run: |
NC_VERSION=$(jq -r '.ncVersion' version.json)
echo "NC_VERSION: $NC_VERSION"
if [ -z "$NC_VERSION" ]; then
echo "NC_VERSION is empty"
exit 1
fi
echo "NC_VERSION=$NC_VERSION" >> $GITHUB_OUTPUT
- name: Upload artifact result for job hidrive-next-build
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
retention-days: 30
name: hidrive_next_build_artifact
path: ${{ env.TARGET_PACKAGE_NAME }}
- name: Show changes on failure
if: failure()
run: |
git status
git --no-pager diff
exit 1 # make it red to grab attention
upload-to-artifactory:
runs-on: self-hosted
# Upload the artifact to the Artifactory repository on PR *OR* on any ionos-dev-vXX / ionos-stable-vXX / rc/* branch push defined in on:push:branches
# NOTE: ionos-dev-v30 / ionos-stable-v30 are NC_BRANCH_VERSION literals —
# env/vars are not allowed in a job-level `if:` (see env block).
if: |
always() &&
(github.event_name == 'pull_request' || startsWith(github.ref_name, 'ionos-dev-') || startsWith(github.ref_name, 'ionos-stable-') || startsWith(github.ref_name, 'rc/')) &&
needs.prepare-matrix.result == 'success' &&
needs.hidrive-next-build.result == 'success'
name: Push to artifactory
needs: [prepare-matrix, hidrive-next-build]
outputs:
ARTIFACTORY_LAST_BUILD_PATH: ${{ steps.artifactory_upload.outputs.ARTIFACTORY_LAST_BUILD_PATH }}
env:
BUILD_NAME: "hidrive_next-snapshot"
steps:
- name: Check prerequisites
run: |
echo "Checking if required secrets are set..."
error_count=0
if [ -z "${{ secrets.JF_ARTIFACTORY_URL }}" ]; then
echo "::error::JF_ARTIFACTORY_URL secret is not set"
error_count=$((error_count + 1))
fi
if [ -z "${{ secrets.JF_ARTIFACTORY_USER }}" ]; then
echo "::error::JF_ARTIFACTORY_USER secret is not set"
error_count=$((error_count + 1))
fi
if [ -z "${{ secrets.JF_ACCESS_TOKEN }}" ]; then
echo "::error::JF_ACCESS_TOKEN secret is not set"
error_count=$((error_count + 1))
fi
if [ $error_count -ne 0 ]; then
echo "::error::Required secrets are not set. Aborting."
exit 1
fi
# Checkout is required to access the local composite action at ./.github/actions/get-job-data
- name: Checkout repository
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
with:
fetch-depth: 1
- name: Download artifact zip
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: hidrive_next_build_artifact
# This action sets up the JFrog CLI with the Artifactory URL and access token
- uses: jfrog/setup-jfrog-cli@1641575d87647fb969c0545f0b6a76873e328b7c # v5.0.0
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: Get Job data
id: get_job_data
continue-on-error: true
uses: ./.github/actions/get-job-data
with:
job-name: 'Push to artifactory'
github-token: ${{ github.token }}
repository: ${{ github.repository }}
run-id: ${{ github.run_id }}
- name: Upload build to artifactory
id: artifactory_upload
run: |
# Artifactory Build Storage Structure:
# | Branch/Event | Stage Prefix | Artifact Path |
# |------------------|------------------|------------------------------------------------------------------------------|
# | Pull Request | pr | pr/hidrive-next-pr-<number>.zip |
# | ionos-dev-v30 | dev | dev/hidrive-next-<ncVersion>/<shortSha>/hidrive-next-<ncVersion>.zip |
# | ionos-stable-v30 | stable | stable/hidrive-next-<ncVersion>/<shortSha>/hidrive-next-<ncVersion>.zip |
# | rc/* | <ref-name> | rc/<branch>/hidrive-next-<ncVersion>/<shortSha>/hidrive-next-<ncVersion>.zip |
# | */dev/* | devs/<prefix> | devs/<prefix>/hidrive-next-<ncVersion>/<shortSha>/hidrive-next-<ncVersion>.zip |
ARTIFACTORY_STAGE_PREFIX="dev"
if [ -n "${{ github.event.pull_request.number }}" ]; then
ARTIFACTORY_STAGE_PREFIX="pr"
elif [ "${{ github.ref_name }}" == "ionos-stable-${{ env.NC_BRANCH_VERSION }}" ]; then
ARTIFACTORY_STAGE_PREFIX="stable"
elif [[ "${{ github.ref_name }}" =~ ^rc/.*$ ]]; then
ARTIFACTORY_STAGE_PREFIX="${{ github.ref_name }}"
elif [[ "${{ github.ref_name }}" =~ ^.*/dev/.*$ ]]; then
BRANCH_PREFIX=$(echo "${{ github.ref_name }}" | sed 's|/.*||' | sed 's/[^A-Za-z0-9._-]/-/g')
ARTIFACTORY_STAGE_PREFIX="devs/${BRANCH_PREFIX}"
fi
export PATH_TO_DIRECTORY="${{ env.ARTIFACTORY_REPOSITORY_SNAPSHOT }}/${ARTIFACTORY_STAGE_PREFIX}"
if [ -n "${{ github.event.pull_request.number }}" ]; then
# PR uploads keep the flat layout (one slot per PR number, top-level pr/)
PATH_TO_FILE="hidrive-next-pr-${{ github.event.pull_request.number }}.zip"
else
# branch uploads nest under <ncVersion>/<shortSha>/ to preserve every build
SHORT_SHA="${{ github.sha }}"
SHORT_SHA="${SHORT_SHA:0:7}"
NC_VERSION="${{ needs.hidrive-next-build.outputs.NC_VERSION }}"
PATH_TO_FILE="hidrive-next-${NC_VERSION}/${SHORT_SHA}/hidrive-next-${NC_VERSION}.zip"
fi
export PATH_TO_LATEST_ARTIFACT="${PATH_TO_DIRECTORY}/${PATH_TO_FILE}"
JFROG_PROPS_LIST=()
JFROG_PROPS_LIST+=("build.nc_version=${{ needs.hidrive-next-build.outputs.NC_VERSION }}")
JFROG_PROPS_LIST+=("vcs.branch=${{ github.ref }}")
JFROG_PROPS_LIST+=("vcs.revision=${{ github.sha }}")
JOB_URL="${{ steps.get_job_data.outputs.job_html_url }}"
if [ -n "$JOB_URL" ]; then
JFROG_PROPS_LIST+=("job.html_url=${JOB_URL}")
fi
JFROG_PROPS=$(IFS=';'; printf '%s' "${JFROG_PROPS_LIST[*]}")
# Upload with retry logic (3 attempts with exponential backoff: 10s, 20s)
MAX_ATTEMPTS=3
ATTEMPT=1
UPLOAD_SUCCESS=false
DELAY_SEC=10
while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
echo "Upload attempt $ATTEMPT of $MAX_ATTEMPTS..."
if jf rt upload "${{ env.TARGET_PACKAGE_NAME }}" \
--build-name "${{ env.BUILD_NAME }}" \
--build-number ${{ github.run_number }} \
--target-props "$JFROG_PROPS" \
$PATH_TO_LATEST_ARTIFACT; then
UPLOAD_SUCCESS=true
echo "✅ Upload successful on attempt $ATTEMPT"
break
else
echo "⚠️ Upload attempt $ATTEMPT failed"
if [ $ATTEMPT -lt $MAX_ATTEMPTS ]; then
echo "Waiting $DELAY_SEC seconds before retry..."
sleep $DELAY_SEC
DELAY_SEC=$((DELAY_SEC * 2))
fi
fi
ATTEMPT=$((ATTEMPT + 1))
done
if [ "$UPLOAD_SUCCESS" != "true" ]; then
echo "❌ Upload failed after $MAX_ATTEMPTS attempts"
exit 1
fi
echo "ARTIFACTORY_LAST_BUILD_PATH=${PATH_TO_LATEST_ARTIFACT}" >> $GITHUB_OUTPUT
- name: Show changes on failure
if: failure()
run: |
git status
git --no-pager diff
exit 1 # make it red to grab attention
hidirve-next-artifact-to-ghcr_io:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
name: Push artifact to ghcr.io
needs: [prepare-matrix, hidrive-next-build]
# NOTE: ionos-dev-v30 / ionos-stable-v30 are NC_BRANCH_VERSION literals —
# env/vars are not allowed in a job-level `if:` (see env block).
if: |
always() &&
(github.event_name == 'pull_request' || startsWith(github.ref_name, 'ionos-dev-') || startsWith(github.ref_name, 'ionos-stable-')) &&
needs.prepare-matrix.result == 'success' &&
needs.hidrive-next-build.result == 'success'
steps:
- name: Download artifact zip
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: hidrive_next_build_artifact
- name: Log in to the Container registry
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
- name: Create Dockerfile
run: |
cat >Dockerfile << EOF
FROM busybox as builder
COPY ./${{ env.TARGET_PACKAGE_NAME }} /
WORKDIR /builder
RUN unzip /${{ env.TARGET_PACKAGE_NAME }} -d /builder
FROM scratch
WORKDIR /app
VOLUME /app
COPY --from=builder /builder /app
EOF
- name: Build and push Docker image
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Show changes on failure
if: failure()
run: |
exit 1 # make it red to grab attention
trigger-remote-dev-workflow:
runs-on: self-hosted
name: Trigger remote workflow
needs: [ hidrive-next-build, upload-to-artifactory ]
# Trigger remote build on "ionos-dev|ionos-stable|rc/*|*/dev/*" branch *push* defined in on:push:branches
# Can be disabled via repository variable 'DISABLE_REMOTE_TRIGGER' (set to 'true' to disable).
# Version-gate: only trigger QA deployment for the whitelisted NC major version.
# Set repo variable 'REMOTE_TRIGGER_NC_VERSION' to the current release version (e.g. "v30").
# Only 'ionos-dev-v*'/'ionos-stable-v*' branches are subject to this gate (matched by
# prefix), and among those, only an exact suffix match on REMOTE_TRIGGER_NC_VERSION passes;
# a same-prefix branch for a different version (e.g. 'ionos-dev-v31' when the variable is
# set to "v33") will still build & push images but will NOT trigger the remote QA workflow.
# Leave unset (empty) to allow all versions.
# RC-gate: rc/* branches carry no version suffix and are NOT covered by the NC-version
# suffix check above, so set 'REMOTE_TRIGGER_RC_BRANCH' to the exact RC branch that should
# trigger QA (e.g. "rc/web-3.5"). 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 and are controlled solely by ENABLE_REMOTE_TRIGGER_USER_DEV.
# Configure at: https://github.com/IONOS-Productivity/nc-server/settings/variables/actions
if: |
always() &&
github.event_name == 'push' &&
(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.hidrive-next-build.result == 'success' &&
needs.upload-to-artifactory.result == 'success' &&
vars.DISABLE_REMOTE_TRIGGER != 'true' &&
(contains(github.ref_name, '/dev/') ||
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: |
echo "Checking if all required variables are set..."
error_count=0
if [ -z "${{ secrets.GITLAB_TOKEN }}" ]; then
echo "::error::GITLAB_TOKEN secret is not set"
error_count=$((error_count + 1))
fi
if [ -z "${{ secrets.GITLAB_TRIGGER_URL }}" ]; then
echo "::error::GITLAB_TRIGGER_URL secret is not set"
error_count=$((error_count + 1))
fi
if [ -z "${{ needs.hidrive-next-build.outputs.NC_VERSION }}" ]; then
echo "::error::NC_VERSION output from hidrive-next-build job is not set"
error_count=$((error_count + 1))
else
echo "✓ NC_VERSION: ${{ needs.hidrive-next-build.outputs.NC_VERSION }}"
fi
if [ -z "${{ needs.upload-to-artifactory.outputs.ARTIFACTORY_LAST_BUILD_PATH }}" ]; then
echo "::error::ARTIFACTORY_LAST_BUILD_PATH output from upload-to-artifactory job is not set"
error_count=$((error_count + 1))
else
echo "✓ ARTIFACTORY_LAST_BUILD_PATH: ${{ needs.upload-to-artifactory.outputs.ARTIFACTORY_LAST_BUILD_PATH }}"
fi
if [ -z "${{ github.sha }}" ]; then
echo "::error::github.sha is not set"
error_count=$((error_count + 1))
else
echo "✓ GITHUB_SHA: ${{ github.sha }}"
fi
if [ -z "${{ github.run_id }}" ]; then
echo "::error::github.run_id is not set"
error_count=$((error_count + 1))
else
echo "✓ BUILD_ID: ${{ github.run_id }}"
fi
if [ $error_count -ne 0 ]; then
echo "::error::Required variables are not set. Aborting."
exit 1
fi
echo "✅ All required variables are set"
- name: Trigger remote workflow
run: |
# Enable command echo for debugging purposes
set -x
# Branch to GitLab Trigger Mapping (see HDNEXT-1373):
# | ref_name | GITLAB_REF | BUILD_TYPE |
# |------------------|------------|-------------------|
# | ionos-dev-v30 | main | dev |
# | ionos-stable-v30 | main | stable |
# | rc/* | main | rc |
# | */dev/* | main | dev-<branch-pfx> |
#
# BUILD_TYPE only says which lane a build came from. The ref name is
# forwarded verbatim as well, so the downstream release report can name
# the RC or branch and link back to it.
BUILD_TYPE="dev"
if [ "${{ github.ref_name }}" == "ionos-stable-${{ env.NC_BRANCH_VERSION }}" ]; then
BUILD_TYPE="stable"
elif [[ "${{ github.ref_name }}" =~ ^rc/ ]]; then
BUILD_TYPE="rc"
elif [[ "${{ github.ref_name }}" =~ ^.*/dev/.*$ ]]; then
BRANCH_PREFIX=$(echo "${{ github.ref_name }}" | sed 's|/.*||' | sed 's/[^A-Za-z0-9._-]/-/g')
BUILD_TYPE="dev-${BRANCH_PREFIX}"
fi
# Construct source build URL for traceability
SOURCE_BUILD_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
echo "Source Build URL: $SOURCE_BUILD_URL"
# Call webhook (GitLab pipeline trigger always targets ref "main";
# the branch is distinguished downstream via the BUILD_TYPE variable)
curl \
--silent \
--insecure \
--request POST \
--fail-with-body \
-o response.json \
--form token=${{ secrets.GITLAB_TOKEN }} \
--form ref="main" \
--form "variables[GITHUB_SHA]=${{ github.sha }}" \
--form "variables[ARTIFACTORY_LAST_BUILD_PATH]=${{ needs.upload-to-artifactory.outputs.ARTIFACTORY_LAST_BUILD_PATH }}" \
--form "variables[NC_VERSION]=${{ needs.hidrive-next-build.outputs.NC_VERSION }}" \
--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 }}" || ( RETCODE="$?"; jq . response.json; exit "$RETCODE" )
# Print and parse json
# jq . response.json
echo "json<<END" >> $GITHUB_OUTPUT
cat response.json >> $GITHUB_OUTPUT
echo "END" >> $GITHUB_OUTPUT
echo "web_url<<END" >> $GITHUB_OUTPUT
cat response.json | jq --raw-output '.web_url' >> $GITHUB_OUTPUT
echo "END" >> $GITHUB_OUTPUT
- name: Show changes on failure
if: failure()
run: |
git status
git --no-pager diff
exit 1 # make it red to grab attention