From 786a27c335a61887e55d9575d8b79035f9f892a7 Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Tue, 21 Jul 2026 15:38:55 +0200 Subject: [PATCH 1/4] Updated deprecated GitHub Actions in auto_tag workflow Aligned with the IBX-11778 treatment from ibexa/gh-workflows#103, adjusted for metapackages: - Bumped actions/create-github-app-token from v2 to v3, switching the deprecated app-id input to client-id - Replaced tibdex/github-app-token@v1 with actions/create-github-app-token@v3 in the action job - Replaced octokit/request-action with equivalent gh api calls, preserving the data output consumed by later steps - Bumped actions/checkout to v7 and both jobs to ubuntu-26.04 - Removed steps guarded by other editions' repository names (the file was designed to be copy-pasted between edition repositories, but the copies have since diverged) and the unused cs2pr tool. Headless deliberately does not wait for its parent package (ibexa/oss), which is available on Packagist, not via Satis; a comment now records that Co-Authored-By: Claude Fable 5 --- .github/workflows/auto_tag.yml | 77 +++++++++------------------------- 1 file changed, 20 insertions(+), 57 deletions(-) diff --git a/.github/workflows/auto_tag.yml b/.github/workflows/auto_tag.yml index 86c912c..845a7b3 100644 --- a/.github/workflows/auto_tag.yml +++ b/.github/workflows/auto_tag.yml @@ -19,7 +19,7 @@ on: jobs: preparation: - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 # This should allow parallel runs in a chain, e.g. OSS->Headless->Experience->Commerce # whilst allowing Satis to process timeout-minutes: 30 @@ -27,61 +27,22 @@ jobs: steps: - name: Generate token id: generate_token - uses: actions/create-github-app-token@v2 + uses: actions/create-github-app-token@v3 with: - app-id: ${{ secrets.AUTOMATION_CLIENT_ID }} + client-id: ${{ secrets.AUTOMATION_CLIENT_ID }} private-key: ${{ secrets.AUTOMATION_CLIENT_SECRET }} owner: ${{ github.repository_owner }} + # No need to wait for the parent package (ibexa/oss) — it is available on Packagist, not via Satis - name: Check for headless-assets tag - uses: octokit/request-action@v2.x - with: - owner: ibexa - repo: headless-assets - route: /repos/{owner}/{repo}/contents/package.json?ref=v${{ inputs.version }} + shell: bash + run: gh api "/repos/ibexa/headless-assets/contents/package.json?ref=v${{ inputs.version }}" >/dev/null env: GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} - # The jq command would return a zero exit status if it was able to filter the input JSON data and - # produce at least one matching object in the array, and a non-zero exit status if no matching object was found. - # This particular JQ filter expression: - # .packages."${{ env.PARENT }}"[]: accesses an array of objects in the packages object, with the key specified by the environment variable PARENT. - # select(.version == "${{ env.V_VERSION }}"): filters the array to only include objects where the version property is equal to the value of the environment variable V_VERSION. - - # No need to validate for oss version in satis - - name: Validate satis for headless version - if: github.event.repository.name == 'experience' - env: - SATIS_NETWORK_KEY: ${{ secrets.SATIS_NETWORK_KEY }} - SATIS_NETWORK_TOKEN: ${{ secrets.SATIS_NETWORK_TOKEN }} - PARENT: ibexa/headless - V_VERSION: v${{ inputs.version }} - run: | - for EXPONENTIAL_BACKOFF in {1..10}; do - curl https://updates.ibexa.co/p2/${PARENT}.json -s -u $SATIS_NETWORK_KEY:$SATIS_NETWORK_TOKEN | jq -e '.packages."${{ env.PARENT }}"[] | select(.version == "${{ env.V_VERSION }}")' && break; - DELAY=$((2**$EXPONENTIAL_BACKOFF)) - echo "${PARENT}:${V_VERSION} not yet available, sleeping for $DELAY seconds" - sleep $DELAY - done - - - name: Validate satis for experience version - if: github.event.repository.name == 'commerce' - env: - SATIS_NETWORK_KEY: ${{ secrets.SATIS_NETWORK_KEY }} - SATIS_NETWORK_TOKEN: ${{ secrets.SATIS_NETWORK_TOKEN }} - PARENT: ibexa/experience - V_VERSION: v${{ inputs.version }} - run: | - for EXPONENTIAL_BACKOFF in {1..10}; do - curl https://updates.ibexa.co/p2/${PARENT}.json -s -u $SATIS_NETWORK_KEY:$SATIS_NETWORK_TOKEN | jq -e '.packages."${{ env.PARENT }}"[] | select(.version == "${{ env.V_VERSION }}")' && break; - DELAY=$((2**$EXPONENTIAL_BACKOFF)) - echo "${PARENT}:${V_VERSION} not yet available, sleeping for $DELAY seconds" - sleep $DELAY - done - action: needs: preparation - runs-on: ubuntu-22.04 + runs-on: ubuntu-26.04 steps: - name: Install sponge @@ -94,27 +55,29 @@ jobs: php-version: 8.3 coverage: none extensions: pdo_sqlite, gd - tools: cs2pr - name: Generate token id: generate_token - uses: tibdex/github-app-token@v1 + uses: actions/create-github-app-token@v3 with: - app_id: ${{ secrets.AUTOMATION_CLIENT_ID }} - installation_id: ${{ secrets.AUTOMATION_CLIENT_INSTALLATION }} - private_key: ${{ secrets.AUTOMATION_CLIENT_SECRET }} + client-id: ${{ secrets.AUTOMATION_CLIENT_ID }} + private-key: ${{ secrets.AUTOMATION_CLIENT_SECRET }} + owner: ${{ github.repository_owner }} - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: persist-credentials: false - name: Get release information - uses: octokit/request-action@v2.x id: release - with: - owner: ibexa - repo: release-maker - route: /repos/{owner}/{repo}/contents/releases/${{ inputs.version }}/release.json + shell: bash + run: | + response=$(gh api "/repos/ibexa/release-maker/contents/releases/${{ inputs.version }}/release.json") + { + echo 'data<> "$GITHUB_OUTPUT" env: GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} From 551f2955e9146a958cf4bf287fe46b1810674dcb Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Tue, 21 Jul 2026 16:43:50 +0200 Subject: [PATCH 2/4] Replaced ezrobot PAT with GitHub App token in auto_tag push step The Commit, tag and push step used the EZROBOT_PAT personal access token and rewrote the origin remote URL to embed it, while the job already generates a GitHub App installation token. Now: - the push step receives the app token via its GITHUB_TOKEN env and authenticates git through gh auth setup-git (gh acting as the git credential helper), keeping the whole credential flow local to the step - checkout stays credential-free and no secret is written to .git/config - the release commit is authored as github-actions[bot] instead of ezrobot, which no longer plays any role here - inputs.version is passed to the shell via the step's VERSION env instead of raw workflow-expression interpolation Note before merging: this path only runs with real_op: true, so PR CI does not exercise it. The automation GitHub App must have contents write permission and any tag protection allowances previously granted to the ezrobot account. Co-Authored-By: Claude Fable 5 --- .github/workflows/auto_tag.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/auto_tag.yml b/.github/workflows/auto_tag.yml index 845a7b3..77b81d0 100644 --- a/.github/workflows/auto_tag.yml +++ b/.github/workflows/auto_tag.yml @@ -149,13 +149,14 @@ jobs: - name: Commit, tag and push if: inputs.real_op env: + GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} GIT_PUSH_ARGS: ${{ inputs.git_push_args }} - ROBOT_TOKEN: ${{ secrets.EZROBOT_PAT }} + VERSION: ${{ inputs.version }} run: | - git config --local user.email "681611+ezrobot@users.noreply.github.com" - git config --local user.name "ezrobot" - git remote set-url origin https://x-access-token:${{ env.ROBOT_TOKEN }}@github.com/${{ github.repository }} + gh auth setup-git + git config --local user.name "github-actions[bot]" + git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" git add composer.* - git commit -m "[composer] Set dependencies for ${{ inputs.version }} release + .lock" - git tag "v${{ inputs.version }}" - git push origin "v${{ inputs.version }}" ${GIT_PUSH_ARGS} + git commit -m "[composer] Set dependencies for ${VERSION} release + .lock" + git tag "v${VERSION}" + git push origin "v${VERSION}" ${GIT_PUSH_ARGS} From e133043f0c82674c7e7c0170ca65f2ab7ee8ba5a Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Wed, 22 Jul 2026 16:22:03 +0200 Subject: [PATCH 3/4] Extracted auto_tag logic into shared gh-workflows composite actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Create Tag workflow now keeps only its edition-specific data and delegates the mechanics to two composite actions in ibexa/gh-workflows: - check-composer-package (preparation) checks that the required package version is available on the Composer repository that composer update will actually consume — more accurate than the previous GitHub-tag probe, which could pass while the package was not yet installable; - create-metapackage-tag (action) fetches the release definition, derives minimum stability, pins the parent/assets packages, patches require versions, updates composer.lock and, with real_op, commits, tags and pushes using the GitHub App token. Behavior is unchanged apart from the more accurate preparation check and the dropped sponge/moreutils dependency. Co-Authored-By: Claude Fable 5 --- .github/workflows/auto_tag.yml | 150 +++++---------------------------- 1 file changed, 22 insertions(+), 128 deletions(-) diff --git a/.github/workflows/auto_tag.yml b/.github/workflows/auto_tag.yml index 77b81d0..fb17372 100644 --- a/.github/workflows/auto_tag.yml +++ b/.github/workflows/auto_tag.yml @@ -20,143 +20,37 @@ on: jobs: preparation: runs-on: ubuntu-26.04 - # This should allow parallel runs in a chain, e.g. OSS->Headless->Experience->Commerce - # whilst allowing Satis to process - timeout-minutes: 30 steps: - - name: Generate token - id: generate_token - uses: actions/create-github-app-token@v3 - with: - client-id: ${{ secrets.AUTOMATION_CLIENT_ID }} - private-key: ${{ secrets.AUTOMATION_CLIENT_SECRET }} - owner: ${{ github.repository_owner }} - # No need to wait for the parent package (ibexa/oss) — it is available on Packagist, not via Satis - - name: Check for headless-assets tag - shell: bash - run: gh api "/repos/ibexa/headless-assets/contents/package.json?ref=v${{ inputs.version }}" >/dev/null - env: - GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} + - name: Check for headless-assets package in Satis + uses: ibexa/gh-workflows/actions/check-composer-package@main + with: + package: ibexa/headless-assets + version: v${{ inputs.version }} + repository-url: https://updates.ibexa.co + auth-key: ${{ secrets.SATIS_NETWORK_KEY }} + auth-token: ${{ secrets.SATIS_NETWORK_TOKEN }} action: needs: preparation runs-on: ubuntu-26.04 - - steps: - - name: Install sponge - run: | - sudo apt-get install -y moreutils - - - name: Setup PHP Action - uses: shivammathur/setup-php@v2 - with: - php-version: 8.3 - coverage: none - extensions: pdo_sqlite, gd - - - name: Generate token - id: generate_token - uses: actions/create-github-app-token@v3 - with: - client-id: ${{ secrets.AUTOMATION_CLIENT_ID }} - private-key: ${{ secrets.AUTOMATION_CLIENT_SECRET }} - owner: ${{ github.repository_owner }} + steps: - uses: actions/checkout@v7 with: persist-credentials: false - - name: Get release information - id: release - shell: bash - run: | - response=$(gh api "/repos/ibexa/release-maker/contents/releases/${{ inputs.version }}/release.json") - { - echo 'data<> "$GITHUB_OUTPUT" - env: - GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} - - # The effect of this jq command is to take a JSON array of objects, - # transform each object into a new object using its packageName and targetVersion properties, - # and return the result as a single JSON object. - # The sponge command is used to pipe the output of jq back into the same file, effectively replacing its contents with the updated JSON data. - - name: Process release information - run: | - cat > input.json <<'EOF' - ${{ steps.release.outputs.data }} - EOF - jq -r '.["content"]' input.json | base64 --decode | jq -c . > release.json - jq -s '[ .[][] | { (.packageName): (.targetVersion) } ] | add' release.json | sponge release.json - - - name: Set minimum stability - run: | - VERSION=$( echo ${{ inputs.version }} | cut -d '-' -f 2 ) - SET_STABILITY="composer config minimum-stability" - $SET_STABILITY --unset - composer config prefer-stable --unset - case $VERSION in - alpha*|beta*|rc*) composer config prefer-stable true ;;& - alpha*) $SET_STABILITY alpha ;; - beta*) $SET_STABILITY beta ;; - rc*) $SET_STABILITY rc ;; - esac; - - - name: Patch parent version for Headless - run: | - jq '.require["ibexa/headless-assets"] |= "${{ inputs.version }}"' composer.json | sponge composer.json - jq '.require["ibexa/oss"] |= "${{ inputs.version }}"' composer.json | sponge composer.json - - # The effect of this jq command is to modify the require property of the input JSON object by using values from the $release object, - # if they exist, to update the values of the keys in the require object. - - name: Patch composer require versions - run: | - jq --slurpfile release <(cat release.json) ' - .require |= ( - to_entries | - map({ - key: .key, - value: (if ($release[0][.key]) then $release[0][.key] else .value end) - }) | from_entries - ) - ' composer.json > composer.tmp - mv composer.tmp composer.json - - - name: Reformat composer.json - run: cat composer.json | unexpand -t2 | expand -t4 | sponge composer.json - - - name: Preview composer.json - run: cat composer.json - - - name: Add composer keys for private packagist - run: | - composer config http-basic.updates.ibexa.co $SATIS_NETWORK_KEY $SATIS_NETWORK_TOKEN - composer config github-oauth.github.com $APP_GITHUB_TOKEN - env: - SATIS_NETWORK_KEY: ${{ secrets.SATIS_NETWORK_KEY }} - SATIS_NETWORK_TOKEN: ${{ secrets.SATIS_NETWORK_TOKEN }} - APP_GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} - - - name: Composer update - run: | - composer update --no-scripts --no-plugins --no-install - composer validate - - - name: Commit, tag and push - if: inputs.real_op - env: - GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} - GIT_PUSH_ARGS: ${{ inputs.git_push_args }} - VERSION: ${{ inputs.version }} - run: | - gh auth setup-git - git config --local user.name "github-actions[bot]" - git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add composer.* - git commit -m "[composer] Set dependencies for ${VERSION} release + .lock" - git tag "v${VERSION}" - git push origin "v${VERSION}" ${GIT_PUSH_ARGS} + - name: Set dependency versions, commit, tag and push + uses: ibexa/gh-workflows/actions/create-metapackage-tag@main + with: + version: ${{ inputs.version }} + pin-packages: | + ibexa/headless-assets + ibexa/oss + real-op: ${{ inputs.real_op }} + git-push-args: ${{ inputs.git_push_args }} + gh-client-id: ${{ secrets.AUTOMATION_CLIENT_ID }} + gh-client-secret: ${{ secrets.AUTOMATION_CLIENT_SECRET }} + satis-network-key: ${{ secrets.SATIS_NETWORK_KEY }} + satis-network-token: ${{ secrets.SATIS_NETWORK_TOKEN }} From 64300649f296eaf387b7366fffa9d6a979ee785a Mon Sep 17 00:00:00 2001 From: Andrew Longosz Date: Wed, 22 Jul 2026 16:22:33 +0200 Subject: [PATCH 4/4] [TMP][GHA] Pointed gh-workflows action refs at feature branch Allows testing the new composite actions before the ibexa/gh-workflows pull request that introduces them is merged. Drop before merging. Co-Authored-By: Claude Fable 5 --- .github/workflows/auto_tag.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/auto_tag.yml b/.github/workflows/auto_tag.yml index fb17372..935b6c2 100644 --- a/.github/workflows/auto_tag.yml +++ b/.github/workflows/auto_tag.yml @@ -24,7 +24,7 @@ jobs: steps: # No need to wait for the parent package (ibexa/oss) — it is available on Packagist, not via Satis - name: Check for headless-assets package in Satis - uses: ibexa/gh-workflows/actions/check-composer-package@main + uses: ibexa/gh-workflows/actions/check-composer-package@ibx-11778-metapackage-composite-actions with: package: ibexa/headless-assets version: v${{ inputs.version }} @@ -42,7 +42,7 @@ jobs: persist-credentials: false - name: Set dependency versions, commit, tag and push - uses: ibexa/gh-workflows/actions/create-metapackage-tag@main + uses: ibexa/gh-workflows/actions/create-metapackage-tag@ibx-11778-metapackage-composite-actions with: version: ${{ inputs.version }} pin-packages: |