Windows-local test runner: 13 tests fail due to platform differences #78
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Approved Issues Only | |
| on: | |
| issues: | |
| types: [opened, reopened] | |
| permissions: | |
| issues: write | |
| contents: read | |
| env: | |
| UNAPPROVED_LABEL: unapproved | |
| UNAPPROVED_ISSUE_COMMENT: "This repository is invite-only. Issues from unapproved actors are automatically closed." | |
| APPROVED_ACTORS_FILE: .github/approved-actors.yml | |
| jobs: | |
| enforce-approved-issues: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Enforce invite-only issue participation | |
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd | |
| with: | |
| script: | | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const issue_number = context.payload.issue.number; | |
| const opener = context.payload.issue.user.login; | |
| const label = process.env.UNAPPROVED_LABEL; | |
| const comment = process.env.UNAPPROVED_ISSUE_COMMENT; | |
| const whitelistPath = process.env.APPROVED_ACTORS_FILE; | |
| async function loadWhitelist() { | |
| try { | |
| const { data } = await github.request( | |
| "GET /repos/{owner}/{repo}/contents/{path}", | |
| { owner, repo, path: whitelistPath } | |
| ); | |
| if (!data?.content) return new Set(); | |
| const text = Buffer.from(data.content, "base64").toString("utf8"); | |
| const users = []; | |
| let inUsers = false; | |
| for (const raw of text.split(/\r?\n/)) { | |
| const line = raw.trim(); | |
| if (!line || line.startsWith("#")) continue; | |
| if (line === "users:" || line.startsWith("users:")) { | |
| inUsers = true; | |
| continue; | |
| } | |
| if (inUsers && line.startsWith("- ")) { | |
| users.push(line.slice(2).trim()); | |
| continue; | |
| } | |
| if (inUsers && !line.startsWith("- ")) { | |
| break; | |
| } | |
| } | |
| return new Set(users); | |
| } catch (error) { | |
| core.warning(`Unable to read ${whitelistPath}: ${error.message}`); | |
| return new Set(); | |
| } | |
| } | |
| const whitelist = await loadWhitelist(); | |
| const whitelisted = whitelist.has(opener); | |
| let collaborator = false; | |
| try { | |
| const resp = await github.request( | |
| "GET /repos/{owner}/{repo}/collaborators/{username}", | |
| { owner, repo, username: opener } | |
| ); | |
| collaborator = resp.status === 204; | |
| } catch (error) { | |
| if (error.status !== 404) { | |
| core.warning(`Collaborator check returned ${error.status}: ${error.message}`); | |
| } | |
| collaborator = false; | |
| } | |
| const approved = collaborator || whitelisted; | |
| if (approved) { | |
| core.info(`${opener} is approved (collaborator=${collaborator}, whitelisted=${whitelisted}); no action needed.`); | |
| return; | |
| } | |
| try { | |
| await github.request("GET /repos/{owner}/{repo}/labels/{name}", { | |
| owner, | |
| repo, | |
| name: label, | |
| }); | |
| } catch (error) { | |
| if (error.status === 404) { | |
| try { | |
| await github.request("POST /repos/{owner}/{repo}/labels", { | |
| owner, | |
| repo, | |
| name: label, | |
| color: "B60205", | |
| description: "Issue or PR opened by a non-collaborator in invite-only participation mode", | |
| }); | |
| } catch (createError) { | |
| if (createError.status !== 422) { | |
| throw createError; | |
| } | |
| } | |
| } else { | |
| throw error; | |
| } | |
| } | |
| await github.request("POST /repos/{owner}/{repo}/issues/{issue_number}/labels", { | |
| owner, | |
| repo, | |
| issue_number, | |
| labels: [label], | |
| }); | |
| await github.request("POST /repos/{owner}/{repo}/issues/{issue_number}/comments", { | |
| owner, | |
| repo, | |
| issue_number, | |
| body: comment, | |
| }); | |
| await github.request("PATCH /repos/{owner}/{repo}/issues/{issue_number}", { | |
| owner, | |
| repo, | |
| issue_number, | |
| state: "closed", | |
| }); |