IONOS(ci): forward the source ref name to the remote trigger (HDNEXT-… #1181
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |