Skip to content

Commit 711874e

Browse files
Add README to gist workflow
1 parent 5dbfb76 commit 711874e

1 file changed

Lines changed: 208 additions & 0 deletions

File tree

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
name: Create README Gist
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
repository:
7+
description: "Repo name in the serpgames org, or serpgames/repo"
8+
required: true
9+
type: string
10+
ref:
11+
description: "Branch, tag, or SHA to read from. Leave blank to use the repo default branch."
12+
required: false
13+
default: ""
14+
type: string
15+
public:
16+
description: "Create a public gist"
17+
required: false
18+
default: true
19+
type: boolean
20+
gist_description:
21+
description: "Optional gist description"
22+
required: false
23+
default: ""
24+
type: string
25+
workflow_call:
26+
inputs:
27+
repository:
28+
description: "Repo name in the serpgames org, or serpgames/repo"
29+
required: true
30+
type: string
31+
ref:
32+
description: "Branch, tag, or SHA to read from. Leave blank to use the repo default branch."
33+
required: false
34+
default: ""
35+
type: string
36+
public:
37+
description: "Create a public gist"
38+
required: false
39+
default: true
40+
type: boolean
41+
gist_description:
42+
description: "Optional gist description"
43+
required: false
44+
default: ""
45+
type: string
46+
secrets:
47+
SERPGAMEDEVELOPER_GIST_TOKEN:
48+
description: "PAT from the serpgamedeveloper account with gist scope"
49+
required: true
50+
outputs:
51+
gist_url:
52+
description: "Created gist URL"
53+
value: ${{ jobs.create-readme-gist.outputs.gist_url }}
54+
gist_id:
55+
description: "Created gist ID"
56+
value: ${{ jobs.create-readme-gist.outputs.gist_id }}
57+
58+
permissions:
59+
contents: read
60+
61+
jobs:
62+
create-readme-gist:
63+
name: Create README gist
64+
runs-on: ubuntu-latest
65+
outputs:
66+
gist_url: ${{ steps.create.outputs.gist_url }}
67+
gist_id: ${{ steps.create.outputs.gist_id }}
68+
steps:
69+
- name: Create gist from repository README
70+
id: create
71+
shell: bash
72+
env:
73+
INPUT_REPOSITORY: ${{ inputs.repository }}
74+
INPUT_REF: ${{ inputs.ref }}
75+
GIST_PUBLIC: ${{ inputs.public }}
76+
GIST_DESCRIPTION: ${{ inputs.gist_description }}
77+
GITHUB_TOKEN: ${{ github.token }}
78+
SERPGAMEDEVELOPER_GIST_TOKEN: ${{ secrets.SERPGAMEDEVELOPER_GIST_TOKEN }}
79+
run: |
80+
node <<'NODE'
81+
const fs = require("fs");
82+
83+
const apiVersion = "2022-11-28";
84+
const readToken = process.env.GITHUB_TOKEN || "";
85+
const gistToken = process.env.SERPGAMEDEVELOPER_GIST_TOKEN || "";
86+
87+
if (!gistToken) {
88+
throw new Error("Missing SERPGAMEDEVELOPER_GIST_TOKEN secret. Add a serpgamedeveloper PAT with gist scope.");
89+
}
90+
91+
const rawRepository = (process.env.INPUT_REPOSITORY || "").trim();
92+
if (!rawRepository) {
93+
throw new Error("The repository input is required.");
94+
}
95+
96+
const parts = rawRepository.includes("/")
97+
? rawRepository.split("/")
98+
: ["serpgames", rawRepository];
99+
100+
if (parts.length !== 2 || parts[0] !== "serpgames") {
101+
throw new Error("repository must be a repo name in serpgames, or serpgames/repo-name.");
102+
}
103+
104+
const [owner, repo] = parts;
105+
if (!/^[A-Za-z0-9_.-]+$/.test(repo)) {
106+
throw new Error(`Invalid repository name: ${repo}`);
107+
}
108+
109+
const githubHeaders = {
110+
"Accept": "application/vnd.github+json",
111+
"X-GitHub-Api-Version": apiVersion,
112+
"User-Agent": "serpgames-readme-gist-action",
113+
};
114+
if (readToken) {
115+
githubHeaders.Authorization = `Bearer ${readToken}`;
116+
}
117+
118+
async function requestJson(url, options = {}) {
119+
const response = await fetch(url, {
120+
...options,
121+
headers: {
122+
...githubHeaders,
123+
...(options.headers || {}),
124+
},
125+
});
126+
const text = await response.text();
127+
let body = null;
128+
if (text) {
129+
try {
130+
body = JSON.parse(text);
131+
} catch {
132+
body = text;
133+
}
134+
}
135+
if (!response.ok) {
136+
const details = typeof body === "string" ? body : JSON.stringify(body);
137+
throw new Error(`GitHub API request failed: ${response.status} ${response.statusText} ${url} ${details}`);
138+
}
139+
return body;
140+
}
141+
142+
const repoInfo = await requestJson(`https://api.github.com/repos/${owner}/${repo}`);
143+
const requestedRef = (process.env.INPUT_REF || "").trim();
144+
const ref = requestedRef || repoInfo.default_branch;
145+
const readme = await requestJson(
146+
`https://api.github.com/repos/${owner}/${repo}/readme?ref=${encodeURIComponent(ref)}`
147+
);
148+
149+
if (readme.encoding !== "base64") {
150+
throw new Error(`Unsupported README encoding: ${readme.encoding}`);
151+
}
152+
153+
const readmeMarkdown = Buffer.from(readme.content.replace(/\n/g, ""), "base64").toString("utf8");
154+
const gistPublic = String(process.env.GIST_PUBLIC || "true").toLowerCase() !== "false";
155+
const generatedAt = new Date().toISOString();
156+
const description = (process.env.GIST_DESCRIPTION || "").trim()
157+
|| `${owner}/${repo} README from ${ref}`;
158+
159+
const metadata = {
160+
repository: `${owner}/${repo}`,
161+
ref,
162+
default_branch: repoInfo.default_branch,
163+
readme_path: readme.path,
164+
readme_sha: readme.sha,
165+
readme_size: readme.size,
166+
readme_html_url: readme.html_url,
167+
readme_download_url: readme.download_url,
168+
generated_at: generatedAt,
169+
};
170+
171+
const gist = await requestJson("https://api.github.com/gists", {
172+
method: "POST",
173+
headers: {
174+
Authorization: `Bearer ${gistToken}`,
175+
},
176+
body: JSON.stringify({
177+
description,
178+
public: gistPublic,
179+
files: {
180+
[`${repo}-README.md`]: {
181+
content: readmeMarkdown,
182+
},
183+
[`${repo}-readme-metadata.json`]: {
184+
content: JSON.stringify(metadata, null, 2),
185+
},
186+
},
187+
}),
188+
});
189+
190+
fs.appendFileSync(process.env.GITHUB_OUTPUT, `gist_url=${gist.html_url}\n`);
191+
fs.appendFileSync(process.env.GITHUB_OUTPUT, `gist_id=${gist.id}\n`);
192+
193+
if (process.env.GITHUB_STEP_SUMMARY) {
194+
fs.appendFileSync(
195+
process.env.GITHUB_STEP_SUMMARY,
196+
[
197+
"## README gist created",
198+
"",
199+
`- Repository: ${owner}/${repo}`,
200+
`- Ref: ${ref}`,
201+
`- README: ${readme.html_url}`,
202+
`- Gist: ${gist.html_url}`,
203+
`- Public: ${gist.public}`,
204+
"",
205+
].join("\n")
206+
);
207+
}
208+
NODE

0 commit comments

Comments
 (0)