This is an automated email from the ASF dual-hosted git repository.
hubcio pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git
The following commit(s) were added to refs/heads/master by this push:
new e04d90d24 fix(ci): stop stale bot from re-marking PRs each week (#3283)
e04d90d24 is described below
commit e04d90d24b17ca7507642cc0601f912590f55c70
Author: Hubert Gruszecki <[email protected]>
AuthorDate: Wed May 20 08:39:10 2026 +0200
fix(ci): stop stale bot from re-marking PRs each week (#3283)
---
.github/workflows/stale-prs-unmark-on-activity.yml | 111 +++++++++++++++++++++
.github/workflows/stale-prs-unmark.yml | 54 ++++++++++
.github/workflows/stale-prs.yml | 5 +-
3 files changed, 168 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/stale-prs-unmark-on-activity.yml
b/.github/workflows/stale-prs-unmark-on-activity.yml
new file mode 100644
index 000000000..d451269f7
--- /dev/null
+++ b/.github/workflows/stale-prs-unmark-on-activity.yml
@@ -0,0 +1,111 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Removes the S-stale label on PR comments and review submissions, via
+# the workflow_run handoff from pr-triage-collect.yml.
+#
+# Why workflow_run instead of issue_comment / pull_request_review here:
+# those events deliver a read-only GITHUB_TOKEN on cross-fork PRs
+# regardless of the workflow's permissions block, so the label DELETE
+# silently fails for the majority of contributor PRs. pr-triage-collect.yml
+# already collects the event payload as an artifact under a read-only
+# token; this workflow runs against base ref via workflow_run, where the
+# GITHUB_TOKEN has write perms, and removes the label.
+#
+# Push-driven unmark stays in stale-prs-unmark.yml because
+# pull_request_target.synchronize gets a write token directly.
+#
+# SECURITY: no actions/checkout, no exec of PR contents. The artifact
+# contents come from the runner-written event_path, not from PR code.
+
+name: Unmark Stale PRs on Activity
+
+on:
+ workflow_run:
+ workflows: ["PR Triage Collect"]
+ types: [completed]
+
+permissions:
+ pull-requests: write
+ contents: read
+ # Required for actions/download-artifact@v8 to fetch the triage-event
+ # artifact uploaded by the upstream PR Triage Collect run via run-id.
+ actions: read
+
+concurrency:
+ # workflow_run cannot key on PR number until after artifact parse, so it
+ # falls back to the upstream run id. Same constraint as pr-triage-apply.
+ group: ${{ github.workflow }}-${{ github.event.workflow_run.id }}
+ cancel-in-progress: false
+
+jobs:
+ unmark:
+ if: github.event.workflow_run.conclusion == 'success'
+ runs-on: ubuntu-latest
+ timeout-minutes: 2
+ steps:
+ - name: Download triage event artifact
+ uses: actions/download-artifact@v8
+ with:
+ name: triage-event
+ run-id: ${{ github.event.workflow_run.id }}
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ path: payload/
+
+ - name: Extract PR number
+ run: |
+ set -euo pipefail
+ shopt -s nullglob
+ # The artifact contains exactly one file: the JSON event payload
+ # uploaded as ${{ github.event_path }}. Its on-disk name is
+ # whatever the runner used; resolve it dynamically.
+ payload=( payload/*.json payload/event.json )
+ f=""
+ for candidate in "${payload[@]}"; do
+ [[ -f "$candidate" ]] && f="$candidate" && break
+ done
+ if [[ -z "$f" ]]; then
+ echo "triage payload not found under payload/" >&2
+ ls -la payload/ >&2 || true
+ exit 1
+ fi
+ pr=$(jq -r '.pull_request.number // .issue.number // ""' "$f")
+ if [[ -z "$pr" ]]; then
+ echo "no PR number in payload" >&2
+ exit 1
+ fi
+ echo "PR_NUMBER=$pr" >> "$GITHUB_ENV"
+
+ - name: Remove stale label if present
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ PR_NUMBER: ${{ env.PR_NUMBER }}
+ REPO: ${{ github.repository }}
+ # Pre-check via REST so we only invoke the GraphQL edit when the
+ # label is actually on the PR. Saves an API write on every drive-by
+ # comment that is far more common than a comment on a stale PR.
+ # The edit itself is idempotent (GraphQL removeLabelsFromLabelable
+ # succeeds whether or not the label is set), so the gate is purely
+ # a cost optimization.
+ run: |
+ set -euo pipefail
+ if gh api "repos/$REPO/issues/$PR_NUMBER/labels" \
+ --jq '.[].name' | grep -qx S-stale; then
+ gh pr edit "$PR_NUMBER" --repo "$REPO" --remove-label S-stale
+ else
+ echo "PR #$PR_NUMBER has no S-stale label, skipping"
+ fi
diff --git a/.github/workflows/stale-prs-unmark.yml
b/.github/workflows/stale-prs-unmark.yml
new file mode 100644
index 000000000..92fea53aa
--- /dev/null
+++ b/.github/workflows/stale-prs-unmark.yml
@@ -0,0 +1,54 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Removes the S-stale label on contributor push / reopen / ready_for_review.
+# Companion to stale-prs.yml which runs with remove-stale-when-updated:false
+# to stop the stale bot from unmarking its own label on the next cron run.
+#
+# Comment- and review-driven unmark is handled separately by
+# stale-prs-unmark-on-activity.yml because issue_comment and
+# pull_request_review on cross-fork PRs deliver a read-only GITHUB_TOKEN.
+
+name: Unmark Stale PRs
+
+on:
+ pull_request_target:
+ types: [synchronize, reopened, ready_for_review]
+
+permissions:
+ pull-requests: write
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
+ cancel-in-progress: true
+
+jobs:
+ unmark:
+ runs-on: ubuntu-latest
+ timeout-minutes: 2
+ if: contains(github.event.pull_request.labels.*.name, 'S-stale')
+ steps:
+ - name: Remove stale label
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ PR_NUMBER: ${{ github.event.pull_request.number }}
+ REPO: ${{ github.repository }}
+ # gh pr edit --remove-label uses GraphQL removeLabelsFromLabelable
+ # which is idempotent: succeeds whether or not the label is on the
+ # PR at API time. Avoids the 404 race with the bot or a parallel
+ # run removing the label between event delivery and step run.
+ run: gh pr edit "$PR_NUMBER" --repo "$REPO" --remove-label S-stale
diff --git a/.github/workflows/stale-prs.yml b/.github/workflows/stale-prs.yml
index d5745e919..ab2c1d827 100644
--- a/.github/workflows/stale-prs.yml
+++ b/.github/workflows/stale-prs.yml
@@ -33,7 +33,8 @@ jobs:
with:
days-before-pr-stale: 7
days-before-pr-close: 7
- stale-pr-label: "stale"
+ stale-pr-label: "S-stale"
+ remove-stale-when-updated: false
stale-pr-message: >
This pull request has been automatically marked as stale because
it has not had recent activity. It will be closed in 7 days if
@@ -42,7 +43,7 @@ jobs:
If you need a review, please ensure CI is green and the PR is
rebased
on the latest master. Don't hesitate to ping the maintainers -
either
- @core on Discord or by mentioning them directly here on the PR.
+ `@core` on Discord or by mentioning them directly here on the PR.
Thank you for your contribution!