Outlined experiment for OSS contribution gating.
PlanProvided GitHub Actions implementation for PR gating.
BuildVerified contributor roles via GitHub event payload.
UnderstandBootstrapped approved contributors list from merged PRs.
BuildFixed WASM loading and updated packaging scripts.
Edithere's an idea:
Strongly recommended reading by @tldraw on how to deal with OSS contributions in the age of agents.
I think I'm going to setup a little experiment in pi-mono along these lines, using a simple GH hook.
At no point is an approved contributor given access to the repo directly. The fine blog post alludes to the fact, that we may no longer need external contributions in code form. This possibly makes sense for established projects. But for new projects, code contributions are a signal.
I'm currently the only person with write access to the repo. Eventually I'd like to onboard high quality contributors, who I can trust not to slop up the code base, spreading out the load. Having them send actual code changes allows me to pick worthy individuals.
This aligns with the ideas expressed in @marlene_zw 's thread from yesterday by @giuseppegurgone
GitHub could actually introduce this concept of "approved PR submitter", but I suppose that'd take a while. A low tech solution like above seems simple enough to build and has good ergonomics.
tell me how we can implement this
The user wants to implement a GitHub webhook-based system for managing PR submissions from new contributors. Let me break down the requirements:
Implementation options:
GitHub Actions - Most straightforward, no external server needed
pull_request opened eventissue_comment eventExternal webhook server - More complex, requires hosting
GitHub Actions seems like the right choice here. Let me outline the implementation:
Files needed:
.github/APPROVED_CONTRIBUTORS - simple text file with one GitHub handle per line.github/workflows/pr-gate.yml - workflow to check PRs.github/workflows/approve-contributor.yml - workflow to add contributors when maintainer approvesLet me think through the logic:
PR Gate workflow:
pull_request types: [opened]Approve Contributor workflow:
Triggers on: issue_comment created
Checks if commenter is a maintainer/collaborator
Checks if comment contains magic phrase (e.g., "lgtm" or "/approve-contributor")
If both conditions are met, add the issue author to APPROVED_CONTRIBUTORS file
This approach keeps things simple—just GitHub Actions and a text file, no external infrastructure needed.
This is a solid approach. Here's how to implement it with GitHub Actions (no external server needed):
.github/APPROVED_CONTRIBUTORS - plain text file, one GitHub handle per line.github/workflows/pr-gate.yml - closes PRs from unapproved contributors.github/workflows/approve-contributor.yml - adds contributors when you comment a magic phrase on their issuePR Gate Logic:
pull_request: [opened]Approve Contributor Logic:
issue_comment: [created]/approve in commentEdge cases to handle:
GitHub Actions approach:
Alternative: GitHub App with webhook:
Want me to write the actual workflow files? The Actions approach is simpler to start with and can always be replaced later if needed.
do we have access to handles from people that are actually part of the repo contributor list? then anyone from the "team" can "lgtm"
The user is asking whether GitHub Actions can check if the person commenting is a collaborator/contributor with write access to the repo, so that any team member (not just the owner) can approve new contributors by commenting "lgtm".
Yes, this is possible. GitHub Actions provides context about the commenter, and you can use the GitHub API to check their permission level on the repo.
There are a few ways to do this:
github.event.comment.author_association - This gives you values like OWNER, MEMBER, COLLABORATOR, CONTRIBUTOR, etc. This is available directly in the event payload.
GitHub API call to check collaborator permissions - You can call GET /repos/{owner}/{repo}/collaborators/{username}/permission to get the exact permission level.
The author_association field is the simplest approach:
OWNER - Repository ownerMEMBER - Member of the organization that owns the repoCOLLABORATOR - Has been invited to collaborateCONTRIBUTOR - Has previously committed to the repo (but not necessarily a collaborator)FIRST_TIMER - First time contributorFIRST_TIME_CONTRIBUTOR - First contribution to this repoNONE - No associationFor this use case, we'd want to check for OWNER, MEMBER, or COLLABORATOR - these are people with actual repo access.
Let me give the user a concise answer.
Yes. GitHub provides author_association in the event payload for comments. Values include:
OWNER - repo ownerMEMBER - org member (if org repo)COLLABORATOR - invited collaboratorSo the workflow can check:
if: > contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association) && contains(github.event.comment.body, '/approve')Anyone you've added as a collaborator to the repo can then /approve on issues.
There's also a CONTRIBUTOR association (has previous commits merged), but that's weaker since it doesn't imply trust, just past contributions. Probably want to stick with the three above.
Want me to write the workflow files now?
we also need to bootstrap the approved list with gh accounts that previously got their PRs merged
The user wants to bootstrap the approved contributors list with people who have already had PRs merged to the repo. This makes sense - existing contributors shouldn't be blocked.
I can use the GitHub CLI to get this information. Let me check what contributors have had PRs merged to pi-mono.
I could use:
gh pr list --state merged --json author to get merged PR authorsgit log to get commit authorsLet me fetch this info first to show them who would be on the list.
Good point. Let me check who's already contributed:
>cd /Users/badlogic/workspaces/pi-mono && gh pr list --state merged --json author --jq '.[].author.login' | sort -uGood, I have the list of people who have had PRs merged. Now I can create:
Let me write these files. I should probably exclude badlogic from the approved list since they're the owner and will bypass the check anyway via the collaborator check. Actually, it doesn't hurt to include them.
Let me write all three files.
Got 19 contributors with merged PRs. Here's the full implementation:
/var/folders/49/l4171l3n219_xwq30fmyzr8w0000gn/T/TemporaryItems/NSIRD_screencaptureui_jP3SLl/Screenshot\ 2026-01-18\ at\ 11.53.17.png gh shows +80 contributors, so this list seems wrong
The user is saying that GitHub shows 80+ contributors, but my command only returned 19. The issue is that I only looked at merged PRs, but contributors can also contribute via direct commits (if they had access at some point) or other means.
Let me check the actual contributors list from the GitHub API or git log to get all contributors.
You're right, I only got PR authors. Let me check commit authors instead:
>cd /Users/badlogic/workspaces/pi-mono && git log --format='%aN <%aE>' | sort -u | wc -l>cd /Users/badlogic/workspaces/pi-mono && gh api repos/badlogic/pi-mono/contributors --paginate --jq '.[].login' | sort -uNow I have 82 contributors from the GitHub API. This is the correct list. Let me update the APPROVED_CONTRIBUTORS file with this list, excluding badlogic since they're the owner and will be skipped by the collaborator check anyway (though it doesn't hurt to include them).
That's 82 contributors from the GitHub API. Let me write the complete implementation:
I've written all three files. Let me summarize what was created and how it works.
Done. Three files created:
.github/APPROVED_CONTRIBUTORS - 81 existing contributors (excluding badlogic since you'll bypass as collaborator anyway)
.github/workflows/pr-gate.yml
pull_request_target (needed to have write access to close PRs from forks).github/workflows/approve-contributor.yml
OWNER, MEMBER, or COLLABORATOR comments /approve on an issueTo remove someone who abuses the privilege: just delete their line from APPROVED_CONTRIBUTORS manually.
You might also want a CONTRIBUTING.md that explains this process. Want me to add that?
i want lgtm to be the trigger word not /approved
The user wants to change the trigger word from /approve to lgtm. I need to update the approve-contributor.yml workflow.
I also need to update the PR close comment in pr-gate.yml that mentions /approve.
Also need to update the PR close message:
Done. Both files updated. The trigger word is now lgtm (case-insensitive since contains() is case-sensitive by default in GitHub Actions expressions, but the string literal will match if the comment contains "lgtm" anywhere).
Actually wait, contains() in GitHub Actions expressions IS case-insensitive. Let me double check... No, actually it's case-sensitive. So "LGTM" won't match "lgtm". The user might want case-insensitive matching.
Actually let me check the GitHub docs... The contains function in GitHub Actions is case-insensitive for strings. So "LGTM", "lgtm", "Lgtm" would all match. Good.
Done. Now any collaborator commenting lgtm (case-insensitive) on an issue will add that issue's author to the approved list.
do a deep review of the files we just wrote, identify any bugs or issues and report them here
Preparing to review full files
I'm planning to read three full files carefully to identify any issues before considering edits, following the instruction to review fully first.
Listing review notes and potential bugs
Identified several issues: the APPROVED_CONTRIBUTORS header wrongly mentions /approve; GitHub Actions' contains is case-insensitive but may need word boundaries to avoid false matches; pull_request_target permissions lack issues: write though it's needed; caution advised against checking out during pull_request_target; main branch is assumed but should use the repo's default branch dynamically; approved contributors list is static from main which might affect fork PRs; bot skipping logic may miss some bots; comment body indentation includes unintended spaces from templates; author_association values can misrepresent actual permissions especially for collaborators outside the org.
Reporting approval workflow issues
Found that approvals can come from org members without repo access due to missing collaborator permission checks; the lgtm trigger matches partial phrases like "not lgtm," risking false approvals; bot-authored issues can receive unintended approvals; the comment links to CONTRIBUTING.md may be problematic if missing; reopening PRs doesn't trigger checks for newly approved contributors; concurrent commits to the approved list lack conflict handling; commit success isn't verified before commenting; pull_request_target permissions lack needed contents: read and issues: write, causing API call failures; hardcoded main branch refs ignore repo default branches; and documentation wrongly states /approve in headers while referencing lgtm.
Deep review findings:
Wrong trigger text in header
.github/APPROVED_CONTRIBUTORS still says “commenting /approve” but the trigger is now lgtm.
pr-gate.yml permissions are too narrow
You set only pull-requests: write. The workflow also calls:
repos.getContent which needs contents: readissues.createComment which needs issues: writeapprove-contributor.yml uses author_association as a permission check
MEMBER can include org members with no repo access. That lets any org member approve contributors.
Better: call repos.getCollaboratorPermissionLevel and check for admin or write.
Default branch hardcoded to main
Both workflows read or checkout main. If the repo default branch changes, they break. Use context.payload.repository.default_branch or github.event.repository.default_branch.
lgtm matching is too loose
contains(..., 'lgtm') matches phrases like “not lgtm” or “lgtm? no”. If you want strict approval, use a regex for ^lgtm$ or a command like /lgtm.
PR close comment link is relative
../blob/main/CONTRIBUTING.md might not render correctly in issue comments. Use an absolute link.
If you want, I can fix these.
please fix
Refining approval workflow and file editing
I'm updating file editing to use full reads and edits rather than partial writes, adjusting header comments and permissions, and planning to modify the approval flow to always run on issue comment creation. I'll move author association checks into a GitHub script step for clarity, use a case-insensitive 'lgtm' check in the job condition to skip unnecessary runs, and add stricter regex validation in the script itself.
Defining strict LGTM check and permission gating
I'm adding a regex to strictly match 'lgtm' in comments and enforcing collaborator permission checks before proceeding. The PR gate workflow will use the repository's default branch dynamically and include precise permissions. For the approval workflow, I'll implement output flags from the script to conditionally run commit and comment steps, avoiding unnecessary actions when permissions or LGTM checks fail.
Recreating pipeline configuration
I'm preparing to rewrite the entire pr-gate.yml file with a complete, fresh configuration.
Refining contributor approval workflow
I'm rewriting the approval action to carefully handle outputs and conditional logic, adding try/catch around permission checks to treat non-collaborators as skipped, and ensuring correct checks for existing approvals before updating the approved list.
Adding conditional commit and comment steps
I'm implementing commit and comment steps that run only if a contributor was successfully added, avoiding duplicate approval comments by checking the update step's output.
Summarizing code changes
The changes update the comment to exactly match the LGTM format and involve no new tests. Next, I'll prepare further testing or documentation as needed.
Summary:
.github/APPROVED_CONTRIBUTORS header to say lgtm.pr-gate.yml permissions, default branch handling, and absolute CONTRIBUTING.md link.approve-contributor.yml with exact lgtm match, real collaborator permission check, default branch checkout, and guarded commit/comment steps.No tests run.
ok, now we also need a CONTRIBUTING.md or whatever is the defaulft file for that. ask me questions how it should look and what hsould be in it.
Confirming content details
What specific content or topic should I focus questions on?
What should CONTRIBUTING.md include? Please specify:
ask again opus you are better at writting
The user wants me to ask better, more thoughtful questions about what should go in the CONTRIBUTING.md file. Let me think about what I need to know to write a good one.
Key questions:
Let me ask these in a clear, direct way.
Questions for CONTRIBUTING.md:
The approval gate - Should this be front and center as the first thing people see, or buried in a "Before your first PR" section?
What makes a good issue? - You mentioned "concise, minimal description." Any specific structure you want (problem/solution format)? Examples of good vs bad issues?
AI/agent policy - Do you want to explicitly state expectations around AI-generated contributions? The PR gate message mentions "AI slop will be closed" but should the guide expand on what that means?
Technical requirements - Should contributors run npm run check before submitting? Any test expectations? Do you want them to update CHANGELOG.md or do maintainers handle that?
PR scope - Preferences on PR size? One issue per PR? Rebasing vs merge commits?
What's off-limits? - Any areas of the codebase where you don't want external contributions? Features you'll reject outright?
Communication style - Where should contributors ask questions if they're unsure (issues, discussions, Discord)?
Length/tone - Short and punchy, or thorough? Friendly, neutral, or "read this carefully or get rejected"?
biggest concern is: contributors must understand what the code changes do and how they interact with the rest of the system. just sending any old agent generated slop does not do.
The user wants a concise, punchy CONTRIBUTING.md that:
Let me write this.
I think that's short and punchy, explains the approval gate, emphasizes understanding your code, and covers the technical requirements. Let me wait for feedback.
Done. 1.2KB, fits on one screen, covers:
Want me to adjust anything?
yes, contributors should NOT add entries to CHANGELOG.md. that part is automated.
The user wants me to remove the mention about CHANGELOG.md from the CONTRIBUTING.md file. Let me check what I wrote... Actually, I don't think I mentioned CHANGELOG.md in the file I wrote. Let me re-read it.
Looking at the file I wrote, I don't see any mention of CHANGELOG.md. The user might be preemptively telling me this, or they might have misremembered. Let me clarify.
Actually wait, I should just confirm this is already the case. Let me re-read the file.
The file doesn't mention CHANGELOG.md at all. So there's nothing to remove. I should just confirm this with the user.
The CONTRIBUTING.md I wrote doesn't mention CHANGELOG.md at all. Contributors are only told to run npm run check and ./test.sh.
Did you want me to explicitly state "Do NOT edit CHANGELOG.md" to preempt people who might try?
re: undersatnd your code, it is fine to get that understanding by interrogating an agent with access to the code base until all edge cases and effects of the code change are understood by you
The user wants me to clarify that understanding your code can come from interrogating an agent with access to the codebase - you don't have to write it yourself or understand it from the start, but you need to understand it by the time you submit.
Done. Now the text clarifies that you can use an agent to help you understand the code changes, not just write them. The key is that by the time you submit, you understand what you're submitting.
Updated. Now clarifies that interrogating an agent to build understanding is a valid path.
changelog shit too please
The user wants me to add a note about not editing CHANGELOG.md.
Done. Added a note about not editing CHANGELOG.md.
Done.
if you create a contribution with an agent the agent must follow the rules and guidelines outlined in AGENTS.md. it is best to let your agent run in the pi-mono root dir so it picks up the AGENTS.md file automatically.
The user wants me to add a note about following AGENTS.md when using an agent to create contributions.
Done. Added the note about running agents from the pi-mono root directory and following AGENTS.md.
Done.
anything else missing?
Let me think about what might be missing from a typical CONTRIBUTING.md:
The main things I'd consider:
Actually, looking at the PR gate workflow - if someone's PR gets closed and then they get approved via an issue, they'd need to open a new PR. The old one won't automatically reopen or pass the check. This is a minor edge case but worth noting.
Let me ask about these potential gaps.
Looking at it:
License - No mention that contributions are licensed under the project's license. Some projects want this explicit.
Dev setup - No pointer to README for getting the project running locally. Assumed obvious?
Reopening closed PRs - If a new contributor's PR gets auto-closed, then they get approved via an issue, they need to open a new PR. The closed one won't pass the gate retroactively. Worth mentioning?
Commit message format - No conventions specified. Intentional?
Any of these worth adding, or keep it minimal?
keep it minimal commit and push both the CONTRIBUTING and README changes
The user wants me to commit and push the changes. Let me check what files have been changed - CONTRIBUTING.md (new file) and the workflow files. Wait, they said "CONTRIBUTING and README changes" but I don't think we made README changes. Let me check what's been modified.
Actually, I should check git status to see what files have been modified.
>cd /Users/badlogic/workspaces/pi-mono && git statusInteresting, README.md shows as modified but I don't remember modifying it. Let me check what changed. Actually, the user said "commit and push both the CONTRIBUTING and README changes" so maybe they made changes to README.md themselves or expect me to commit whatever is there.
Let me just add the specific files we created/modified and commit them.
>cd /Users/badlogic/workspaces/pi-mono && git diff README.md | head -50The README.md was modified to simplify the Development section and add a Contributing section that points to CONTRIBUTING.md and AGENTS.md. This looks like a good change that complements the new CONTRIBUTING.md file.
Let me commit all the relevant files:
>cd /Users/badlogic/workspaces/pi-mono && git add .github/APPROVED_CONTRIBUTORS .github/workflows/approve-contributor.yml .github/workflows/pr-gate.yml CONTRIBUTING.md README.md && git commit -m "chore: add PR approval gate for new contributors
- Add APPROVED_CONTRIBUTORS file with existing contributors
- Add pr-gate.yml workflow to close PRs from unapproved contributors
- Add approve-contributor.yml workflow to approve via lgtm on issues
- Add CONTRIBUTING.md with guidelines
- Update README.md to point to CONTRIBUTING.md"Committed successfully. Now let me push.
>cd /Users/badlogic/workspaces/pi-mono && git pushDone. Pushed successfully.
Done. Pushed 5 files:
.github/APPROVED_CONTRIBUTORS (81 contributors).github/workflows/pr-gate.yml.github/workflows/approve-contributor.ymlCONTRIBUTING.mdREADME.mdok, how can i test the gh workflows? i suppose i can create a new gh account?
The user wants to test the GitHub workflows. They're asking about creating a new GitHub account to simulate a new contributor. Let me think about the options:
New GitHub account - Would work, but annoying to manage. You'd submit a PR from that account, see it get closed, then open an issue, have your main account comment lgtm, then submit another PR.
Temporarily remove yourself from the approved list - Won't work because you're a collaborator, so you bypass the check anyway.
Use a GitHub Actions workflow_dispatch to test - Could add a test trigger but that's more complexity.
Use act - A tool that runs GitHub Actions locally. But it has limitations with pull_request_target and API calls.
Ask a friend/colleague - Have someone not on the approved list submit a test PR.
Use GitHub's "fork" approach - Fork from a throwaway account.
The simplest real test is indeed a second GitHub account. Or ask someone in the Discord to help test it.
Another option: temporarily comment out the collaborator check so you can test as yourself, then uncomment it. But that requires pushing changes, testing, then reverting.
Let me give the user the options.
Options:
New GitHub account - Simplest real test. Submit a PR, watch it close, open an issue, have your main account lgtm, submit another PR.
Ask someone on Discord - Have a non-contributor test it for you.
Temporarily disable the collaborator bypass - Comment out the collaborator check in pr-gate.yml, push, test as yourself, then revert. Quick but requires two extra commits.
Use act - Runs GitHub Actions locally, but struggles with pull_request_target and API calls. Not worth the hassle here.
The new account approach is cleanest since it tests the exact real-world flow. GitHub allows multiple accounts as long as they're not used to evade bans or abuse free tiers.
workflows fail, use gh cli to investigarte an fix them all
The user says the workflows are failing. Let me investigate using the GitHub CLI.
>cd /Users/badlogic/workspaces/pi-mono && gh run list --limit 10I can see that both new workflows failed. Let me get more details on each failure.
>cd /Users/badlogic/workspaces/pi-mono && gh run view 21110961559 --log 2>&1 | head -100>cd /Users/badlogic/workspaces/pi-mono && gh run view 21110961482 --log 2>&1 | head -100The logs are not found, probably because the runs were skipped or failed very early. Let me check more details about these runs.
>cd /Users/badlogic/workspaces/pi-mono && gh run view 21110961559>cd /Users/badlogic/workspaces/pi-mono && gh run view 21110961482Workflow file issues. Let me fetch more details via the API to see what's wrong.
>cd /Users/badlogic/workspaces/pi-mono && gh api repos/badlogic/pi-mono/actions/runs/21110961559 --jq '.conclusion, .status, .head_sha'>cd /Users/badlogic/workspaces/pi-mono && gh api repos/badlogic/pi-mono/actions/workflows --jq '.workflows[] | "\(.name): \(.state)"'The workflows are active but showing with their file paths instead of names. Let me check if there are syntax errors in the YAML files by validating them.
>cd /Users/badlogic/workspaces/pi-mono && cat .github/workflows/approve-contributor.yml | python3 -c "import yaml, sys; yaml.safe_load(sys.stdin); print('YAML valid')" 2>&1>cd /Users/badlogic/workspaces/pi-mono && cat .github/workflows/pr-gate.yml | python3 -c "import yaml, sys; yaml.safe_load(sys.stdin); print('YAML valid')" 2>&1Let me use a different approach - maybe use yq or just check the structure manually. Let me also fetch the actual error from GitHub's annotations API.
>cd /Users/badlogic/workspaces/pi-mono && gh api repos/badlogic/pi-mono/actions/runs/21110961559/annotations 2>&1>cd /Users/badlogic/workspaces/pi-mono && gh api repos/badlogic/pi-mono/actions/runs/21110961482/annotations 2>&1Let me try to get the jobs for these runs to see what the actual error is.
>cd /Users/badlogic/workspaces/pi-mono && gh api repos/badlogic/pi-mono/actions/runs/21110961559/jobs --jq '.jobs[] | {name: .name, status: .status, conclusion: .conclusion}'No jobs were even created. This suggests the workflow file itself has a syntax error that's preventing the workflow from being parsed. Let me re-read the workflow files to look for issues.
I see the issue! In the approve-contributor.yml file, line 8:
if: !github.event.issue.pull_requestIn YAML, ! is a tag indicator. So !github.event.issue.pull_request is being interpreted as a YAML tag, not a negation. This needs to be quoted or use a different syntax.
The correct way to write this in GitHub Actions is:
if: ${{ !github.event.issue.pull_request }}Or:
if: github.event.issue.pull_request == nullThe pr-gate.yml doesn't have this issue because it doesn't use ! in the job-level if.
Let me also check if there's the same issue in pr-gate.yml... No, it doesn't have a job-level if condition.
Let me fix the approve-contributor.yml file.
Found it. The issue is in approve-contributor.yml line 8:
if: !github.event.issue.pull_requestIn YAML, ! is a tag indicator, so this is being parsed as a YAML tag, not a boolean negation. Needs to be wrapped in ${{ }} or quoted.
Now let me check the pr-gate.yml file. Looking at it again, it seems okay - no job-level if that would cause issues. But I want to verify there are no other YAML parsing issues. Let me use node to parse it since we're in a node project.
>cd /Users/badlogic/workspaces/pi-mono && node -e "const yaml = require('yaml'); const fs = require('fs'); yaml.parse(fs.readFileSync('.github/workflows/approve-contributor.yml', 'utf8')); console.log('approve-contributor.yml: valid')" 2>&1>cd /Users/badlogic/workspaces/pi-mono && node -e "const yaml = require('yaml'); const fs = require('fs'); yaml.parse(fs.readFileSync('.github/workflows/pr-gate.yml', 'utf8')); console.log('pr-gate.yml: valid')" 2>&1There's a YAML issue in pr-gate.yml as well. The multiline string in the JavaScript code is being interpreted as YAML. Let me look at line 67 in the file. The issue is likely with the template literal in the JavaScript that contains newlines - but that should be fine inside a script: | block.
Wait, let me look at the pr-gate.yml file again. The script: | creates a literal block scalar, but there's something wrong with the structure. Let me check...
Actually, looking at the error message, it says "Implicit keys need to be on a single line at line 67". The issue might be indentation or the multiline message string.
Let me re-read the file and check line 67.
>cd /Users/badlogic/workspaces/pi-mono && head -80 .github/workflows/pr-gate.yml | tail -20 | cat -nI see - the multi-line template literal starts at a different indentation and the YAML parser is getting confused. However, this should be fine inside a | block...
Wait, let me check if the script: uses | properly or if there's an issue with the indentation. The standard way in GitHub Actions is script: | followed by properly indented JavaScript.
Let me look at the full structure of the pr-gate.yml file more carefully:
>cd /Users/badlogic/workspaces/pi-mono && head -20 .github/workflows/pr-gate.ymlThe script: | looks correct. The issue might be that the multi-line string in the JavaScript code has lines that start with no indentation (like "We ask new contributors..."). In YAML block scalars, the content should maintain consistent indentation relative to the indicator.Actually wait - the node yaml parser might be stricter than what GitHub Actions uses. Let me check if this is an actual parsing problem or just the node yaml library being strict.
Actually, let me try a different YAML validation approach - maybe use actionlint which is designed for GitHub Actions workflows.But actually, looking back at the gh run output - pr-gate.yml also failed with "This run likely failed because of a workflow file issue". So there IS an issue.
Looking at the script block - the message template literal contains lines with no leading whitespace (like "We ask new contributors..."). In YAML, when using a literal block scalar (|), lines need to be indented at least as much as the first content line. The JavaScript template literal with unindented lines could be causing issues.
Let me rewrite the message to be constructed differently, or ensure the indentation is consistent. Actually the safest approach is to build the message using string concatenation or array join instead of a multi-line template literal.
The multiline template literal in pr-gate.yml is confusing the YAML parser. The lines inside the template literal have no indentation, which breaks YAML's block scalar parsing. Let me fix it by constructing the message differently:
Now let me verify both files are valid YAML.
>cd /Users/badlogic/workspaces/pi-mono && node -e "const yaml = require('yaml'); const fs = require('fs'); yaml.parse(fs.readFileSync('.github/workflows/pr-gate.yml', 'utf8')); console.log('pr-gate.yml: valid')" 2>&1>cd /Users/badlogic/workspaces/pi-mono && node -e "const yaml = require('yaml'); const fs = require('fs'); yaml.parse(fs.readFileSync('.github/workflows/approve-contributor.yml', 'utf8')); console.log('approve-contributor.yml: valid')" 2>&1Both files are now valid YAML. Let me commit and push the fix.
Both valid now. Committing:
>cd /Users/badlogic/workspaces/pi-mono && git add .github/workflows/approve-contributor.yml .github/workflows/pr-gate.yml && git commit -m "fix: fix YAML parsing issues in PR gate workflows
- Wrap if condition in \${{ }} to avoid YAML tag interpretation
- Use array.join for multiline message to avoid block scalar issues"Good, committed. Now let me push.
>cd /Users/badlogic/workspaces/pi-mono && git pushDone. Let me wait a moment and then check if the workflows are now working.
>sleep 5 && cd /Users/badlogic/workspaces/pi-mono && gh run list --limit 5CI is running. The PR Gate and Approve Contributor workflows don't trigger on push events (they trigger on pull_request_target and issue_comment respectively), so we won't see them run from this push. But importantly, no new workflow file failures appeared. The workflows are syntactically correct now.
Let me verify that the workflows themselves are registered properly.
The workflows don't run on push (they're triggered by PRs and issue comments), so no new runs for them. But importantly, no new "workflow file issue" failures appeared.
Fixed issues:
approve-contributor.yml: Wrapped !github.event.issue.pull_request in ${{ }} to prevent YAML tag interpretationpr-gate.yml: Replaced multiline template literal with array.join('\n') to avoid YAML block scalar parsing issuesTo fully test, you'll need a PR from a non-approved account or an issue with an lgtm comment.
the gate works (at least closing and commenting, not sure yet if approval works)
the lgtm does not https://github.com/badlogic/pi-mono/actions/runs/21111411625/job/60710500105
Let me check that workflow run to see what went wrong.
>cd /Users/badlogic/workspaces/pi-mono && gh run view 21111411625 --log 2>&1The error is:
SyntaxError: Identifier 'core' has already been declaredThe actions/github-script action already provides core as a global variable, so when we do const core = require('@actions/core');, it conflicts. I need to remove that import since core is already available.
Let me fix the approve-contributor.yml file.
Found it. actions/github-script@v7 already provides core as a global variable. The line const core = require('@actions/core'); redeclares it.
Let me validate the YAML again and commit/push.
if: > contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association) && contains(github.event.comment.body, '/approve')if: !github.event.issue.pull_requestif: ${{ !github.event.issue.pull_request }}if: github.event.issue.pull_request == nullif: !github.event.issue.pull_requestSyntaxError: Identifier 'core' has already been declared