From 13181e0342ce8d21b2d8eb05dd938051f6dfdcee Mon Sep 17 00:00:00 2001 From: Phi Date: Wed, 22 Jan 2025 13:19:14 +0100 Subject: [PATCH 1/7] feat: workflow for marking old draft PRs as stale feat: workflow for marking old draft PRs as stale --- .github/workflows/stale-draft-prs.yml | 77 +++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 .github/workflows/stale-draft-prs.yml diff --git a/.github/workflows/stale-draft-prs.yml b/.github/workflows/stale-draft-prs.yml new file mode 100644 index 00000000000..3228ed7ab3a --- /dev/null +++ b/.github/workflows/stale-draft-prs.yml @@ -0,0 +1,77 @@ +name: Mark Stale Draft PRs + +on: + schedule: + # Run daily at midnight UTC + - cron: '0 0 * * *' + # Allow manual trigger + workflow_dispatch: + +jobs: + stale-draft: + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + - name: Check Draft PRs + uses: actions/github-script@v7 + with: + script: | + const now = new Date(); + const thirtyFiveMonthsAgo = new Date(now.setMonth(now.getMonth() - 35)); + + const query = `query($cursor: String) { + repository(owner: "${context.repo.owner}", name: "${context.repo.repo}") { + pullRequests(first: 100, after: $cursor, states: OPEN, isDraft: false) { + nodes { + number + createdAt + labels(first: 100) { + nodes { + name + } + } + } + pageInfo { + hasNextPage + endCursor + } + } + } + }`; + + async function getAllDraftPRs() { + let cursor = null; + let allPRs = []; + + while (true) { + const response = await github.graphql(query, { cursor }); + const prs = response.repository.pullRequests.nodes; + allPRs = allPRs.concat(prs); + + if (!response.repository.pullRequests.pageInfo.hasNextPage) { + break; + } + cursor = response.repository.pullRequests.pageInfo.endCursor; + } + + return allPRs; + } + + const prs = await getAllDraftPRs(); + + for (const pr of prs) { + const createdAt = new Date(pr.createdAt); + const hasStaleLabel = pr.labels.nodes.some(label => label.name === 'kind/stale'); + + if (createdAt < thirtyFiveMonthsAgo && !hasStaleLabel) { + console.log(`Adding stale label to PR #${pr.number}`); + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + labels: ['kind/stale'] + }); + } + } \ No newline at end of file From d3c4093cb6d88067272b2a09c9d5a5e255ed47eb Mon Sep 17 00:00:00 2001 From: Phi Date: Wed, 22 Jan 2025 13:43:54 +0100 Subject: [PATCH 2/7] feat: marking old draft PRs as stale feat: marking old draft PRs as stale --- .github/workflows/stale-draft-prs.yml | 77 --------------------------- .github/workflows/stale.yml | 2 + 2 files changed, 2 insertions(+), 77 deletions(-) delete mode 100644 .github/workflows/stale-draft-prs.yml diff --git a/.github/workflows/stale-draft-prs.yml b/.github/workflows/stale-draft-prs.yml deleted file mode 100644 index 3228ed7ab3a..00000000000 --- a/.github/workflows/stale-draft-prs.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: Mark Stale Draft PRs - -on: - schedule: - # Run daily at midnight UTC - - cron: '0 0 * * *' - # Allow manual trigger - workflow_dispatch: - -jobs: - stale-draft: - runs-on: ubuntu-latest - permissions: - pull-requests: write - - steps: - - name: Check Draft PRs - uses: actions/github-script@v7 - with: - script: | - const now = new Date(); - const thirtyFiveMonthsAgo = new Date(now.setMonth(now.getMonth() - 35)); - - const query = `query($cursor: String) { - repository(owner: "${context.repo.owner}", name: "${context.repo.repo}") { - pullRequests(first: 100, after: $cursor, states: OPEN, isDraft: false) { - nodes { - number - createdAt - labels(first: 100) { - nodes { - name - } - } - } - pageInfo { - hasNextPage - endCursor - } - } - } - }`; - - async function getAllDraftPRs() { - let cursor = null; - let allPRs = []; - - while (true) { - const response = await github.graphql(query, { cursor }); - const prs = response.repository.pullRequests.nodes; - allPRs = allPRs.concat(prs); - - if (!response.repository.pullRequests.pageInfo.hasNextPage) { - break; - } - cursor = response.repository.pullRequests.pageInfo.endCursor; - } - - return allPRs; - } - - const prs = await getAllDraftPRs(); - - for (const pr of prs) { - const createdAt = new Date(pr.createdAt); - const hasStaleLabel = pr.labels.nodes.some(label => label.name === 'kind/stale'); - - if (createdAt < thirtyFiveMonthsAgo && !hasStaleLabel) { - console.log(`Adding stale label to PR #${pr.number}`); - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.number, - labels: ['kind/stale'] - }); - } - } \ No newline at end of file diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 6b601f52a56..541bc1f7bf0 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -28,5 +28,7 @@ jobs: days-before-issue-close: 3 days-before-pr-stale: 5 days-before-pr-close: 3 + draft-days-before-stale: 1050 # 35 months * 30 days + draft-days-before-close: -1 # Don't automatically close draft PRs remove-stale-when-updated: true enable-statistics: true From af9517fb17b059fdb0c2b794251356c645820bd6 Mon Sep 17 00:00:00 2001 From: Phi Date: Wed, 22 Jan 2025 13:55:24 +0100 Subject: [PATCH 3/7] chore: add manual trigger chore: add manual trigger --- .github/workflows/stale.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 541bc1f7bf0..ba1cc4471f2 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -2,7 +2,8 @@ name: Close and mark stale issue on: schedule: - - cron: '0 12 * * *' + - cron: '0 12 * * *' + workflow_dispatch: permissions: contents: read From 3c0104a65ea77400a9153719e6324b9b2fd9e4d5 Mon Sep 17 00:00:00 2001 From: Phi Date: Mon, 27 Jan 2025 14:01:41 +0100 Subject: [PATCH 4/7] Revert "chore: add manual trigger" This reverts commit af9517fb17b059fdb0c2b794251356c645820bd6. --- .github/workflows/stale.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index ba1cc4471f2..541bc1f7bf0 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -2,8 +2,7 @@ name: Close and mark stale issue on: schedule: - - cron: '0 12 * * *' - workflow_dispatch: + - cron: '0 12 * * *' permissions: contents: read From 3e002a682b76e54a2199d5f97dcfd7cc7e2f91a5 Mon Sep 17 00:00:00 2001 From: Phi Date: Mon, 27 Jan 2025 14:22:16 +0100 Subject: [PATCH 5/7] ci: automate stale labeling for inactive draft PRs ci: automate stale labeling for inactive draft PRs --- .github/workflows/stale.yml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 541bc1f7bf0..d80932c3aab 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,8 +1,9 @@ -name: Close and mark stale issue +name: Close and mark stale issues, and draft PRs on: schedule: - cron: '0 12 * * *' + workflow_dispatch: permissions: contents: read @@ -32,3 +33,23 @@ jobs: draft-days-before-close: -1 # Don't automatically close draft PRs remove-stale-when-updated: true enable-statistics: true + + mark-stale-draft-prs: + permissions: + pull-requests: write + runs-on: ubuntu-latest + steps: + - name: Mark stale draft PRs + env: + GH_TOKEN: ${{ github.token }} + run: | + # Calculate cutoff date for last update (365 days ago) + cutoff_date=$(date -d "365 days ago" +%Y-%m-%d) + prs=$(gh pr list --repo $GITHUB_REPOSITORY --state open \ + --json number,updatedAt,isDraft \ + --jq ".[] | select(.isDraft) | select(.updatedAt < \"$cutoff_date\") | .number") + + for pr in $prs; do + echo "Marking PR #$pr as stale" + gh pr edit $pr --add-label "kind/stale" + done \ No newline at end of file From f9fe0cb64cbfdfd1456d707559e9e492a49c865e Mon Sep 17 00:00:00 2001 From: Phi Date: Mon, 27 Jan 2025 16:19:02 +0100 Subject: [PATCH 6/7] ci: indent properly ci: indent properly --- .github/workflows/stale.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d80932c3aab..bf25baf7256 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -43,13 +43,13 @@ jobs: env: GH_TOKEN: ${{ github.token }} run: | - # Calculate cutoff date for last update (365 days ago) - cutoff_date=$(date -d "365 days ago" +%Y-%m-%d) - prs=$(gh pr list --repo $GITHUB_REPOSITORY --state open \ - --json number,updatedAt,isDraft \ - --jq ".[] | select(.isDraft) | select(.updatedAt < \"$cutoff_date\") | .number") - - for pr in $prs; do - echo "Marking PR #$pr as stale" - gh pr edit $pr --add-label "kind/stale" - done \ No newline at end of file + # Calculate cutoff date for last update (365 days ago) + cutoff_date=$(date -d "365 days ago" +%Y-%m-%d) + prs=$(gh pr list --repo $GITHUB_REPOSITORY --state open \ + --json number,updatedAt,isDraft \ + --jq ".[] | select(.isDraft) | select(.updatedAt < \"$cutoff_date\") | .number") + + for pr in $prs; do + echo "Marking PR #$pr as stale" + gh pr edit $pr --add-label "kind/stale" + done \ No newline at end of file From d09714595e1cb2c9d43a218b2a166113dda1ec49 Mon Sep 17 00:00:00 2001 From: Phi Date: Mon, 27 Jan 2025 16:31:31 +0100 Subject: [PATCH 7/7] ci: update heading ci: update heading --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index bf25baf7256..9e99b7a71ce 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,4 +1,4 @@ -name: Close and mark stale issues, and draft PRs +name: Mark and close stale items on: schedule: