Skip to content

Commit bc58872

Browse files
authored
Merge pull request #42 from 1Password/andi/ok-to-test
Feature: allow forked PRs to access repo secrets after approval
2 parents f0baea0 + 726a3bb commit bc58872

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

.github/workflows/ok-to-test.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# If someone with write access comments "/ok-to-test" on a pull request, emit a repository_dispatch event
2+
name: Ok To Test
3+
4+
on:
5+
issue_comment:
6+
types: [created]
7+
8+
jobs:
9+
ok-to-test:
10+
runs-on: ubuntu-latest
11+
# required permissions for adding reactions to the pull request comments
12+
permissions:
13+
pull-requests: write
14+
# Only run for PRs, not issue comments
15+
if: ${{ github.event.issue.pull_request }}
16+
steps:
17+
- name: Slash Command Dispatch
18+
uses: peter-evans/slash-command-dispatch@v3
19+
with:
20+
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
21+
reaction-token: ${{ secrets.GITHUB_TOKEN }}
22+
issue-type: pull-request
23+
commands: ok-to-test
24+
# The repository permission level required by the user to dispatch commands. Only allows 1Password collaborators to run this.
25+
permission: write

.github/workflows/validate.yml

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ on:
88
pull_request:
99
paths-ignore:
1010
- '**.md'
11+
repository_dispatch:
12+
types: [ ok-to-test-command ]
1113

1214
jobs:
1315

14-
validate:
16+
integration-test-trusted:
17+
# actions that are trusted by default must only be opened from within the repo, and skipped for forks because they'll fail there
18+
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
1519
strategy:
1620
matrix:
1721
os: [ubuntu-latest, windows-latest, macos-latest]
@@ -49,3 +53,75 @@ jobs:
4953
pip install ruff
5054
ruff check --output-format=github --exclude=src/onepassword/lib/,example/ .
5155
continue-on-error: true
56+
57+
# This action is called by the /ok-to-test command, once the forked PR's code has been security reviewed.
58+
# It will checkout the forked (and now trusted) code and it will run the integration tests on it.
59+
# If the tests are successful this action will proceed to update the status of the forked PR integration check.
60+
integration-test-fork:
61+
# required permissions for updating the status of the pull request checks
62+
permissions:
63+
pull-requests: write
64+
checks: write
65+
strategy:
66+
matrix:
67+
os: [ubuntu-latest, windows-latest, macos-latest]
68+
runs-on: ${{ matrix.os }}
69+
if: |
70+
github.event_name == 'repository_dispatch' &&
71+
github.event.client_payload.slash_command.args.named.sha != '' &&
72+
contains(
73+
github.event.client_payload.pull_request.head.sha,
74+
github.event.client_payload.slash_command.args.named.sha
75+
)
76+
steps:
77+
78+
# Check out merge commit
79+
- name: Fork based /ok-to-test checkout
80+
uses: actions/checkout@v4
81+
with:
82+
ref: ${{ github.event.client_payload.pull_request.head.sha }}
83+
84+
- name: Set up Python
85+
uses: actions/setup-python@v4
86+
with:
87+
python-version: '3.x'
88+
89+
- name: Integration Test
90+
env:
91+
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.TEST_SERVICE_ACCOUNT_TOKEN }}
92+
run: |
93+
pip install pytest &&
94+
pip install pytest-asyncio &&
95+
pip install pydantic &&
96+
python -m pytest src/onepassword/test_client.py
97+
98+
- run: |
99+
echo "Integration tests completed successfully!"
100+
101+
# Update check run called "integration-fork" on the forked PR
102+
- uses: actions/github-script@v6
103+
id: update-check-run
104+
if: ${{ always() }}
105+
env:
106+
job: ${{ github.job }}
107+
ref: ${{ github.event.client_payload.pull_request.head.sha }}
108+
# Conveniently, job.status maps to https://developer.github.com/v3/checks/runs/#update-a-check-run
109+
conclusion: ${{ job.status }}
110+
with:
111+
github-token: ${{ secrets.GITHUB_TOKEN }}
112+
script: |
113+
const { data: checks } = await github.rest.checks.listForRef({
114+
...context.repo,
115+
process.env.ref
116+
});
117+
118+
const check = checks.check_runs.filter(c => c.name === process.env.job);
119+
120+
const { data: result } = await github.rest.checks.update({
121+
...context.repo,
122+
check_run_id: check[0].id,
123+
status: 'completed',
124+
conclusion: process.env.conclusion
125+
});
126+
127+
return result;

0 commit comments

Comments
 (0)