Skip to content

Commit a8129c3

Browse files
authored
Merge pull request #1663 from Kobzol/artifacts
Add dry run workflow for testing the applied changes
2 parents 3577528 + 995b3e8 commit a8129c3

File tree

2 files changed

+178
-1
lines changed

2 files changed

+178
-1
lines changed

.github/workflows/dry-run.yml

+166
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# This workflow executes a dry-run of the sync-team tool after a push to any pull request.
2+
# This allows us to see which changes would be applied to live services after the PR
3+
# would be merged.
4+
#
5+
# The workflow uses the `workflow_run` trigger, which should always run in the default branch of
6+
# this repository. This is required so that the workflow has permissions to post PR comments.
7+
# We should not check out any code from the PR, as it could present a security hazard.
8+
# Instead, we simply download a GitHub artifact with a directory of JSON files and use that as
9+
# input for sync-team.
10+
# This artifact is created and uploaded on PR pushes using the CI workflow in `main.yml`.
11+
# Details about `workflow_run`:
12+
# https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_run:
13+
name: sync-team dry-run
14+
15+
on:
16+
workflow_run:
17+
workflows: [ CI ]
18+
types:
19+
- completed
20+
21+
concurrency:
22+
# Only run this once at a time on any given PR
23+
group: dry-run-${{ github.event.workflow_run.pull_requests[0].number }}
24+
cancel-in-progress: true
25+
26+
jobs:
27+
dry-run:
28+
runs-on: ubuntu-latest
29+
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' }}
30+
permissions:
31+
pull-requests: write
32+
steps:
33+
- uses: actions/checkout@v4
34+
with:
35+
repository: rust-lang/sync-team
36+
persist-credentials: false
37+
38+
- name: Install Rust Stable
39+
run: |
40+
rustc -vV
41+
rustup update stable
42+
rustup default stable
43+
rustc -vV
44+
45+
- uses: Swatinem/rust-cache@v2
46+
47+
- name: Download built JSON API
48+
uses: actions/download-artifact@v4
49+
with:
50+
name: team-api-output
51+
path: team-api
52+
run-id: ${{ github.event.workflow_run.id }}
53+
github-token: ${{ secrets.GITHUB_TOKEN }}
54+
55+
# GitHub tokens generated from GitHub Apps can access resources from one organization,
56+
# so we need to generate a token for each organization.
57+
- name: Generate GitHub token (rust-lang)
58+
uses: actions/create-github-app-token@v1
59+
id: rust-lang-token
60+
with:
61+
# GitHub App ID secret name
62+
app-id: ${{ secrets.SYNC_TEAM_GH_APP_ID }}
63+
# GitHub App private key secret name
64+
private-key: ${{ secrets.SYNC_TEAM_GH_APP_PRIVATE_KEY }}
65+
# Set the owner, so the token can be used in all repositories
66+
owner: rust-lang
67+
68+
- name: Generate GitHub token (rust-lang-ci)
69+
uses: actions/create-github-app-token@v1
70+
id: rust-lang-ci-token
71+
with:
72+
app-id: ${{ secrets.SYNC_TEAM_GH_APP_ID }}
73+
private-key: ${{ secrets.SYNC_TEAM_GH_APP_PRIVATE_KEY }}
74+
owner: rust-lang-ci
75+
76+
- name: Generate GitHub token (rust-lang-deprecated)
77+
uses: actions/create-github-app-token@v1
78+
id: rust-lang-deprecated-token
79+
with:
80+
app-id: ${{ secrets.SYNC_TEAM_GH_APP_ID }}
81+
private-key: ${{ secrets.SYNC_TEAM_GH_APP_PRIVATE_KEY }}
82+
owner: rust-lang-deprecated
83+
84+
- name: Generate GitHub token (rust-lang-nursery)
85+
uses: actions/create-github-app-token@v1
86+
id: rust-lang-nursery-token
87+
with:
88+
app-id: ${{ secrets.SYNC_TEAM_GH_APP_ID }}
89+
private-key: ${{ secrets.SYNC_TEAM_GH_APP_PRIVATE_KEY }}
90+
owner: rust-lang-nursery
91+
92+
- name: Generate GitHub token (bors-rs)
93+
uses: actions/create-github-app-token@v1
94+
id: bors-rs-token
95+
with:
96+
app-id: ${{ secrets.SYNC_TEAM_GH_APP_ID }}
97+
private-key: ${{ secrets.SYNC_TEAM_GH_APP_PRIVATE_KEY }}
98+
owner: bors-rs
99+
100+
- name: Generate GitHub token (rust-analyzer)
101+
uses: actions/create-github-app-token@v1
102+
id: rust-analyzer-token
103+
with:
104+
app-id: ${{ secrets.SYNC_TEAM_GH_APP_ID }}
105+
private-key: ${{ secrets.SYNC_TEAM_GH_APP_PRIVATE_KEY }}
106+
owner: rust-analyzer
107+
108+
- name: Generate GitHub token (rust-embedded)
109+
uses: actions/create-github-app-token@v1
110+
id: rust-embedded-token
111+
with:
112+
app-id: ${{ secrets.SYNC_TEAM_GH_APP_ID }}
113+
private-key: ${{ secrets.SYNC_TEAM_GH_APP_PRIVATE_KEY }}
114+
owner: rust-embedded
115+
116+
- name: Generate GitHub token (rust-dev-tools)
117+
uses: actions/create-github-app-token@v1
118+
id: rust-dev-tools-token
119+
with:
120+
app-id: ${{ secrets.SYNC_TEAM_GH_APP_ID }}
121+
private-key: ${{ secrets.SYNC_TEAM_GH_APP_PRIVATE_KEY }}
122+
owner: rust-dev-tools
123+
124+
- name: Run sync-team dry-run check
125+
env:
126+
GITHUB_TOKEN_RUST_LANG: ${{ steps.rust-lang-token.outputs.token }}
127+
GITHUB_TOKEN_RUST_LANG_CI: ${{ steps.rust-lang-ci-token.outputs.token }}
128+
GITHUB_TOKEN_RUST_LANG_DEPRECATED: ${{ steps.rust-lang-deprecated-token.outputs.token }}
129+
GITHUB_TOKEN_RUST_LANG_NURSERY: ${{ steps.rust-lang-nursery-token.outputs.token }}
130+
GITHUB_TOKEN_BORS_RS: ${{ steps.bors-rs-token.outputs.token }}
131+
GITHUB_TOKEN_RUST_ANALYZER: ${{ steps.rust-analyzer-token.outputs.token }}
132+
GITHUB_TOKEN_RUST_EMBEDDED: ${{ steps.rust-embedded-token.outputs.token }}
133+
GITHUB_TOKEN_RUST_DEV_TOOLS: ${{ steps.rust-dev-tools-token.outputs.token }}
134+
run: |
135+
# Perform build and execution separately to avoid any potential output from
136+
# cargo leaking into the output file.
137+
cargo build ./target/debug/sync-team print-plan --services github --team-json team-api > output.txt
138+
139+
- name: Prepare comment
140+
run: |
141+
cat > comment.txt << EOL
142+
<details>
143+
<summary>Dry-run check results</summary>
144+
<pre><code>
145+
EOL
146+
cat output.txt >> comment.txt
147+
printf "</pre></code>\n</details>\n" >> comment.txt
148+
149+
cat comment.txt
150+
151+
- name: Send comment
152+
env:
153+
GH_TOKEN: ${{ github.token }}
154+
run: |
155+
PR=${{ github.event.workflow_run.pull_requests[0].number }}
156+
157+
# --edit-last doesn't work if there is no previous comment, so we have to figure out
158+
# if we should create a comment or not
159+
if gh issue view ${PR} --json comments \
160+
--jq '.comments.[].author.login' | grep --quiet --fixed-strings "github-actions"; then
161+
echo "Editing comment"
162+
gh pr comment ${PR} --body-file comment.txt --edit-last
163+
else
164+
echo "Creating new comment"
165+
gh pr comment ${PR} --body-file comment.txt
166+
fi

.github/workflows/main.yml

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
on: [push, pull_request]
1+
name: CI
2+
3+
on: [ push, pull_request ]
24

35
jobs:
46
ci:
@@ -20,6 +22,8 @@ jobs:
2022
rustup default stable
2123
rustc -vV
2224
25+
- uses: Swatinem/rust-cache@v2
26+
2327
- name: Build the validation tool
2428
run: cargo build
2529

@@ -39,6 +43,13 @@ jobs:
3943
cargo run -- static-api build
4044
echo "team-api.infra.rust-lang.org" > build/CNAME
4145
46+
- name: Upload the built JSON as a GitHub artifact
47+
if: ${{ github.event_name == 'pull_request' }}
48+
uses: actions/upload-artifact@v4
49+
with:
50+
name: team-api-output
51+
path: build
52+
4253
- name: Deploy to GitHub Pages
4354
run: |
4455
touch build/.nojekyll

0 commit comments

Comments
 (0)