Skip to content

Commit 7596dc0

Browse files
ChrisGe4verbanicm
andauthored
Deploy centralized organization stale bot (#48)
<!-- Thank you for proposing a pull request! Please note that SOME TESTS WILL LIKELY FAIL due to how GitHub exposes secrets in Pull Requests from forks. Someone from the team will review your Pull Request and respond. Please describe your change and any implementation details below. --> - Deploy a centralized multi-repository stale bot utilizing GitHub's official `actions/stale` within a dynamic matrix workflow. - To prevent individual repositories from bypassing security standards, enforce Actionlint and Scorecard centrally using a GitHub Organization Ruleset. --------- Signed-off-by: Chris <chris.ge@live.com> Co-authored-by: Mike Verbanic <5046972+verbanicm@users.noreply.github.com>
1 parent 76c7c9d commit 7596dc0

4 files changed

Lines changed: 158 additions & 0 deletions

File tree

.github/workflows/actionlint.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: 'Actionlint'
2+
on:
3+
pull_request:
4+
workflow_dispatch:
5+
6+
permissions:
7+
contents: 'read'
8+
pull-requests: 'write'
9+
10+
concurrency:
11+
group: 'actionlint-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}'
12+
cancel-in-progress: true
13+
14+
jobs:
15+
lint:
16+
runs-on: 'ubuntu-latest'
17+
steps:
18+
- uses: 'actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd' # ratchet:actions/checkout@v6
19+
- name: 'Run actionlint with reviewdog'
20+
uses: 'reviewdog/action-actionlint@6fb7acc99f4a1008869fa8a0f09cfca740837d9d' # ratchet:reviewdog/action-actionlint@v1.72.0
21+
with:
22+
fail_level: 'error'
23+
reporter: 'github-pr-check'
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: 'Centralized Organization Stale Bot'
2+
permissions: {}
3+
on:
4+
schedule:
5+
# Run daily at 01:00 UTC
6+
- cron: '0 1 * * *'
7+
workflow_dispatch:
8+
9+
jobs:
10+
# Stage 1: Query the organization for all active repositories
11+
fetch-repositories:
12+
runs-on: 'ubuntu-latest'
13+
outputs:
14+
matrix: '${{ steps.set-matrix.outputs.repos }}'
15+
steps:
16+
- id: 'auth-minty'
17+
name: 'Authenticate to Google Cloud'
18+
uses: 'google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f' # ratchet:google-github-actions/auth@v2
19+
with:
20+
create_credentials_file: false
21+
export_environment_variables: false
22+
workload_identity_provider: '${{ vars.TOKEN_MINTER_WIF_PROVIDER }}'
23+
service_account: '${{ vars.TOKEN_MINTER_WIF_SERVICE_ACCOUNT }}'
24+
token_format: 'id_token'
25+
id_token_audience: '${{ vars.TOKEN_MINTER_SERVICE_AUDIENCE }}'
26+
id_token_include_email: true
27+
28+
- id: 'mint-github-token'
29+
uses: 'abcxyz/github-token-minter/.github/actions/minty@45c29ca3418ff3bb3ad5815d88a80536efeba21b' # ratchet:abcxyz/github-token-minter/.github/actions/minty@main
30+
with:
31+
id_token: '${{ steps.auth-minty.outputs.id_token }}'
32+
service_url: '${{ vars.TOKEN_MINTER_SERVICE_URL }}'
33+
requested_permissions: |-
34+
{
35+
"scope": "stale-bot",
36+
"repositories": ["*"],
37+
"org_name": "google-github-actions"
38+
}
39+
40+
- name: 'List active repositories'
41+
id: set-matrix
42+
env:
43+
GH_TOKEN: '${{ steps.mint-github-token.outputs.token }}'
44+
run: |
45+
# Query GitHub API for active, public, non-forked repositories and force single-line JSON to prevent GITHUB_OUTPUT truncation
46+
REPOS=$(gh api --paginate /orgs/google-github-actions/repos | jq -s 'add | [.[] | select(.archived == false and .private == false and .fork == false) | .name]' -c)
47+
echo "repos=${REPOS}" >> "$GITHUB_OUTPUT"
48+
49+
# Stage 2: Fan out official actions/stale across all discovered repositories
50+
apply-stale-rules:
51+
needs: fetch-repositories
52+
runs-on: 'ubuntu-latest'
53+
strategy:
54+
fail-fast: false
55+
matrix:
56+
repo: '${{ fromJson(needs.fetch-repositories.outputs.matrix) }}'
57+
58+
steps:
59+
- id: 'auth-minty'
60+
name: 'Authenticate to Google Cloud'
61+
uses: 'google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f' # ratchet:google-github-actions/auth@v2
62+
with:
63+
create_credentials_file: false
64+
export_environment_variables: false
65+
workload_identity_provider: '${{ vars.TOKEN_MINTER_WIF_PROVIDER }}'
66+
service_account: '${{ vars.TOKEN_MINTER_WIF_SERVICE_ACCOUNT }}'
67+
token_format: 'id_token'
68+
id_token_audience: '${{ vars.TOKEN_MINTER_SERVICE_AUDIENCE }}'
69+
id_token_include_email: true
70+
71+
- id: 'mint-github-token'
72+
uses: 'abcxyz/github-token-minter/.github/actions/minty@45c29ca3418ff3bb3ad5815d88a80536efeba21b' # ratchet:abcxyz/github-token-minter/.github/actions/minty@main
73+
with:
74+
id_token: '${{ steps.auth-minty.outputs.id_token }}'
75+
service_url: '${{ vars.TOKEN_MINTER_SERVICE_URL }}'
76+
requested_permissions: |-
77+
{
78+
"scope": "stale-bot",
79+
"repositories": ["${{ matrix.repo }}"],
80+
"org_name": "google-github-actions"
81+
}
82+
83+
- name: 'Run official stale bot'
84+
uses: 'actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f' # ratchet:actions/stale@v10.2.0
85+
env:
86+
GITHUB_REPOSITORY: 'google-github-actions/${{ matrix.repo }}'
87+
with:
88+
repo-token: '${{ steps.mint-github-token.outputs.token }}'
89+
operations-per-run: 300 # Increased burndown limit for first execution
90+
91+
# Issue configuration (60 days total: 53 inactive + 7 warning)
92+
days-before-issue-stale: 53
93+
days-before-issue-close: 7
94+
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs.'
95+
stale-issue-label: 'stale'
96+
97+
# PR configuration (30 days total: 23 inactive + 7 warning)
98+
days-before-pr-stale: 23
99+
days-before-pr-close: 7
100+
stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. Please leave a comment to remove this status.'
101+
stale-pr-label: 'stale'

.github/workflows/scorecard.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: 'Scorecard'
2+
on:
3+
pull_request:
4+
workflow_dispatch:
5+
6+
permissions: 'read-all'
7+
8+
jobs:
9+
analyze:
10+
runs-on: 'ubuntu-latest'
11+
permissions:
12+
contents: 'read'
13+
security-events: 'write'
14+
id-token: 'write'
15+
timeout-minutes: 20
16+
steps:
17+
- uses: 'actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd' # ratchet:actions/checkout@v6
18+
with:
19+
persist-credentials: false
20+
- name: 'Run Scorecard'
21+
uses: 'ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a' # ratchet:ossf/scorecard-action@v2.4.3
22+
with:
23+
results_file: 'results.sarif'
24+
results_format: 'sarif'
25+
publish_results: false
26+
- name: 'Upload to GitHub Security Tab'
27+
uses: 'github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13' # ratchet:github/codeql-action/upload-sarif@v4.35.1
28+
with:
29+
sarif_file: 'results.sarif'

.idea/.gitignore

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)