From d952cfbeddb0e9a6f7a850b31367fd9ed3c19892 Mon Sep 17 00:00:00 2001 From: ctcpip Date: Thu, 7 Aug 2025 14:16:21 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=9A=20fix=20CI=20runs=20for=20fork=20P?= =?UTF-8?q?Rs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fork PRs targeting main will never be able to pass integration tests or action-in-action due to the lack of permissions that fork action/workflow get: - it will not have write permission on the main repo - it will not have write permission on the wesleytodd/meeting-maker repo - it will not have write permission on its own repo because it's running in the main repo context therefore, if you want to see the integration tests and action-in-action test passing, then a PR needs to be created in the fork repo --- .github/workflows/test.yml | 15 +++++++++--- test/_close-issue.js | 7 ++++-- test/integration.js | 50 +++++++++++++++++++++++++++++++------- 3 files changed, 58 insertions(+), 14 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 24388c5..096b9fa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,6 +26,8 @@ jobs: testint: runs-on: ubuntu-latest + # only run if not a fork PR targeting main repo due to permissions + if: ${{ !(github.head_repo || github.event.pull_request.head.repo) || github.repository == (github.head_repo.full_name || github.event.pull_request.head.repo.full_name) }} steps: - uses: actions/checkout@v4 - name: Use Node.js 24 @@ -35,9 +37,13 @@ jobs: - run: npm install - run: npm run test:integration env: - GITHUB_TOKEN: ${{ secrets.INT_TEST_TOKEN }} + GITHUB_TOKEN: ${{ secrets.INT_TEST_TOKEN != '' && secrets.INT_TEST_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_HEAD_REPO: ${{ github.head_repo && github.head_repo.full_name || github.event.pull_request.head.repo.full_name || '' }} action-in-action: runs-on: ubuntu-latest + # only run if not a fork PR targeting main repo due to permissions + if: ${{ !(github.head_repo || github.event.pull_request.head.repo) || github.repository == (github.head_repo.full_name || github.event.pull_request.head.repo.full_name) }} steps: - uses: actions/checkout@v4 - name: Use Node.js 24 @@ -47,6 +53,9 @@ jobs: - run: npm install - uses: ./ id: maker + env: + TEST_REPOS: ${{ github.repository != 'pkgjs/meet' && github.repository || 'pkgjs/meet,pkgjs/meet' }} + TEST_ORGS: ${{ github.repository != 'pkgjs/meet' && '' || 'pkgjs' }} with: token: ${{ secrets.GITHUB_TOKEN }} schedules: 2020-04-02T17:00:00.0Z/P1D @@ -56,7 +65,7 @@ jobs: agendaLabel: meeting-agenda-test meetingLink: https://github.com/pkgjs/meet createNotes: true - repos: pkgjs/meet,pkgjs/meet - orgs: pkgjs + repos: ${{ env.TEST_REPOS }} + orgs: ${{ env.TEST_ORGS }} - name: clean up issue run: node ./test/_close-issue.js ${{ secrets.GITHUB_TOKEN }} ${{ steps.maker.outputs.issueNumber }} diff --git a/test/_close-issue.js b/test/_close-issue.js index 6931923..1b70ea4 100644 --- a/test/_close-issue.js +++ b/test/_close-issue.js @@ -6,10 +6,13 @@ const issues = require('../lib/issues') if (!issueNumber) { return } - console.log(`Closing test issue ${issueNumber}`) const client = getOctokit(token) + const repo = context.repo + + console.log(`Closing test issue ${issueNumber} in ${repo.owner}/${repo.repo}`) + await issues.closeIssue(client, issueNumber, { - ...context.repo + ...repo }) })(process.argv) diff --git a/test/integration.js b/test/integration.js index 347cc79..33d786b 100644 --- a/test/integration.js +++ b/test/integration.js @@ -11,15 +11,47 @@ const { getOctokit } = require('@actions/github') const pkg = require('../package.json') const meetings = require('../lib/meetings') +const mainRepo = 'pkgjs/meet' + +function getTestRepo () { + let testRepo = { owner: 'wesleytodd', repo: 'meeting-maker' } // ✨ Wes, the meeting maker ✨ + + if (process.env.GITHUB_REPOSITORY) { + // we appear to be in a GH action + if (process.env.GITHUB_REPOSITORY !== mainRepo) { + // action running in a fork + const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/') + testRepo = { owner, repo } + } else if (process.env.GITHUB_HEAD_REPO && + process.env.GITHUB_HEAD_REPO !== mainRepo) { + // action running in a fork PR targeting main repo + // skip tests - GH token doesn't have write permissions for either repo + throw new Error('skipping integration tests: fork PR targeting main repo (no permissions)') + } + } + + console.log(`using repository ${testRepo.owner}/${testRepo.repo}`) + return testRepo +} + suite(`${pkg.name} integration`, () => { let client + let testRepo + before(() => { - client = getOctokit(process.env.GITHUB_TOKEN) + const token = process.env.GITHUB_TOKEN + if (!token) { + throw new Error('GITHUB_TOKEN environment variable is required for integration tests') + } + + client = getOctokit(token) + testRepo = getTestRepo() }) + test('should create next meeting issue', async () => { const issue = await meetings.shouldCreateNextMeetingIssue(client, { - owner: 'wesleytodd', - repo: 'meeting-maker', + owner: testRepo.owner, + repo: testRepo.repo, issueTitle: ({ date }) => `Test Meeting ${date.toZonedDateTimeISO('UTC').toPlainDate().toString()}`, createWithin: 'P7D', agendaLabel: 'meeting-agenda', @@ -30,8 +62,8 @@ suite(`${pkg.name} integration`, () => { now: Temporal.Instant.from('2020-04-13T13:00:00.0Z'), meetingLabels: ['testMeeting', 'test'] }) - assert.deepStrictEqual(issue.owner, 'wesleytodd') - assert.deepStrictEqual(issue.repo, 'meeting-maker') + assert.deepStrictEqual(issue.owner, testRepo.owner) + assert.deepStrictEqual(issue.repo, testRepo.repo) assert.deepStrictEqual(issue.title, `Test Meeting ${Temporal.Instant.from('2020-04-16T13:00:00.0Z').toZonedDateTimeISO('UTC').toPlainDate().toString()}`) assert.deepStrictEqual(issue.agendaLabel, 'meeting-agenda') assert.deepStrictEqual(issue.labels, ['testMeeting', 'test']) @@ -41,8 +73,8 @@ suite(`${pkg.name} integration`, () => { test('create next meeting issue', async () => { const issue = await meetings.createNextMeeting(client, { - owner: 'wesleytodd', - repo: 'meeting-maker', + owner: testRepo.owner, + repo: testRepo.repo, createWithin: 'P7D', schedules: [ // 5pm GMT April 2 repeating every 28 days @@ -60,8 +92,8 @@ suite(`${pkg.name} integration`, () => { assert.deepStrictEqual(issue.data.state, 'open') await client.rest.issues.update({ - owner: 'wesleytodd', - repo: 'meeting-maker', + owner: testRepo.owner, + repo: testRepo.repo, issue_number: issue.data.number, state: 'closed' })