From ce24926238135ecd39acf8c662928aa10bed83ad Mon Sep 17 00:00:00 2001 From: Gagan Deep Date: Tue, 27 Oct 2026 02:21:54 +0530 Subject: [PATCH 1/2] [ci] Added Zizmor GitHub Actions security analysis Added a pinned Zizmor workflow that scans GitHub Actions definitions on master and all major.minor release branches. The workflow reports findings through GitHub code scanning with least-privilege permissions. --- .github/workflows/zizmor.yml | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/zizmor.yml diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 0000000..bce0b32 --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,43 @@ +name: GitHub Actions Security Analysis with zizmor + +on: + push: + branches: + - master + - "[0-9]+.[0-9]+" + pull_request: + branches: + - master + - "[0-9]+.[0-9]+" + types: + - opened + - synchronize + - reopened + - edited + - ready_for_review + +permissions: {} + +jobs: + zizmor: + name: Run zizmor + runs-on: ubuntu-latest + # Only run the edited activity when the PR base branch changed. + if: github.event.action != 'edited' || github.event.changes.base.ref.from != '' + concurrency: + group: zizmor-${{ github.repository }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + permissions: + security-events: write # Uploads zizmor findings to GitHub code scanning. + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + persist-credentials: false + + - name: Run zizmor + uses: zizmorcore/zizmor-action@53290badfa369cb0bf7ad16342cb62c2fa47ac7b # v0.8.0 + with: + # Disables SARIF upload for fork PRs; zizmor analysis still runs and fails on findings. + advanced-security: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} + persona: pedantic From 6af7a63a29b61c03e4a7819fe28abca3048d911f Mon Sep 17 00:00:00 2001 From: Gagan Deep Date: Tue, 27 Oct 2026 02:22:09 +0530 Subject: [PATCH 2/2] [ci:security] Hardened GitHub Actions workflows Switched reusable workflows from openwisp-utils to openwisp-actions, pinned to the 0.1.0 release commit. Pinned other actions to immutable revisions and reduced workflow permissions. Disabled persisted checkout credentials, validated metadata consumed by privileged workflows, and added job-level concurrency limits. Related to openwisp/openwisp-utils#805 --- .github/dependabot.yml | 4 + .github/workflows/backport.yml | 23 ++-- .github/workflows/bot-autoassign-issue.yml | 14 ++- .../bot-autoassign-pr-issue-link.yml | 15 +-- .../workflows/bot-autoassign-pr-reopen.yml | 28 +++-- .github/workflows/bot-autoassign-stale-pr.yml | 10 +- .github/workflows/bot-changelog-runner.yml | 107 ++++++++++++++++-- .github/workflows/bot-changelog-trigger.yml | 12 +- .github/workflows/bot-ci-failure.yml | 25 ++-- .github/workflows/ci.yml | 17 ++- .github/workflows/pypi.yml | 22 ++-- .github/workflows/version-branch.yml | 2 +- 12 files changed, 204 insertions(+), 75 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f91a6bd..da01b32 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,11 +9,15 @@ updates: directory: "/" # Location of package manifests schedule: interval: "monthly" + cooldown: + default-days: 7 commit-message: prefix: "[deps] " - package-ecosystem: "github-actions" # Check for GitHub Actions updates directory: "/" schedule: interval: "monthly" # Check for updates weekly + cooldown: + default-days: 7 commit-message: prefix: "[ci] " diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 556ec7d..de1741b 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -4,21 +4,24 @@ on: push: branches: - master - issue_comment: + issue_comment: # zizmor: ignore[dangerous-triggers] Required for member or owner backport commands on merged PRs; inputs are guarded below. types: [created] +permissions: {} + concurrency: group: backport-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: false -permissions: - contents: write - pull-requests: write - jobs: backport-on-push: - if: github.event_name == 'push' - uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master + if: > + github.repository == 'openwisp/netdiff' && + github.event_name == 'push' + permissions: + contents: read + pull-requests: read # Resolves merged pull requests from pushed commits. + uses: openwisp/openwisp-actions/.github/workflows/reusable-backport.yml@5072c81386b436b073b67bc7918cec647f9e3414 # 0.1.0 with: commit_sha: ${{ github.sha }} secrets: @@ -27,13 +30,17 @@ jobs: backport-on-comment: if: > + github.repository == 'openwisp/netdiff' && github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.issue.pull_request.merged_at != null && github.event.issue.state == 'closed' && contains(fromJSON('["MEMBER", "OWNER"]'), github.event.comment.author_association) && startsWith(github.event.comment.body, '/backport') - uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master + permissions: + contents: read + pull-requests: read # Resolves the merge commit before handling a backport command. + uses: openwisp/openwisp-actions/.github/workflows/reusable-backport.yml@5072c81386b436b073b67bc7918cec647f9e3414 # 0.1.0 with: pr_number: ${{ github.event.issue.number }} comment_body: ${{ github.event.comment.body }} diff --git a/.github/workflows/bot-autoassign-issue.yml b/.github/workflows/bot-autoassign-issue.yml index 754e351..4f7403f 100644 --- a/.github/workflows/bot-autoassign-issue.yml +++ b/.github/workflows/bot-autoassign-issue.yml @@ -1,17 +1,19 @@ name: Issue Assignment Bot on: - issue_comment: + issue_comment: # zizmor: ignore[dangerous-triggers] Comments are the assignment interface; trusted bot code validates requests and issues. types: [created] -permissions: - contents: read - issues: write +permissions: {} concurrency: group: bot-autoassign-issue-${{ github.repository }}-${{ github.event.issue.number }} cancel-in-progress: true jobs: respond-to-assign-request: - if: github.event.issue.pull_request == null - uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-autoassign.yml@master + if: > + github.repository == 'openwisp/netdiff' && + github.event.issue.pull_request == null + permissions: + contents: read + uses: openwisp/openwisp-actions/.github/workflows/reusable-bot-autoassign.yml@5072c81386b436b073b67bc7918cec647f9e3414 # 0.1.0 with: bot_command: issue_assignment secrets: diff --git a/.github/workflows/bot-autoassign-pr-issue-link.yml b/.github/workflows/bot-autoassign-pr-issue-link.yml index feabaad..6f3add3 100644 --- a/.github/workflows/bot-autoassign-pr-issue-link.yml +++ b/.github/workflows/bot-autoassign-pr-issue-link.yml @@ -1,18 +1,19 @@ name: PR Issue Auto-Assignment on: - pull_request_target: + pull_request_target: # zizmor: ignore[dangerous-triggers] Required for issue assignment on fork PRs; the workflow runs trusted bot code only. types: [opened, reopened, closed, edited, ready_for_review] -permissions: - contents: read - issues: write - pull-requests: read +permissions: {} concurrency: group: bot-autoassign-pr-link-${{ github.repository }}-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: auto-assign-issue: - if: github.event.action != 'closed' || github.event.pull_request.merged == false - uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-autoassign.yml@master + if: > + github.repository == 'openwisp/netdiff' && + (github.event.action != 'closed' || github.event.pull_request.merged == false) + permissions: + contents: read + uses: openwisp/openwisp-actions/.github/workflows/reusable-bot-autoassign.yml@5072c81386b436b073b67bc7918cec647f9e3414 # 0.1.0 with: bot_command: issue_assignment secrets: diff --git a/.github/workflows/bot-autoassign-pr-reopen.yml b/.github/workflows/bot-autoassign-pr-reopen.yml index 4ee9430..ea37b3e 100644 --- a/.github/workflows/bot-autoassign-pr-reopen.yml +++ b/.github/workflows/bot-autoassign-pr-reopen.yml @@ -1,28 +1,36 @@ name: PR Reopen Reassignment on: - pull_request_target: + pull_request_target: # zizmor: ignore[dangerous-triggers] Required to update stale fork PRs; the workflow runs trusted bot code only. types: [reopened] - issue_comment: + issue_comment: # zizmor: ignore[dangerous-triggers] Required for PR-author recovery comments; the bot verifies the author before writes. types: [created] -permissions: - contents: read - issues: write - pull-requests: write +permissions: {} concurrency: group: bot-autoassign-pr-reopen-${{ github.repository }}-${{ github.event.pull_request.number || github.event.issue.number }} cancel-in-progress: true jobs: reassign-on-reopen: - if: github.event_name == 'pull_request_target' && github.event.action == 'reopened' - uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-autoassign.yml@master + if: > + github.repository == 'openwisp/netdiff' && + github.event_name == 'pull_request_target' && + github.event.action == 'reopened' + permissions: + contents: read + uses: openwisp/openwisp-actions/.github/workflows/reusable-bot-autoassign.yml@5072c81386b436b073b67bc7918cec647f9e3414 # 0.1.0 with: bot_command: pr_reopen secrets: OPENWISP_BOT_APP_ID: ${{ secrets.OPENWISP_BOT_APP_ID }} OPENWISP_BOT_PRIVATE_KEY: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} handle-pr-activity: - if: github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.issue.user.login == github.event.comment.user.login - uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-autoassign.yml@master + if: > + github.repository == 'openwisp/netdiff' && + github.event_name == 'issue_comment' && + github.event.issue.pull_request && + github.event.issue.user.login == github.event.comment.user.login + permissions: + contents: read + uses: openwisp/openwisp-actions/.github/workflows/reusable-bot-autoassign.yml@5072c81386b436b073b67bc7918cec647f9e3414 # 0.1.0 with: bot_command: pr_reopen secrets: diff --git a/.github/workflows/bot-autoassign-stale-pr.yml b/.github/workflows/bot-autoassign-stale-pr.yml index 80e4204..095b4b1 100644 --- a/.github/workflows/bot-autoassign-stale-pr.yml +++ b/.github/workflows/bot-autoassign-stale-pr.yml @@ -3,16 +3,16 @@ on: schedule: - cron: "0 0 * * *" workflow_dispatch: -permissions: - contents: read - issues: write - pull-requests: write +permissions: {} concurrency: group: bot-autoassign-stale-pr-${{ github.repository }} cancel-in-progress: false jobs: manage-stale-prs-python: - uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-autoassign.yml@master + if: github.repository == 'openwisp/netdiff' + permissions: + contents: read + uses: openwisp/openwisp-actions/.github/workflows/reusable-bot-autoassign.yml@5072c81386b436b073b67bc7918cec647f9e3414 # 0.1.0 with: bot_command: stale_pr secrets: diff --git a/.github/workflows/bot-changelog-runner.yml b/.github/workflows/bot-changelog-runner.yml index 218a7cc..d90fdb2 100644 --- a/.github/workflows/bot-changelog-runner.yml +++ b/.github/workflows/bot-changelog-runner.yml @@ -1,51 +1,134 @@ name: Changelog Bot Runner on: - workflow_run: + workflow_run: # zizmor: ignore[dangerous-triggers] Privileged follow-up consumes only validated metadata from the trusted review workflow. workflows: ["Changelog Bot Trigger"] types: - completed -permissions: - actions: read +permissions: {} jobs: fetch-metadata: + name: Fetch PR metadata runs-on: ubuntu-latest - if: github.event.workflow_run.conclusion == 'success' + if: > + github.repository == 'openwisp/netdiff' && + github.event.workflow_run.name == 'Changelog Bot Trigger' && + github.event.workflow_run.event == 'pull_request_review' && + github.event.workflow_run.conclusion == 'success' + concurrency: + group: changelog-runner-fetch-${{ github.repository }}-${{ github.event.workflow_run.head_repository.full_name }}-${{ github.event.workflow_run.head_branch }} + cancel-in-progress: true permissions: - actions: read + actions: read # Downloads the metadata artifact from the triggering workflow run. + pull-requests: read # Resolves the PR associated with the triggering commit. outputs: pr_number: ${{ steps.metadata.outputs.pr_number }} steps: - name: Download PR metadata id: download - uses: actions/download-artifact@v8 + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8 with: name: changelog-metadata + path: ${{ runner.temp }}/changelog-metadata github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} continue-on-error: true + - name: Resolve triggering pull request + if: steps.download.outcome == 'success' + id: association + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + HEAD_SHA: ${{ github.event.workflow_run.head_sha }} + REPOSITORY: ${{ github.repository }} + run: | + set -euo pipefail + RESPONSE=$(curl --fail --silent --show-error \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer $GH_TOKEN" \ + "https://api.github.com/repos/$REPOSITORY/commits/$HEAD_SHA/pulls?per_page=100") + mapfile -t PR_NUMBERS < <(jq -r '.[].number' <<< "$RESPONSE") + if [ "${#PR_NUMBERS[@]}" -ne 1 ]; then + echo "::error::Expected exactly one pull request for the triggering commit" + exit 1 + fi + PR_NUMBER=${PR_NUMBERS[0]} + if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then + echo "::error::Invalid associated PR number: $PR_NUMBER" + exit 1 + fi + echo "number=$PR_NUMBER" >> "$GITHUB_OUTPUT" + + - name: Verify current eligible approval + if: steps.download.outcome == 'success' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ steps.association.outputs.number }} + REPOSITORY: ${{ github.repository }} + run: | + set -euo pipefail + PR=$(gh api "repos/$REPOSITORY/pulls/$PR_NUMBER") + HEAD_SHA=$(jq -er '.head.sha' <<< "$PR") + REVIEWS=$(gh api --paginate --slurp "repos/$REPOSITORY/pulls/$PR_NUMBER/reviews?per_page=100") + if ! jq -e --arg head_sha "$HEAD_SHA" ' + .[][] | select( + .state == "APPROVED" and + .commit_id == $head_sha and + (.author_association == "OWNER" or + .author_association == "MEMBER" or + .author_association == "COLLABORATOR") + ) + ' <<< "$REVIEWS" > /dev/null; then + echo "::error::The pull request has no current eligible approval" + exit 1 + fi + - name: Read PR metadata if: steps.download.outcome == 'success' id: metadata + env: + ARTIFACT_DIR: ${{ runner.temp }}/changelog-metadata + EXPECTED_PR_NUMBER: ${{ steps.association.outputs.number }} run: | - PR_NUMBER=$(cat pr_number) + PR_NUMBER_FILE="$ARTIFACT_DIR/pr_number" + if [ ! -d "$ARTIFACT_DIR" ] || [ -L "$ARTIFACT_DIR" ]; then + echo "::error::Invalid metadata artifact directory" + exit 1 + fi + mapfile -d '' ARTIFACT_FILES < <(find "$ARTIFACT_DIR" -mindepth 1 -maxdepth 1 -print0) + if [ "${#ARTIFACT_FILES[@]}" -ne 1 ] || [ "${ARTIFACT_FILES[0]}" != "$PR_NUMBER_FILE" ] || [ -L "$PR_NUMBER_FILE" ] || [ ! -f "$PR_NUMBER_FILE" ]; then + echo "::error::Metadata artifact must contain only a regular pr_number file" + exit 1 + fi + FILE_SIZE=$(stat -c %s "$PR_NUMBER_FILE") + if [ "$FILE_SIZE" -gt 16 ]; then + echo "::error::Metadata artifact is too large" + exit 1 + fi + PR_NUMBER=$(< "$PR_NUMBER_FILE") if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then echo "::error::Invalid PR number: $PR_NUMBER" exit 1 fi - echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT + if [ -z "$EXPECTED_PR_NUMBER" ] || [ "$PR_NUMBER" != "$EXPECTED_PR_NUMBER" ]; then + echo "::error::Metadata PR number does not match the triggering pull request" + exit 1 + fi + echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT" changelog: needs: fetch-metadata - if: needs.fetch-metadata.outputs.pr_number != '' + if: > + github.repository == 'openwisp/netdiff' && + needs.fetch-metadata.outputs.pr_number != '' + concurrency: + group: changelog-runner-${{ github.repository }}-${{ needs.fetch-metadata.outputs.pr_number }} + cancel-in-progress: true permissions: contents: read - pull-requests: write - issues: write - uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-changelog.yml@master + uses: openwisp/openwisp-actions/.github/workflows/reusable-bot-changelog.yml@5072c81386b436b073b67bc7918cec647f9e3414 # 0.1.0 with: pr_number: ${{ needs.fetch-metadata.outputs.pr_number }} secrets: diff --git a/.github/workflows/bot-changelog-trigger.yml b/.github/workflows/bot-changelog-trigger.yml index 873b6be..e2bc1a1 100644 --- a/.github/workflows/bot-changelog-trigger.yml +++ b/.github/workflows/bot-changelog-trigger.yml @@ -8,11 +8,16 @@ permissions: {} jobs: check: - if: | + name: Check approved pull request + if: > + github.repository == 'openwisp/netdiff' && github.event.review.state == 'approved' && (github.event.review.author_association == 'OWNER' || github.event.review.author_association == 'MEMBER' || github.event.review.author_association == 'COLLABORATOR') + concurrency: + group: changelog-trigger-${{ github.repository }}-${{ github.event.pull_request.number }} + cancel-in-progress: true runs-on: ubuntu-latest steps: - name: Check for noteworthy PR @@ -21,7 +26,7 @@ jobs: PR_TITLE: ${{ github.event.pull_request.title }} run: | if echo "$PR_TITLE" | grep -qiE '^\[(feature|fix|change!?)\]'; then - echo "has_noteworthy=true" >> $GITHUB_OUTPUT + echo "has_noteworthy=true" >> "$GITHUB_OUTPUT" fi - name: Save PR metadata @@ -32,8 +37,7 @@ jobs: - name: Upload PR metadata if: steps.check.outputs.has_noteworthy == 'true' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7 with: name: changelog-metadata path: pr_number - retention-days: 1 diff --git a/.github/workflows/bot-ci-failure.yml b/.github/workflows/bot-ci-failure.yml index bb41292..57c006b 100644 --- a/.github/workflows/bot-ci-failure.yml +++ b/.github/workflows/bot-ci-failure.yml @@ -1,15 +1,12 @@ name: CI Failure Bot on: - workflow_run: + workflow_run: # zizmor: ignore[dangerous-triggers] Privileged analysis follows failed PR CI and treats PR code and logs as data only. workflows: ["OpenWISP CI Build"] types: - completed -permissions: - pull-requests: read - actions: read - contents: read +permissions: {} concurrency: group: ci-failure-${{ github.repository }}-${{ github.event.workflow_run.pull_requests[0].number || github.event.workflow_run.head_branch }} @@ -17,8 +14,16 @@ concurrency: jobs: find-pr: + name: Find failed CI pull request runs-on: ubuntu-latest - if: ${{ github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.event == 'pull_request' }} + if: > + github.repository == 'openwisp/netdiff' && + github.event.workflow_run.name == 'OpenWISP CI Build' && + github.event.workflow_run.conclusion == 'failure' && + github.event.workflow_run.event == 'pull_request' + permissions: + pull-requests: read # Locates the pull request associated with the failed workflow run. + actions: read # Queries workflow runs when the event payload lacks a PR number. outputs: pr_number: ${{ steps.pr.outputs.number }} pr_author: ${{ steps.pr.outputs.author }} @@ -37,7 +42,7 @@ jobs: pr_author=$(gh pr view "$pr_number" --repo "$REPO" --json author --jq '.author.login // empty' 2>/dev/null || echo "") if [ -z "$pr_author" ] || [ "$pr_author" = "null" ]; then echo "::warning::Could not fetch PR author for PR #$pr_number" - fi + fi echo "number=$pr_number" >> "$GITHUB_OUTPUT" echo "author=$pr_author" >> "$GITHUB_OUTPUT" } @@ -49,7 +54,7 @@ jobs: fi HEAD_SHA="$EVENT_HEAD_SHA" echo "Payload empty. Searching for PR via Commits API..." - PR_NUMBER=$(gh api repos/$REPO/commits/$HEAD_SHA/pulls -q '.[0].number' 2>/dev/null || true) + PR_NUMBER=$(gh api "repos/$REPO/commits/$HEAD_SHA/pulls" -q '.[0].number' 2>/dev/null || true) if [ -n "$PR_NUMBER" ] && [ "$PR_NUMBER" != "null" ]; then echo "Found PR #$PR_NUMBER using Commits API." emit_pr "$PR_NUMBER" @@ -69,10 +74,8 @@ jobs: needs: find-pr if: ${{ needs.find-pr.outputs.pr_number != '' }} permissions: - pull-requests: write - actions: write contents: read - uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-ci-failure.yml@master + uses: openwisp/openwisp-actions/.github/workflows/reusable-bot-ci-failure.yml@5072c81386b436b073b67bc7918cec647f9e3414 # 0.1.0 with: pr_number: ${{ needs.find-pr.outputs.pr_number }} head_sha: ${{ github.event.workflow_run.head_sha }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae17389..1f2b534 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,13 @@ on: - master - "[0-9]+.[0-9]+" +permissions: + contents: read + +concurrency: + group: ci-${{ github.repository }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: build: name: Python==${{ matrix.python-version }} @@ -23,12 +30,13 @@ jobs: - "3.13" steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: ${{ github.event.pull_request.head.sha }} + persist-credentials: false - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v7 + uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7 with: python-version: ${{ matrix.python-version }} cache: "pip" @@ -53,7 +61,7 @@ jobs: - name: Upload Coverage if: ${{ success() }} - uses: coverallsapp/github-action@v2 + uses: coverallsapp/github-action@8d6379e14d29928660c4ba802d8e85393440b329 # v2 with: parallel: true format: cobertura @@ -61,10 +69,11 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} coveralls: + name: Finalize Coveralls report needs: build runs-on: ubuntu-latest steps: - name: Coveralls Finished - uses: coverallsapp/github-action@v2 + uses: coverallsapp/github-action@8d6379e14d29928660c4ba802d8e85393440b329 # v2 with: parallel-finished: true diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 356c4a8..e89e6c6 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -4,24 +4,32 @@ on: release: types: [published] -permissions: - id-token: write +permissions: {} + +concurrency: + group: pypi-publish-${{ github.repository }} + queue: max + cancel-in-progress: false jobs: pypi-publish: + if: github.repository == 'openwisp/netdiff' name: Release Python Package on Pypi.org runs-on: ubuntu-latest environment: name: pypi url: https://pypi.org/p/netdiff permissions: - id-token: write + contents: read + id-token: write # Required for trusted publishing to PyPI. steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + persist-credentials: false - name: Set up Python - uses: actions/setup-python@v7 + uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7 with: - python-version: "3.12" + python-version: "3.10" - name: Install dependencies run: | pip install -U pip @@ -29,6 +37,6 @@ jobs: - name: Build package run: python -m build - name: Publish package distributions to PyPI - uses: pypa/gh-action-pypi-publish@v1.14.2 + uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2 with: skip-existing: true diff --git a/.github/workflows/version-branch.yml b/.github/workflows/version-branch.yml index 3a875ee..31ccb51 100644 --- a/.github/workflows/version-branch.yml +++ b/.github/workflows/version-branch.yml @@ -10,7 +10,7 @@ permissions: jobs: version-branch: - uses: openwisp/openwisp-utils/.github/workflows/reusable-version-branch.yml@3497e3fbd42dff2a59f566184a1bf8e1b2ab57ea + uses: openwisp/openwisp-actions/.github/workflows/reusable-version-branch.yml@5072c81386b436b073b67bc7918cec647f9e3414 # 0.1.0 with: module_name: netdiff client_id: ${{ vars.OPENWISP_BOT_CLIENT_ID }}