From 8aaab1028c50ca5068e6de60c144b08577c0b57d Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Sun, 25 Oct 2026 15:28:20 +0000 Subject: [PATCH 1/3] fix(ci): adopt secured LibreCode npm audit workflow Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .github/workflows/npm-audit-fix.yml | 53 ++++++++++++++++------- .github/workflows/npm-audit-fix.yml.patch | 21 +++++++++ 2 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/npm-audit-fix.yml.patch diff --git a/.github/workflows/npm-audit-fix.yml b/.github/workflows/npm-audit-fix.yml index 5ccc57d..039d0db 100644 --- a/.github/workflows/npm-audit-fix.yml +++ b/.github/workflows/npm-audit-fix.yml @@ -1,6 +1,6 @@ # This workflow is provided via the organization template repository # -# https://github.com/nextcloud/.github +# https://github.com/LibreCodeCoop/.github # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization # # SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors @@ -14,6 +14,9 @@ on: # At 2:30 on Sundays - cron: '30 2 * * 0' +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest @@ -21,54 +24,74 @@ jobs: strategy: fail-fast: false matrix: - branches: ['main', 'master', 'stable30', 'stable29', 'stable28'] + branches: + - ${{ github.event.repository.default_branch }} name: npm-audit-fix-${{ matrix.branches }} steps: - name: Checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + id: checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false ref: ${{ matrix.branches }} + continue-on-error: true - name: Read package.json node and npm engines version - uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 + if: steps.checkout.outcome == 'success' + uses: skjnldsv/read-package-engines-version-actions@06d6db44aa62f4609ba070f556ec24bc99fb85cb # v4 id: versions with: - fallbackNode: '^20' - fallbackNpm: '^10' + fallbackNode: '^24' + fallbackNpm: '^11.3' - name: Set up node ${{ steps.versions.outputs.nodeVersion }} - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + if: steps.checkout.outcome == 'success' + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: ${{ steps.versions.outputs.nodeVersion }} - name: Set up npm ${{ steps.versions.outputs.npmVersion }} + if: steps.checkout.outcome == 'success' run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}' - name: Fix npm audit id: npm-audit - uses: nextcloud-libraries/npm-audit-action@2a60bd2e79cc77f2cc4d9a3fe40f1a69896f3a87 # v0.1.0 + if: steps.checkout.outcome == 'success' + uses: nextcloud-libraries/npm-audit-action@1b1728b2b4a7a78d69de65608efcf4db0e3e42d0 # v0.2.0 - name: Run npm ci and npm run build - if: always() + if: steps.checkout.outcome == 'success' env: CYPRESS_INSTALL_BINARY: 0 run: | npm ci npm run build --if-present + - name: Create GitHub App token for dependency PR + id: app-token + if: steps.checkout.outcome == 'success' + uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0 + with: + client-id: ${{ vars.LIBRECODE_WORKFLOW_APP_CLIENT_ID }} + private-key: ${{ secrets.LIBRECODE_WORKFLOW_APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} + repositories: ${{ github.event.repository.name }} + permission-contents: write + permission-pull-requests: write + - name: Create Pull Request - if: always() - uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6.1.0 + if: steps.checkout.outcome == 'success' + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 with: - token: ${{ secrets.COMMAND_BOT_PAT }} - commit-message: 'fix(deps): Fix npm audit' + token: ${{ steps.app-token.outputs.token }} + commit-message: 'fix(deps): resolve npm audit vulnerabilities' committer: GitHub - author: nextcloud-command + author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> signoff: true branch: automated/noid/${{ matrix.branches }}-fix-npm-audit - title: '[${{ matrix.branches }}] Fix npm audit' + title: "${{ matrix.branches != github.event.repository.default_branch && format('[{0}] ', matrix.branches) || '' }}fix(deps): resolve npm audit vulnerabilities" body: ${{ steps.npm-audit.outputs.markdown }} labels: | dependencies diff --git a/.github/workflows/npm-audit-fix.yml.patch b/.github/workflows/npm-audit-fix.yml.patch new file mode 100644 index 0000000..bfbc531 --- /dev/null +++ b/.github/workflows/npm-audit-fix.yml.patch @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2026 LibreCode coop and contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +--- a/.github/workflows/npm-audit-fix.yml ++++ b/.github/workflows/npm-audit-fix.yml +@@ -11,8 +11,8 @@ + on: + workflow_dispatch: + schedule: +- # At 22:30 on Saturdays +- - cron: '30 22 * * 6' ++ # At 2:30 on Sundays ++ - cron: '30 2 * * 0' + + permissions: + contents: read +@@ -95,3 +95,4 @@ + body: ${{ steps.npm-audit.outputs.markdown }} + labels: | + dependencies ++ 3. to review From cc4b9316bb8c5d87969aa8f056c828c7f47db2a4 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Sun, 25 Oct 2026 15:50:47 +0000 Subject: [PATCH 2/3] fix(ci): drop obsolete Psalm baseline entry Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- tests/psalm-baseline.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml index b972764..51c048f 100644 --- a/tests/psalm-baseline.xml +++ b/tests/psalm-baseline.xml @@ -13,7 +13,6 @@ - From 6bf231a0af7adcd4b9aac8643dcd382130a5a49e Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Sun, 25 Oct 2026 15:54:16 +0000 Subject: [PATCH 3/3] ci(actions): install selective LibreCode workflow synchronization Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .github/workflows/sync-workflow-templates.yml | 194 ++++++++++++++++++ .../sync-workflow-templates.yml.patch | 13 ++ 2 files changed, 207 insertions(+) create mode 100644 .github/workflows/sync-workflow-templates.yml create mode 100644 .github/workflows/sync-workflow-templates.yml.patch diff --git a/.github/workflows/sync-workflow-templates.yml b/.github/workflows/sync-workflow-templates.yml new file mode 100644 index 0000000..daa2bfe --- /dev/null +++ b/.github/workflows/sync-workflow-templates.yml @@ -0,0 +1,194 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/LibreCodeCoop/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization +# +# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: MIT + +# This workflow will update all workflow templates. +# Additionally it will reapply workflow.yml.patch files after syncing and only then commit the result. +# +# Authentication is selected explicitly with vars.WORKFLOW_SYNC_AUTH_MODE. +# See docs/cross-repository-automation.md for modes, credentials and GITHUB_TOKEN limitations. +name: Update workflows +on: + workflow_dispatch: + schedule: + - cron: "5 2 * * 0" + +permissions: + contents: read + +jobs: + dispatch: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + branches: + - ${{ github.event.repository.default_branch }} + + name: Update workflows in ${{ matrix.branches }} + + permissions: + contents: write + pull-requests: write + + steps: + - name: Check actor permission + if: ${{ github.event_name == 'workflow_dispatch' }} + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + permission="$(gh api "repos/${GITHUB_REPOSITORY}/collaborators/${GITHUB_ACTOR}/permission" --jq '.permission')" + [[ "${permission}" == "admin" ]] || { + echo "::error::Manual workflow runs require repository admin permission; ${GITHUB_ACTOR} has ${permission}" + exit 1 + } + + - name: Validate workflow sync authentication + shell: bash + env: + AUTH_MODE: ${{ vars.WORKFLOW_SYNC_AUTH_MODE || 'librecode-app' }} + LIBRECODE_APP_CLIENT_ID: ${{ vars.LIBRECODE_WORKFLOW_APP_CLIENT_ID }} + LIBRECODE_APP_PRIVATE_KEY: ${{ secrets.LIBRECODE_WORKFLOW_APP_PRIVATE_KEY }} + CONSUMER_APP_CLIENT_ID: ${{ vars.WORKFLOW_SYNC_APP_CLIENT_ID }} + CONSUMER_APP_PRIVATE_KEY: ${{ secrets.WORKFLOW_SYNC_APP_PRIVATE_KEY }} + CONSUMER_TOKEN: ${{ secrets.WORKFLOW_SYNC_TOKEN }} + run: | + set -euo pipefail + + case "${AUTH_MODE}" in + librecode-app) + [[ -n "${LIBRECODE_APP_CLIENT_ID}" && -n "${LIBRECODE_APP_PRIVATE_KEY}" ]] || { + echo "::error::librecode-app requires LIBRECODE_WORKFLOW_APP_CLIENT_ID and LIBRECODE_WORKFLOW_APP_PRIVATE_KEY" + exit 1 + } + ;; + github-app) + [[ -n "${CONSUMER_APP_CLIENT_ID}" && -n "${CONSUMER_APP_PRIVATE_KEY}" ]] || { + echo "::error::github-app requires WORKFLOW_SYNC_APP_CLIENT_ID and WORKFLOW_SYNC_APP_PRIVATE_KEY" + exit 1 + } + ;; + token) + [[ -n "${CONSUMER_TOKEN}" ]] || { + echo "::error::token mode requires WORKFLOW_SYNC_TOKEN" + exit 1 + } + ;; + github-token) + ;; + *) + echo "::error::Unsupported WORKFLOW_SYNC_AUTH_MODE: ${AUTH_MODE}" + exit 1 + ;; + esac + + - name: Create LibreCode GitHub App token + if: ${{ vars.WORKFLOW_SYNC_AUTH_MODE == '' || vars.WORKFLOW_SYNC_AUTH_MODE == 'librecode-app' }} + id: librecode-app-token + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + with: + client-id: ${{ vars.LIBRECODE_WORKFLOW_APP_CLIENT_ID }} + private-key: ${{ secrets.LIBRECODE_WORKFLOW_APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} + repositories: ${{ github.event.repository.name }} + permission-contents: write + permission-pull-requests: write + permission-workflows: write + + - name: Create consumer GitHub App token + if: ${{ vars.WORKFLOW_SYNC_AUTH_MODE == 'github-app' }} + id: consumer-app-token + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + with: + client-id: ${{ vars.WORKFLOW_SYNC_APP_CLIENT_ID }} + private-key: ${{ secrets.WORKFLOW_SYNC_APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} + repositories: ${{ github.event.repository.name }} + permission-contents: write + permission-pull-requests: write + permission-workflows: write + + - name: Resolve workflow sync token + id: auth-token + shell: bash + env: + AUTH_MODE: ${{ vars.WORKFLOW_SYNC_AUTH_MODE || 'librecode-app' }} + LIBRECODE_APP_TOKEN: ${{ steps.librecode-app-token.outputs.token }} + CONSUMER_APP_TOKEN: ${{ steps.consumer-app-token.outputs.token }} + CONSUMER_TOKEN: ${{ secrets.WORKFLOW_SYNC_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + + case "${AUTH_MODE}" in + librecode-app) token="${LIBRECODE_APP_TOKEN}" ;; + github-app) token="${CONSUMER_APP_TOKEN}" ;; + token) token="${CONSUMER_TOKEN}" ;; + github-token) token="${GITHUB_TOKEN}" ;; + *) exit 1 ;; + esac + + [[ -n "${token}" ]] || { + echo "::error::Selected workflow sync authentication produced an empty token" + exit 1 + } + + echo "::add-mask::${token}" + echo "token=${token}" >> "${GITHUB_OUTPUT}" + + - name: Checkout workflow repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + path: source + repository: LibreCodeCoop/.github + + - name: Record workflow catalog revision + id: catalog-revision + working-directory: source + shell: bash + run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + + - name: Checkout app + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + path: target + ref: ${{ matrix.branches }} + + - name: Synchronize workflow templates + id: sync + uses: ./source/actions/sync-workflows + with: + source: source/workflow-templates + target: target + catalog-commit: ${{ steps.catalog-revision.outputs.sha }} + include: npm-audit-fix.yml + + - name: Create Pull Request + if: ${{ steps.sync.outputs.changed == 'true' }} + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 + with: + token: ${{ steps.auth-token.outputs.token }} + commit-message: 'ci(actions): Update workflow templates from organization template repository' + committer: GitHub + author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> + path: target + signoff: true + branch: 'automated/noid/${{ matrix.branches }}-update-workflows' + title: '[${{ matrix.branches }}] ci(actions): Update workflow templates from organization template repository' + draft: ${{ steps.sync.outputs.patch_failed == 'true' }} + add-paths: .github/workflows/*.yml,.github/actions-lock.txt + body: | + Automated update of workflow templates from [LibreCodeCoop/.github](https://github.com/LibreCodeCoop/.github) + ${{ steps.sync.outputs.summary }} + labels: | + dependencies + 3. to review diff --git a/.github/workflows/sync-workflow-templates.yml.patch b/.github/workflows/sync-workflow-templates.yml.patch new file mode 100644 index 0000000..edd1873 --- /dev/null +++ b/.github/workflows/sync-workflow-templates.yml.patch @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2026 LibreCode coop and contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +--- a/.github/workflows/sync-workflow-templates.yml ++++ b/.github/workflows/sync-workflow-templates.yml +@@ -170,6 +170,7 @@ + source: source/workflow-templates + target: target + catalog-commit: ${{ steps.catalog-revision.outputs.sha }} ++ include: npm-audit-fix.yml + + - name: Create Pull Request + if: ${{ steps.sync.outputs.changed == 'true' }}