Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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] "
23 changes: 15 additions & 8 deletions .github/workflows/backport.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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 }}
Expand Down
14 changes: 8 additions & 6 deletions .github/workflows/bot-autoassign-issue.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
15 changes: 8 additions & 7 deletions .github/workflows/bot-autoassign-pr-issue-link.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
28 changes: 18 additions & 10 deletions .github/workflows/bot-autoassign-pr-reopen.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/bot-autoassign-stale-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
107 changes: 95 additions & 12 deletions .github/workflows/bot-changelog-runner.yml
Original file line number Diff line number Diff line change
@@ -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
Comment thread
coderabbitai[bot] marked this conversation as resolved.
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:
Expand Down
12 changes: 8 additions & 4 deletions .github/workflows/bot-changelog-trigger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Loading
Loading