Skip to content

Commit 24bf80b

Browse files
refactor: Fix minor issues
- Replace GitHub CLI with direct network requests - Improve diagnostic messages
1 parent 852596f commit 24bf80b

File tree

5 files changed

+61
-29
lines changed

5 files changed

+61
-29
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747

4848
- run: pnpm build
4949
env:
50-
GH_TOKEN: ${{ github.token }} # `<SeeAlso>` requires GitHub CLI
50+
GH_TOKEN: ${{ github.token }} # `<SeeAlso>` requires GitHub API
5151

5252
- name: Upload artifact
5353
uses: actions/upload-pages-artifact@v3

.github/workflows/check.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646

4747
- run: pnpm build
4848
env:
49-
GH_TOKEN: ${{ github.token }} # `<SeeAlso>` requires GitHub CLI
49+
GH_TOKEN: ${{ github.token }} # `<SeeAlso>` requires GitHub API
5050

5151
- uses: actions/upload-artifact@v4
5252
with:

docs/.vitepress/theme/see_also.data.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
* When modifying the page frontmatter, the loader may be called repeatedly. Therefore, network requests are cached.
1212
*
13-
* For maximal compatibility, features requires network or GitHub CLI are disabled granularly if not available.
13+
* For maximal compatibility, features requires network or GitHub API are disabled granularly if not available.
1414
*
1515
* @module
1616
*/

docs/.vitepress/theme/see_also_data/auto_title.ts

Lines changed: 58 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { zip } from 'es-toolkit';
22
import assert from 'node:assert';
3+
import { env } from 'node:process';
34
import { duration_fmt, removePrefix } from '../../util';
4-
import { execFile } from '../../util_node';
55
import type { Link, RelativePath } from '../see_also.data';
66
import { FileCacheWithInit } from './caching.ts';
77

@@ -158,29 +158,41 @@ type PullState = { title: string } & (
158158
);
159159

160160
/**
161-
* Query GitHub GraphQL API using GitHub CLI.
161+
* Query GitHub GraphQL API.
162162
* https://docs.github.com/en/graphql/reference/queries
163163
*/
164-
async function queryGitHub(
165-
query: string,
166-
vars: Record<string, string | number> = {},
167-
): Promise<any> {
164+
async function queryGitHub(query: string): Promise<any> {
168165
const timeStart = Date.now();
169166

170-
const { stdout } = await execFile('gh', [
171-
'api',
172-
'graphql',
173-
'--raw-field',
174-
`query=${query}`,
175-
...Object.entries(vars).flatMap(([k, v]) => ['--field', `${k}=${v}`]),
176-
]);
167+
const token = env.GH_TOKEN ?? env.GITHUB_TOKEN;
168+
if (token === undefined) {
169+
throw new Error(
170+
'GitHub GraphQL API requires authentication, but no token is available. Please set $GITHUB_TOKEN (no scope required) to authenticate.',
171+
);
172+
}
173+
174+
const response = await fetch('https://api.github.com/graphql', {
175+
method: 'POST',
176+
headers: {
177+
'Content-Type': 'application/json',
178+
Authorization: `Bearer ${token}`,
179+
},
180+
body: JSON.stringify({ query }),
181+
});
182+
const result = await response.text();
183+
184+
if (!response.ok) {
185+
throw new Error(
186+
`GitHub API request failed: ${response.status} ${response.statusText}\n${result}`,
187+
);
188+
}
177189

178190
console.log(
179-
`📩 Got ${stdout.length} characters from GitHub API successfully in`,
191+
`📩 Got ${result.length} characters from GitHub API successfully in`,
180192
`${duration_fmt(Date.now() - timeStart)}.`,
181193
);
182194

183-
return JSON.parse(stdout).data;
195+
return JSON.parse(result).data;
184196
}
185197

186198
/**
@@ -252,7 +264,22 @@ async function fetchStates(meta_list: (IssueMeta | PullMeta)[]): Promise<void> {
252264

253265
const stateFlat: (IssueState | PullState)[] = Object.values(data)
254266
.map((items_of_a_repo) => Object.values(items_of_a_repo))
255-
.flat();
267+
.flat()
268+
.map(({ __typename: typename, ...state }, i) => {
269+
// Check the types match
270+
const actualType =
271+
typename === 'Issue'
272+
? 'issue'
273+
: typename === 'PullRequest'
274+
? 'pull'
275+
: typename;
276+
const mismatched = grouped[i].filter((meta) => meta.type !== actualType);
277+
assert(
278+
mismatched.length === 0,
279+
`the link type is wrong. Actual: ${actualType}; Found: ${JSON.stringify(mismatched)}`,
280+
);
281+
return state;
282+
});
256283

257284
assert.strictEqual(metaFlat.length, stateFlat.length);
258285

@@ -266,6 +293,9 @@ async function fetchStates(meta_list: (IssueMeta | PullMeta)[]): Promise<void> {
266293
_GITHUB_STATES_CACHE.save();
267294
}
268295

296+
/** Warned metadata, saved to avoid repetitive warnings. */
297+
const _WARNED = new Set<SerializedMeta>();
298+
269299
/**
270300
* Try to populate titles via GitHub in place.
271301
*
@@ -294,22 +324,28 @@ async function tryResolveViaGitHub(targets: Link[]): Promise<void> {
294324
try {
295325
await fetchStates(fetchPlan);
296326
} catch (e) {
297-
// @ts-ignore
298-
if (e.code === 'ENOENT') {
327+
if (!fetchPlan.every((meta) => _WARNED.has(serialize(meta)))) {
299328
console.warn(
300-
'[Warning] GitHub CLI is not available. Skip resolving titles via GitHub for `<SeeAlso>`.',
329+
'[Warning] GitHub API is not accessible. Skip resolving titles for the following links in <SeeAlso> via GitHub. (You can ignore this warning if you do not care those titles.)\n ',
330+
fetchPlan.map((meta) => `${meta.repo}#${meta.num} (${meta.type})`),
331+
`\n Cause: ${e}`,
301332
);
302-
return;
333+
334+
for (const meta of fetchPlan) {
335+
_WARNED.add(serialize(meta));
336+
}
303337
}
304-
throw e;
305338
}
306339
}
307340

308341
// 2. Use the cache to populate titles
309342

310343
for (const [link, meta] of relevant) {
311344
const state = cache.get(serialize(meta));
312-
assert(state !== undefined);
345+
if (state === undefined) {
346+
// Skip this one if its cache is not ready, but allow others to reuse their caches.
347+
continue;
348+
}
313349

314350
const repoNum = `${removePrefix(meta.repo, 'typst/')}#${meta.num}`;
315351

docs/.vitepress/util_node.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
* @module
44
*/
55

6-
import { execFile as _execFile } from 'node:child_process';
76
import { readFileSync } from 'node:fs';
8-
import { promisify } from 'node:util';
97

108
/**
119
* Read a file to string, return `undefined` if not existed
@@ -22,5 +20,3 @@ export function readToString(file: string): string | undefined {
2220
}
2321
}
2422
}
25-
26-
export const execFile = promisify(_execFile);

0 commit comments

Comments
 (0)