Skip to content

Commit dfc4480

Browse files
Guide new SEP proposals towards discussions first (#1949)
* 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. * 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. * 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.
1 parent 3f862c0 commit dfc4480

1 file changed

Lines changed: 111 additions & 0 deletions

File tree

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
name: 'New SEP Proposal'
2+
3+
# When a PR adds a new file to the ecosystem/ directory it is likely proposing a
4+
# new SEP. New ideas are meant to start as a GitHub Discussion rather than a PR,
5+
# so this workflow locks the PR and explains the process to the author.
6+
#
7+
# Uses pull_request_target so the GITHUB_TOKEN has write access even for PRs
8+
# opened from forks. No untrusted PR code is checked out or executed; the job
9+
# only inspects the list of changed files via the API.
10+
11+
on:
12+
pull_request_target:
13+
types: [opened, reopened]
14+
paths:
15+
- 'ecosystem/**'
16+
17+
permissions:
18+
issues: write
19+
pull-requests: read
20+
21+
jobs:
22+
new-sep-proposal:
23+
runs-on: ubuntu-latest
24+
steps:
25+
- name: Lock PR and explain SEP proposal process
26+
uses: actions/github-script@v7
27+
with:
28+
script: |
29+
const { owner, repo } = context.repo;
30+
const pull_number = context.payload.pull_request.number;
31+
32+
// Find files added (not just modified) under ecosystem/.
33+
const files = await github.paginate(github.rest.pulls.listFiles, {
34+
owner,
35+
repo,
36+
pull_number,
37+
per_page: 100,
38+
});
39+
40+
const newSepFiles = files.filter(
41+
(f) =>
42+
f.status === 'added' &&
43+
f.filename.startsWith('ecosystem/') &&
44+
f.filename.endsWith('.md') &&
45+
f.filename !== 'ecosystem/README.md'
46+
);
47+
48+
if (newSepFiles.length === 0) {
49+
core.info('No new files added under ecosystem/; nothing to do.');
50+
return;
51+
}
52+
53+
// Idempotency guard: if guidance has already been posted on this PR,
54+
// do nothing. This avoids duplicate comments and re-lock errors when
55+
// the workflow fires again (e.g. on reopened), and avoids re-locking
56+
// a PR that a maintainer has deliberately unlocked.
57+
const marker = '<!-- new-sep-proposal-guidance -->';
58+
const existingComments = await github.paginate(
59+
github.rest.issues.listComments,
60+
{ owner, repo, issue_number: pull_number, per_page: 100 }
61+
);
62+
if (existingComments.some((c) => c.body && c.body.includes(marker))) {
63+
core.info('SEP proposal guidance already posted; nothing to do.');
64+
return;
65+
}
66+
67+
// Link to the SEP process docs in ecosystem/README.md, anchored to
68+
// the specific sections that explain the flow and statuses.
69+
const defaultBranch = context.payload.repository.default_branch;
70+
const readmeUrl = `https://github.com/${owner}/${repo}/blob/${defaultBranch}/ecosystem/README.md`;
71+
const discussionsUrl =
72+
'https://github.com/orgs/stellar/discussions/categories/stellar-ecosystem-proposals';
73+
74+
const body = [
75+
marker,
76+
'👋 Thanks for your contribution!',
77+
'',
78+
'It looks like this PR is proposing a **new SEP** — it adds the following new file(s) to the `ecosystem/` directory:',
79+
'',
80+
...newSepFiles.map((f) => `- \`${f.filename}\``),
81+
'',
82+
`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).`,
83+
'',
84+
'### How the SEP process works',
85+
'',
86+
`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.`,
87+
'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).',
88+
'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.',
89+
'',
90+
`> ⚠️ **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).`,
91+
'',
92+
`For details on what each SEP status (Draft, FCP, Active, Final, …) means, see [SEP Status Terms](${readmeUrl}#sep-status-terms).`,
93+
'',
94+
'Thanks for helping improve the Stellar ecosystem! 🚀',
95+
].join('\n');
96+
97+
await github.rest.issues.createComment({
98+
owner,
99+
repo,
100+
issue_number: pull_number,
101+
body,
102+
});
103+
104+
await github.rest.issues.lock({
105+
owner,
106+
repo,
107+
issue_number: pull_number,
108+
lock_reason: 'resolved',
109+
});
110+
111+
core.info(`Locked PR #${pull_number} and posted the SEP proposal guidance.`);

0 commit comments

Comments
 (0)