Skip to content

Commit 376f838

Browse files
authored
Merge pull request #109 from codeacme17/codex/bootstrap-control-plane-installer
fix(loop): publish trusted control plane on macOS
2 parents 826aa47 + e794f6a commit 376f838

2 files changed

Lines changed: 121 additions & 4 deletions

File tree

loops/issue-dev-loop/scripts/install-trusted-control-plane.mjs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ async function main() {
9696
}
9797
const temporaryBundleRoot = `${targetBundleRoot}.tmp-${process.pid}-${randomBytes(4).toString('hex')}`
9898
const targetLoopRoot = path.join(temporaryBundleRoot, 'issue-dev-loop')
99+
let cleanupBundleRoot = temporaryBundleRoot
99100
try {
100101
await mkdir(targetLoopRoot, { recursive: true })
101102
await cp(path.join(sourceLoopRoot, 'scripts'), path.join(targetLoopRoot, 'scripts'), {
@@ -198,9 +199,11 @@ async function main() {
198199
}
199200
await chmod(path.join(targetLoopRoot, 'trusted-control-plane.json'), 0o444)
200201
for (const directory of (await directories(temporaryBundleRoot)).reverse()) {
201-
await chmod(directory, 0o555)
202+
if (directory !== temporaryBundleRoot) await chmod(directory, 0o555)
202203
}
203204
await rename(temporaryBundleRoot, targetBundleRoot)
205+
cleanupBundleRoot = targetBundleRoot
206+
await chmod(targetBundleRoot, 0o555)
204207
process.stdout.write(
205208
`${JSON.stringify({
206209
bundleRoot: targetBundleRoot,
@@ -210,13 +213,13 @@ async function main() {
210213
)
211214
} catch (error) {
212215
try {
213-
for (const directory of await directories(temporaryBundleRoot)) {
216+
for (const directory of await directories(cleanupBundleRoot)) {
214217
await chmod(directory, 0o755)
215218
}
216219
} catch {
217-
// Best-effort permission restoration for an interrupted pre-rename install.
220+
// Best-effort permission restoration for an interrupted install.
218221
}
219-
await rm(temporaryBundleRoot, { recursive: true, force: true })
222+
await rm(cleanupBundleRoot, { recursive: true, force: true })
220223
throw error
221224
}
222225
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import assert from 'node:assert/strict'
2+
import { execFile } from 'node:child_process'
3+
import {
4+
chmod,
5+
cp,
6+
lstat,
7+
mkdir,
8+
mkdtemp,
9+
readFile,
10+
readdir,
11+
realpath,
12+
rm,
13+
stat,
14+
writeFile,
15+
} from 'node:fs/promises'
16+
import os from 'node:os'
17+
import path from 'node:path'
18+
import test from 'node:test'
19+
import { promisify } from 'node:util'
20+
import { fileURLToPath } from 'node:url'
21+
22+
const execFileAsync = promisify(execFile)
23+
const testDirectory = path.dirname(fileURLToPath(import.meta.url))
24+
const installerSource = path.resolve(
25+
testDirectory,
26+
'..',
27+
'scripts',
28+
'install-trusted-control-plane.mjs',
29+
)
30+
31+
async function makeWritable(target) {
32+
let targetStat
33+
try {
34+
targetStat = await lstat(target)
35+
} catch (error) {
36+
if (error?.code === 'ENOENT') return
37+
throw error
38+
}
39+
if (!targetStat.isDirectory()) {
40+
await chmod(target, 0o644)
41+
return
42+
}
43+
await chmod(target, 0o755)
44+
for (const entry of await readdir(target)) {
45+
await makeWritable(path.join(target, entry))
46+
}
47+
}
48+
49+
async function git(repositoryRoot, args) {
50+
return execFileAsync('git', args, { cwd: repositoryRoot })
51+
}
52+
53+
test('installer atomically publishes a read-only trusted control plane', async (context) => {
54+
const fixtureRoot = await mkdtemp(path.join(os.tmpdir(), 'echo-ui-control-plane-install-'))
55+
context.after(async () => {
56+
await makeWritable(fixtureRoot)
57+
await rm(fixtureRoot, { recursive: true, force: true })
58+
})
59+
60+
const repositoryRoot = path.join(fixtureRoot, 'repository')
61+
const loopRoot = path.join(repositoryRoot, 'loops', 'issue-dev-loop')
62+
const installer = path.join(loopRoot, 'scripts', 'install-trusted-control-plane.mjs')
63+
const target = path.join(fixtureRoot, 'trusted-control-plane')
64+
const canonicalTarget = path.join(await realpath(fixtureRoot), 'trusted-control-plane')
65+
await Promise.all([
66+
mkdir(path.dirname(installer), { recursive: true }),
67+
mkdir(path.join(loopRoot, 'triggers'), { recursive: true }),
68+
mkdir(path.join(repositoryRoot, 'loops', '_shared', 'owner-channel'), { recursive: true }),
69+
])
70+
await Promise.all([
71+
cp(installerSource, installer),
72+
writeFile(path.join(loopRoot, 'triggers', 'detect-work.mjs'), 'export {}\n', 'utf8'),
73+
writeFile(
74+
path.join(repositoryRoot, 'loops', '_shared', 'owner-channel', 'channel.json'),
75+
'{}\n',
76+
'utf8',
77+
),
78+
])
79+
80+
await git(repositoryRoot, ['init', '--initial-branch=dev'])
81+
await git(repositoryRoot, ['add', '.'])
82+
await git(repositoryRoot, [
83+
'-c',
84+
'user.name=Echo UI Test',
85+
'-c',
86+
'user.email=echo-ui-test@example.invalid',
87+
'commit',
88+
'-m',
89+
'fixture',
90+
])
91+
const { stdout: sourceCommitOutput } = await git(repositoryRoot, ['rev-parse', 'HEAD'])
92+
const sourceCommit = sourceCommitOutput.trim()
93+
await git(repositoryRoot, ['update-ref', 'refs/remotes/origin/dev', sourceCommit])
94+
95+
const { stdout } = await execFileAsync(process.execPath, [installer, '--target', target], {
96+
cwd: repositoryRoot,
97+
})
98+
99+
const result = JSON.parse(stdout)
100+
assert.equal(result.bundleRoot, canonicalTarget)
101+
assert.equal(result.controlPlaneRoot, path.join(canonicalTarget, 'issue-dev-loop'))
102+
assert.equal(result.sourceCommit, sourceCommit)
103+
assert.equal((await stat(target)).mode & 0o777, 0o555)
104+
assert.equal((await stat(path.join(target, 'issue-dev-loop'))).mode & 0o777, 0o555)
105+
106+
const manifest = JSON.parse(
107+
await readFile(
108+
path.join(target, 'issue-dev-loop', 'trusted-control-plane.json'),
109+
'utf8',
110+
),
111+
)
112+
assert.equal(manifest.bundleRoot, canonicalTarget)
113+
assert.equal(manifest.sourceCommit, sourceCommit)
114+
})

0 commit comments

Comments
 (0)