From 50dcba8004cc5d4c18857ba3f1bd98fcddfb68c5 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 9 Jun 2026 02:05:41 +0000 Subject: [PATCH 1/3] Add workflow to lock new SEP proposal PRs and guide authors to Discussions When a PR adds a new file under ecosystem/, it is likely proposing a new SEP. This workflow locks the PR and comments explaining that new ideas should start as a GitHub Discussion, be collaborated on by the ecosystem, and only then be merged by a maintainer who assigns the SEP number. Includes a reminder to never pre-allocate SEP numbers. --- .github/workflows/new-sep-proposal.yml | 89 ++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 .github/workflows/new-sep-proposal.yml diff --git a/.github/workflows/new-sep-proposal.yml b/.github/workflows/new-sep-proposal.yml new file mode 100644 index 000000000..bed7215a1 --- /dev/null +++ b/.github/workflows/new-sep-proposal.yml @@ -0,0 +1,89 @@ +name: 'New SEP Proposal' + +# When a PR adds a new file to the ecosystem/ directory it is likely proposing a +# new SEP. New ideas are meant to start as a GitHub Discussion rather than a PR, +# so this workflow locks the PR and explains the process to the author. +# +# Uses pull_request_target so the GITHUB_TOKEN has write access even for PRs +# opened from forks. No untrusted PR code is checked out or executed; the job +# only inspects the list of changed files via the API. + +on: + pull_request_target: + types: [opened, reopened] + paths: + - 'ecosystem/**' + +permissions: + issues: write + pull-requests: write + +jobs: + new-sep-proposal: + runs-on: ubuntu-latest + steps: + - name: Lock PR and explain SEP proposal process + uses: actions/github-script@v7 + with: + script: | + const { owner, repo } = context.repo; + const pull_number = context.payload.pull_request.number; + + // Find files added (not just modified) under ecosystem/. + const files = await github.paginate(github.rest.pulls.listFiles, { + owner, + repo, + pull_number, + per_page: 100, + }); + + const newSepFiles = files.filter( + (f) => + f.status === 'added' && + f.filename.startsWith('ecosystem/') && + f.filename.endsWith('.md') && + f.filename !== 'ecosystem/README.md' + ); + + if (newSepFiles.length === 0) { + core.info('No new files added under ecosystem/; nothing to do.'); + return; + } + + const discussionsUrl = `https://github.com/${owner}/${repo}/discussions`; + + const body = [ + '👋 Thanks for your contribution!', + '', + 'It looks like this PR is proposing a **new SEP** — it adds the following new file(s) to the `ecosystem/` directory:', + '', + ...newSepFiles.map((f) => `- \`${f.filename}\``), + '', + 'New SEP ideas start as a **discussion**, not a pull request, so I have **locked this PR** for now.', + '', + '### How the SEP process works', + '', + `1. 💬 **Start a discussion.** Discussion for new ideas happens on [GitHub Discussions](${discussionsUrl}). Please start a discussion there about your idea and proposal so people in the Stellar ecosystem can collaborate on it.`, + '2. 🤝 **Collaborate.** Iterate on the proposal with the community in that discussion.', + '3. ✅ **Request a merge.** Once the proposal has been collaborated on by other people in the Stellar ecosystem, post in your GitHub Discussion asking for this PR to be merged. A maintainer will then unlock this PR, review it for formatting, **assign a SEP number**, and merge it.', + '', + '> ⚠️ **Never pre-allocate a SEP number in your PR.** A maintainer will assign the SEP number — please do not pick one yourself.', + '', + 'Thanks for helping improve the Stellar ecosystem! 🚀', + ].join('\n'); + + await github.rest.issues.createComment({ + owner, + repo, + issue_number: pull_number, + body, + }); + + await github.rest.issues.lock({ + owner, + repo, + issue_number: pull_number, + lock_reason: 'resolved', + }); + + core.info(`Locked PR #${pull_number} and posted the SEP proposal guidance.`); From 9d0b0bece0d059cdaa72dd4f3fbc77a56e369896 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 9 Jun 2026 04:50:53 +0000 Subject: [PATCH 2/3] Link SEP proposal comment to ecosystem README process and status sections Reference the canonical SEP process docs in ecosystem/README.md using anchored links (Contribution Process, Pre-SEP discussion, Creating a SEP Draft, SEP Status Terms), and point at the correct org-level GitHub Discussions category for SEPs. --- .github/workflows/new-sep-proposal.yml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/workflows/new-sep-proposal.yml b/.github/workflows/new-sep-proposal.yml index bed7215a1..606465840 100644 --- a/.github/workflows/new-sep-proposal.yml +++ b/.github/workflows/new-sep-proposal.yml @@ -50,7 +50,12 @@ jobs: return; } - const discussionsUrl = `https://github.com/${owner}/${repo}/discussions`; + // Link to the SEP process docs in ecosystem/README.md, anchored to + // the specific sections that explain the flow and statuses. + const defaultBranch = context.payload.repository.default_branch; + const readmeUrl = `https://github.com/${owner}/${repo}/blob/${defaultBranch}/ecosystem/README.md`; + const discussionsUrl = + 'https://github.com/orgs/stellar/discussions/categories/stellar-ecosystem-proposals'; const body = [ '👋 Thanks for your contribution!', @@ -59,15 +64,17 @@ jobs: '', ...newSepFiles.map((f) => `- \`${f.filename}\``), '', - 'New SEP ideas start as a **discussion**, not a pull request, so I have **locked this PR** for now.', + `New SEP ideas start as a **discussion**, not a pull request, so I have **locked this PR** for now. The full process, including how SEP statuses work, is documented in the [SEP Contribution Process](${readmeUrl}#contribution-process).`, '', '### How the SEP process works', '', - `1. 💬 **Start a discussion.** Discussion for new ideas happens on [GitHub Discussions](${discussionsUrl}). Please start a discussion there about your idea and proposal so people in the Stellar ecosystem can collaborate on it.`, - '2. 🤝 **Collaborate.** Iterate on the proposal with the community in that discussion.', + `1. 💬 **Start a discussion.** Per [Pre-SEP (Initial Discussion)](${readmeUrl}#pre-sep-initial-discussion), discussion for new ideas happens on [GitHub Discussions](${discussionsUrl}). Please start a discussion there about your idea and proposal so people in the Stellar ecosystem can collaborate on it.`, + '2. 🤝 **Collaborate.** Iterate on the proposal with the community in that discussion until it is ready to become a draft. See [Creating a SEP Draft](' + readmeUrl + '#creating-a-sep-draft).', '3. ✅ **Request a merge.** Once the proposal has been collaborated on by other people in the Stellar ecosystem, post in your GitHub Discussion asking for this PR to be merged. A maintainer will then unlock this PR, review it for formatting, **assign a SEP number**, and merge it.', '', - '> ⚠️ **Never pre-allocate a SEP number in your PR.** A maintainer will assign the SEP number — please do not pick one yourself.', + `> ⚠️ **Never pre-allocate a SEP number in your PR.** Leave the SEP number as "To Be Assigned" — a maintainer will assign it on merge, as described in [Creating a SEP Draft](${readmeUrl}#creating-a-sep-draft).`, + '', + `For details on what each SEP status (Draft, FCP, Active, Final, …) means, see [SEP Status Terms](${readmeUrl}#sep-status-terms).`, '', 'Thanks for helping improve the Stellar ecosystem! 🚀', ].join('\n'); From b2a4a7f91e0935bd818a3bb90824781b70569d96 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 9 Jun 2026 07:10:19 +0000 Subject: [PATCH 3/3] Add idempotency guard and tighten permissions for SEP workflow Skip commenting and locking when guidance has already been posted (detected via a hidden marker in the comment body), so reopened PRs are not re-commented or re-locked and a maintainer's deliberate unlock is respected. Reduce the pull-requests token scope to read since listing changed files needs only read access and locking/commenting go through the issues API. --- .github/workflows/new-sep-proposal.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/new-sep-proposal.yml b/.github/workflows/new-sep-proposal.yml index 606465840..fac21c96e 100644 --- a/.github/workflows/new-sep-proposal.yml +++ b/.github/workflows/new-sep-proposal.yml @@ -16,7 +16,7 @@ on: permissions: issues: write - pull-requests: write + pull-requests: read jobs: new-sep-proposal: @@ -50,6 +50,20 @@ jobs: return; } + // Idempotency guard: if guidance has already been posted on this PR, + // do nothing. This avoids duplicate comments and re-lock errors when + // the workflow fires again (e.g. on reopened), and avoids re-locking + // a PR that a maintainer has deliberately unlocked. + const marker = ''; + const existingComments = await github.paginate( + github.rest.issues.listComments, + { owner, repo, issue_number: pull_number, per_page: 100 } + ); + if (existingComments.some((c) => c.body && c.body.includes(marker))) { + core.info('SEP proposal guidance already posted; nothing to do.'); + return; + } + // Link to the SEP process docs in ecosystem/README.md, anchored to // the specific sections that explain the flow and statuses. const defaultBranch = context.payload.repository.default_branch; @@ -58,6 +72,7 @@ jobs: 'https://github.com/orgs/stellar/discussions/categories/stellar-ecosystem-proposals'; const body = [ + marker, '👋 Thanks for your contribution!', '', 'It looks like this PR is proposing a **new SEP** — it adds the following new file(s) to the `ecosystem/` directory:',