Skip to content

Commit dffb394

Browse files
authored
chore(ci): gh test-project typescript actions (#1383)
1 parent 147435c commit dffb394

18 files changed

+408
-346
lines changed

.github/actions/actionsLib.mjs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/* eslint-env node */
21
// @ts-check
32

43
import fs from 'node:fs'
@@ -21,9 +20,17 @@ export const CEDAR_FRAMEWORK_PATH = fileURLToPath(
2120
* @param {ExecOptions} options
2221
*/
2322
function execWithEnv(command, { env = {}, ...rest } = {}) {
23+
/** @type {{ [key: string]: string }} */
24+
const processEnv = Object.fromEntries(
25+
Object.entries(process.env).filter(
26+
/** @returns {entry is [string, string]} */
27+
(entry) => entry[1] !== undefined,
28+
),
29+
)
30+
2431
return getExecOutput(command, undefined, {
2532
env: {
26-
...process.env,
33+
...processEnv,
2734
...env,
2835
},
2936
...rest,
@@ -74,7 +81,7 @@ export async function createCacheKeys({
7481
const baseKey = [
7582
baseKeyPrefix,
7683
process.env.RUNNER_OS,
77-
process.env.GITHUB_REF.replaceAll('/', '-'),
84+
process.env.GITHUB_REF?.replaceAll('/', '-'),
7885
await hashFiles(path.join('__fixtures__', 'test-project')),
7986
].join('-')
8087

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import { spawn } from 'node:child_process'
2+
import fs from 'node:fs'
3+
import path from 'node:path'
4+
import { fileURLToPath } from 'node:url'
5+
6+
import type { ExecOptions } from '@actions/exec'
7+
8+
export const CEDAR_FRAMEWORK_PATH = fileURLToPath(
9+
new URL('../../', import.meta.url),
10+
)
11+
12+
export function setOutput(key: string, value: string) {
13+
console.log(`setOutput: ${key} = ${value}`)
14+
}
15+
16+
export function getInput(key: string) {
17+
console.log(`getInput: ${key}`)
18+
return ''
19+
}
20+
21+
/**
22+
* This is an approximation of `getExecOutput` from `@actions/exec` that can be
23+
* used locally (i.e. outside of GitHub Actions) for testing.
24+
*/
25+
function getExecOutput(
26+
command: string,
27+
args?: string[],
28+
options: ExecOptions = {},
29+
): Promise<{ stdout: string; stderr: string }> {
30+
return new Promise((resolve, reject) => {
31+
const { cwd, env, silent = false, input } = options
32+
33+
const child = spawn(command, args ?? [], {
34+
cwd,
35+
env,
36+
shell: true,
37+
stdio: ['pipe', 'pipe', 'pipe'],
38+
})
39+
40+
let stdout = ''
41+
let stderr = ''
42+
43+
child.stdout.on('data', (chunk: string | Buffer) => {
44+
const text = chunk.toString()
45+
stdout += text
46+
47+
if (!silent) {
48+
process.stdout.write(text)
49+
}
50+
})
51+
52+
child.stderr.on('data', (chunk: string | Buffer) => {
53+
const text = chunk.toString()
54+
stderr += text
55+
56+
if (!silent) {
57+
process.stderr.write(text)
58+
}
59+
})
60+
61+
child.on('error', (error) => {
62+
reject(error)
63+
})
64+
65+
child.on('close', (code) => {
66+
if (code === 0) {
67+
resolve({ stdout, stderr })
68+
return
69+
}
70+
71+
const error = new Error(
72+
`Command failed with exit code ${code}: ${command}`,
73+
) as Error & {
74+
code?: number | null
75+
stdout?: string
76+
stderr?: string
77+
}
78+
79+
error.code = code
80+
error.stdout = stdout
81+
error.stderr = stderr
82+
83+
reject(error)
84+
})
85+
86+
if (input !== undefined) {
87+
child.stdin.write(input)
88+
}
89+
90+
child.stdin.end()
91+
})
92+
}
93+
94+
function execWithEnv(command: string, { env = {}, ...rest }: ExecOptions = {}) {
95+
const processEnv: Record<string, string> = Object.fromEntries(
96+
Object.entries(process.env).filter(
97+
(entry): entry is [string, string] => entry[1] !== undefined,
98+
),
99+
)
100+
101+
return getExecOutput(command, undefined, {
102+
env: {
103+
...processEnv,
104+
...env,
105+
},
106+
...rest,
107+
})
108+
}
109+
110+
export function createExecWithEnvInCwd(cwd: string) {
111+
return function (command: string, options: Omit<ExecOptions, 'cwd'> = {}) {
112+
return execWithEnv(command, { cwd, ...options })
113+
}
114+
}
115+
116+
export const execInFramework = createExecWithEnvInCwd(CEDAR_FRAMEWORK_PATH)
117+
118+
/**
119+
* @param commandLine command to execute (can include additional args). Must be
120+
* correctly escaped.
121+
* @param options exec options. See ExecOptions
122+
* @returns exit code
123+
*/
124+
type ExecInProject = (
125+
commandLine: string,
126+
options?: Omit<ExecOptions, 'cwd'>,
127+
) => Promise<unknown>
128+
129+
export async function setUpRscTestProject(
130+
testProjectPath: string,
131+
fixtureName: string,
132+
core: { setOutput: (key: string, value: string) => void },
133+
execInProject: ExecInProject,
134+
) {
135+
core.setOutput('test-project-path', testProjectPath)
136+
137+
console.log('Cedar Framework Path', CEDAR_FRAMEWORK_PATH)
138+
console.log('testProjectPath', testProjectPath)
139+
140+
const fixturePath = path.join(
141+
CEDAR_FRAMEWORK_PATH,
142+
'__fixtures__',
143+
fixtureName,
144+
)
145+
const cedarBinPath = path.join(
146+
CEDAR_FRAMEWORK_PATH,
147+
'packages/cli/dist/index.js',
148+
)
149+
const cfwBinPath = path.join(CEDAR_FRAMEWORK_PATH, 'packages/cli/dist/cfw.js')
150+
151+
console.log(`Creating project at ${testProjectPath}`)
152+
console.log()
153+
fs.cpSync(fixturePath, testProjectPath, { recursive: true })
154+
155+
console.log('Syncing framework')
156+
await execInProject(`node ${cfwBinPath} project:tarsync --verbose`, {
157+
env: { CFW_PATH: CEDAR_FRAMEWORK_PATH },
158+
})
159+
console.log()
160+
161+
console.log(`Building project in ${testProjectPath}`)
162+
await execInProject(`node ${cedarBinPath} build -v`)
163+
console.log()
164+
}

.github/actions/set-up-rsa-project/action.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Sets up an RSA project for smoke-tests
33

44
runs:
55
using: node24
6-
main: 'setUpRsaProjectGitHub.mjs'
6+
main: 'setUpRsaProjectGitHub.mts'
77

88
outputs:
99
test-project-path:

.github/actions/set-up-rsa-project/setUpRsaProjectGitHub.mjs renamed to .github/actions/set-up-rsa-project/setUpRsaProjectGitHub.mts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
/* eslint-env node */
2-
// @ts-check
3-
41
import path from 'node:path'
52

63
import core from '@actions/core'
74

85
import { createExecWithEnvInCwd, setUpRscTestProject } from '../actionsLib.mjs'
96

107
const testProjectAndFixtureName = 'test-project-rsa'
8+
119
const testProjectPath = path.join(
1210
path.dirname(process.cwd()),
1311
testProjectAndFixtureName,
1412
)
13+
1514
const execInProject = createExecWithEnvInCwd(testProjectPath)
1615

1716
setUpRscTestProject(

.github/actions/set-up-rsa-project/setUpRsaProjectLocally.mjs

Lines changed: 0 additions & 111 deletions
This file was deleted.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import os from 'node:os'
2+
import path from 'node:path'
3+
4+
import {
5+
createExecWithEnvInCwd,
6+
setOutput,
7+
setUpRscTestProject,
8+
} from '../actionsLibLocally.mts'
9+
10+
const testProjectAndFixtureName = 'test-project-rsa'
11+
12+
const testProjectPath = path.join(
13+
os.tmpdir(),
14+
'cedar',
15+
testProjectAndFixtureName,
16+
// ":" is problematic with paths
17+
new Date().toISOString().split(':').join('-'),
18+
)
19+
20+
const core = { setOutput }
21+
22+
const execInProject = createExecWithEnvInCwd(testProjectPath)
23+
24+
setUpRscTestProject(
25+
testProjectPath,
26+
testProjectAndFixtureName,
27+
core,
28+
execInProject,
29+
)

.github/actions/set-up-rsa-project/jsconfig.json renamed to .github/actions/set-up-rsa-project/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
"module": "esnext",
77
"moduleResolution": "node",
88
"skipLibCheck": false,
9-
"jsx": "react-jsx"
9+
"allowImportingTsExtensions": true
1010
}
1111
}

.github/actions/set-up-rsc-project/action.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Sets up an RSC project for smoke-tests
33

44
runs:
55
using: node24
6-
main: 'setUpRscProjectGitHub.mjs'
6+
main: 'setUpRscProjectGitHub.mts'
77

88
outputs:
99
test-project-path:

0 commit comments

Comments
 (0)