Skip to content

Commit e702ec5

Browse files
Bo98branchvincent
authored andcommitted
Adopt TypeScript under Node 24
1 parent 9d95677 commit e702ec5

File tree

510 files changed

+311717
-884
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

510 files changed

+311717
-884
lines changed

.github/workflows/test.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ jobs:
2222
- name: Setup Node
2323
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
2424
with:
25-
node-version: '20'
25+
node-version: '24'
26+
27+
- name: Run type checking
28+
run: npm install && npx tsc
2629

2730
- name: Run tests
2831
run: npm test -- --experimental-test-coverage --test-reporter lcov --test-reporter-destination lcov.info

.github/workflows/vendor-node-modules.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5151
- name: Vendor node_modules
5252
run: |
53-
npm ci --ignore-scripts
53+
npm ci --omit=dev --ignore-scripts
5454
rm -r ./node_modules/esm-reload/.github/
5555
- name: Commit changes
5656
id: commit

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/node_modules/.bin/
2+
/node_modules/@tsconfig/
3+
/node_modules/@types/
4+
/node_modules/typescript/
5+
/node_modules/undici-types/
6+
/node_modules/**/.github/
7+
/node_modules/**/tests/

api-commit-and-push/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ inputs:
2323
required: false
2424
default: ${{ github.repository }}
2525
runs:
26-
using: node20
27-
main: main.mjs
26+
using: node24
27+
main: main.mts

api-commit-and-push/main.mjs renamed to api-commit-and-push/main.mts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import github from "@actions/github"
44
import fs from "node:fs/promises"
55
import path from "node:path"
66

7+
import type { RestEndpointMethodTypes } from "@octokit/plugin-rest-endpoint-methods"
8+
79
async function main() {
810
const commitMessage = core.getInput("message")
911
const branch = core.getInput("branch")
@@ -22,17 +24,19 @@ async function main() {
2224
const headCommitSha = (await exec.getExecOutput("git", ["-C", directory, "rev-parse", "HEAD"], { silent: true })).stdout.trim()
2325
const headTreeSha = (await exec.getExecOutput("git", ["-C", directory, "rev-parse", "HEAD:"], { silent: true })).stdout.trim()
2426

25-
const tree = {}
27+
const tree: Record<string, RestEndpointMethodTypes["git"]["createTree"]["parameters"]["tree"][number]> = {}
2628
for (const file of files) {
2729
const absoluteFile = path.resolve(directory, file)
2830

2931
let content;
3032
try {
3133
content = await fs.readFile(absoluteFile, {encoding: "base64"})
3234
} catch (error) {
33-
if (error.code !== "ENOENT") throw error;
34-
35-
content = null;
35+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
36+
content = null
37+
} else {
38+
throw error
39+
}
3640
}
3741

3842
if (content !== null) {
@@ -59,7 +63,7 @@ async function main() {
5963
const blobResponse = await client.rest.git.createBlob({
6064
owner: owner,
6165
repo: repo,
62-
content: await fs.readFile(absoluteFile, {encoding: "base64"}),
66+
content: content,
6367
encoding: "base64"
6468
})
6569

api-commit-and-push/main.test.mjs renamed to api-commit-and-push/main.test.mts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import os from "node:os"
44
import path from "node:path"
55
import util from "node:util"
66

7+
import type { RestEndpointMethodTypes } from "@octokit/plugin-rest-endpoint-methods"
8+
79
describe("api-commit-and-push", async () => {
810
const token = "fake-token"
911
const branch = "a-branch"
1012
const message = "Some message"
11-
let directory
12-
let baseCommitSha
13-
let baseTreeSha
13+
let directory: string
14+
let baseCommitSha: string
15+
let baseTreeSha: string
1416

1517
const blobSha = "abcdef1234567890abcdef1234567890abcdef12"
1618
const treeSha = "abcdef1234567890abcdef1234567890abcdef13"
@@ -70,7 +72,7 @@ describe("api-commit-and-push", async () => {
7072
sha: blobSha,
7173
})
7274

73-
const tree = []
75+
const tree: Array<RestEndpointMethodTypes["git"]["createTree"]["parameters"]["tree"][number]> = []
7476
addedFile.split("/").slice(0, -1).reduce((parentPath, component) => {
7577
const treePath = path.posix.join(parentPath, component);
7678

check-commit-format/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ inputs:
2222
required: false
2323
default: CI-published-bottle-commits
2424
runs:
25-
using: node20
26-
main: main.mjs
25+
using: node24
26+
main: main.mts

check-commit-format/main.mjs renamed to check-commit-format/main.mts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import assert from "node:assert/strict"
12
import core from "@actions/core"
23
import github from "@actions/github"
34
import fs from "fs"
45
import path from "path"
56

7+
import type { RestEndpointMethodTypes } from "@octokit/plugin-rest-endpoint-methods"
8+
69
async function main() {
710
try {
811
const token = core.getInput("token", { required: true })
@@ -13,6 +16,7 @@ async function main() {
1316
const client = github.getOctokit(token)
1417

1518
// Parse event
19+
assert(process.env.GITHUB_EVENT_PATH)
1620
const json = fs.readFileSync(process.env.GITHUB_EVENT_PATH, { encoding: "utf-8" })
1721
const event = JSON.parse(json)
1822
const pull = event.pull_request
@@ -25,9 +29,9 @@ async function main() {
2529

2630
let is_success = true
2731
let autosquash = false
28-
let commit_state = "success"
32+
let commit_state: RestEndpointMethodTypes["repos"]["createCommitStatus"]["parameters"]["state"] = "success"
2933
let message = "Commit format is correct."
30-
let files_touched = []
34+
let files_touched: Array<string> = []
3135
let target_url = "https://docs.brew.sh/Formula-Cookbook#commit"
3236

3337
// For each commit...
@@ -47,6 +51,14 @@ async function main() {
4751
break
4852
}
4953

54+
// Empty commits that are not merge commits are usually a mistake or a bad rebase.
55+
if (!commit_info.data.files || commit_info.data.files.length === 0) {
56+
is_success = false
57+
commit_state = "failure"
58+
message = `${short_sha} is an empty commit.`
59+
break
60+
}
61+
5062
// Autosquash doesn't support commits that modify more than one file.
5163
if (commit_info.data.files.length != 1) {
5264
is_success = false
@@ -72,7 +84,7 @@ async function main() {
7284
}
7385

7486
const file = commit_info.data.files[0]
75-
const commit_subject = commit_info.data.commit.message.split("\n").shift()
87+
const commit_subject = commit_info.data.commit.message.split("\n")[0]
7688

7789
if (file.filename.startsWith("Formula/")) {
7890
const formula = path.basename(file.filename, '.rb')
@@ -118,11 +130,11 @@ async function main() {
118130
})
119131

120132
// Get existing labels on PR
121-
let existingLabels = await client.rest.issues.listLabelsOnIssue({
133+
let issueLabels = await client.rest.issues.listLabelsOnIssue({
122134
...github.context.repo,
123135
issue_number: pull.number
124136
})
125-
existingLabels = existingLabels.data.map(label => label.name)
137+
let existingLabels = issueLabels.data.map(label => label.name)
126138

127139
// Copy labels into new Array
128140
const updatedLabels = existingLabels.slice()
@@ -167,6 +179,8 @@ async function main() {
167179
labels: updatedLabels
168180
})
169181
} catch (error) {
182+
if (!(error instanceof Error)) throw error
183+
170184
core.setFailed(error)
171185
}
172186
}

check-commit-format/main.test.mjs renamed to check-commit-format/main.test.mts

Lines changed: 174 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ describe("check-commit-format", async () => {
2828
})
2929

3030
afterEach(() => {
31-
fs.rmSync(path.dirname(process.env.GITHUB_EVENT_PATH), { recursive: true })
31+
if (process.env.GITHUB_EVENT_PATH) {
32+
fs.rmSync(path.dirname(process.env.GITHUB_EVENT_PATH), { recursive: true })
33+
}
3234
})
3335

3436
describe("on a correct commit", async () => {
@@ -132,6 +134,177 @@ describe("check-commit-format", async () => {
132134
})
133135
})
134136

137+
describe("on a merge commit", async () => {
138+
beforeEach(() => {
139+
const mockPool = githubMockPool()
140+
141+
mockPool.intercept({
142+
method: "GET",
143+
path: `/repos/${GITHUB_REPOSITORY}/pulls/${pr}/commits`,
144+
headers: {
145+
Authorization: `token ${token}`,
146+
},
147+
}).defaultReplyHeaders({
148+
"Content-Type": "application/json",
149+
}).reply(200, [
150+
{
151+
sha: sha,
152+
},
153+
])
154+
155+
mockPool.intercept({
156+
method: "GET",
157+
path: `/repos/${GITHUB_REPOSITORY}/commits/${sha}`,
158+
headers: {
159+
Authorization: `token ${token}`,
160+
},
161+
}).defaultReplyHeaders({
162+
"Content-Type": "application/json",
163+
}).reply(200, {
164+
sha: sha,
165+
parents: [
166+
{ sha: "abcdef1234567890abcdef1234567890abcdef11" },
167+
{ sha: "abcdef1234567890abcdef1234567890abcdef12" }
168+
],
169+
files: [],
170+
commit: {
171+
message: "Merge commit",
172+
}
173+
})
174+
175+
mockPool.intercept({
176+
method: "POST",
177+
path: `/repos/${GITHUB_REPOSITORY}/statuses/${sha}`,
178+
headers: {
179+
Authorization: `token ${token}`,
180+
},
181+
body: (body) => util.isDeepStrictEqual(JSON.parse(body), {
182+
state: "failure",
183+
description: `${sha.substring(0, 10)} has 2 parents. Please rebase against origin/HEAD.`,
184+
context: "Commit style",
185+
target_url: "https://docs.brew.sh/Formula-Cookbook#commit"
186+
}),
187+
}).defaultReplyHeaders({
188+
"Content-Type": "application/json",
189+
}).reply(200, {})
190+
})
191+
192+
it("fails and adds a failure label", async () => {
193+
const mockPool = githubMockPool()
194+
195+
mockPool.intercept({
196+
method: "GET",
197+
path: `/repos/${GITHUB_REPOSITORY}/issues/${pr}/labels`,
198+
headers: {
199+
Authorization: `token ${token}`,
200+
},
201+
}).defaultReplyHeaders({
202+
"Content-Type": "application/json",
203+
}).reply(200, [
204+
{ name: "other-label" },
205+
])
206+
207+
mockPool.intercept({
208+
method: "PATCH",
209+
path: `/repos/${GITHUB_REPOSITORY}/issues/${pr}`,
210+
headers: {
211+
Authorization: `token ${token}`,
212+
},
213+
body: (body) => util.isDeepStrictEqual(JSON.parse(body), {
214+
labels: ["other-label", failureLabel],
215+
}),
216+
}).defaultReplyHeaders({
217+
"Content-Type": "application/json",
218+
}).reply(200, {})
219+
220+
await loadMain()
221+
})
222+
})
223+
224+
describe("on an empty commit", async () => {
225+
beforeEach(() => {
226+
const mockPool = githubMockPool()
227+
228+
mockPool.intercept({
229+
method: "GET",
230+
path: `/repos/${GITHUB_REPOSITORY}/pulls/${pr}/commits`,
231+
headers: {
232+
Authorization: `token ${token}`,
233+
},
234+
}).defaultReplyHeaders({
235+
"Content-Type": "application/json",
236+
}).reply(200, [
237+
{
238+
sha: sha,
239+
},
240+
])
241+
242+
mockPool.intercept({
243+
method: "GET",
244+
path: `/repos/${GITHUB_REPOSITORY}/commits/${sha}`,
245+
headers: {
246+
Authorization: `token ${token}`,
247+
},
248+
}).defaultReplyHeaders({
249+
"Content-Type": "application/json",
250+
}).reply(200, {
251+
sha: sha,
252+
parents: [{ sha: "abcdef1234567890abcdef1234567890abcdef11" }],
253+
files: [],
254+
commit: {
255+
message: "Empty commit",
256+
}
257+
})
258+
259+
mockPool.intercept({
260+
method: "POST",
261+
path: `/repos/${GITHUB_REPOSITORY}/statuses/${sha}`,
262+
headers: {
263+
Authorization: `token ${token}`,
264+
},
265+
body: (body) => util.isDeepStrictEqual(JSON.parse(body), {
266+
state: "failure",
267+
description: `${sha.substring(0, 10)} is an empty commit.`,
268+
context: "Commit style",
269+
target_url: "https://docs.brew.sh/Formula-Cookbook#commit"
270+
}),
271+
}).defaultReplyHeaders({
272+
"Content-Type": "application/json",
273+
}).reply(200, {})
274+
})
275+
276+
it("fails and adds a failure label", async () => {
277+
const mockPool = githubMockPool()
278+
279+
mockPool.intercept({
280+
method: "GET",
281+
path: `/repos/${GITHUB_REPOSITORY}/issues/${pr}/labels`,
282+
headers: {
283+
Authorization: `token ${token}`,
284+
},
285+
}).defaultReplyHeaders({
286+
"Content-Type": "application/json",
287+
}).reply(200, [
288+
{ name: "other-label" },
289+
])
290+
291+
mockPool.intercept({
292+
method: "PATCH",
293+
path: `/repos/${GITHUB_REPOSITORY}/issues/${pr}`,
294+
headers: {
295+
Authorization: `token ${token}`,
296+
},
297+
body: (body) => util.isDeepStrictEqual(JSON.parse(body), {
298+
labels: ["other-label", failureLabel],
299+
}),
300+
}).defaultReplyHeaders({
301+
"Content-Type": "application/json",
302+
}).reply(200, {})
303+
304+
await loadMain()
305+
})
306+
})
307+
135308
describe("on an autosquashable incorrect commit", async () => {
136309
beforeEach(() => {
137310
const mockPool = githubMockPool()

create-or-update-issue/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,5 @@ outputs:
6262
The node ID of the created or updated issue, used in GitHub GraphQL API
6363
queries; undefined if `outcome` is `none`
6464
runs:
65-
using: node20
66-
main: main.mjs
65+
using: node24
66+
main: main.mts

0 commit comments

Comments
 (0)