-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathgenerate-deploy-env.ts
More file actions
94 lines (80 loc) · 2.63 KB
/
Copy pathgenerate-deploy-env.ts
File metadata and controls
94 lines (80 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/usr/bin/env bun
import { readFileSync, writeFileSync } from "node:fs"
import { resolve } from "node:path"
type ManifestVariable = {
name: string
sourceEnv: string
required?: boolean
defaultValue?: string
}
type Manifest = {
variables: ManifestVariable[]
}
function parseArgs(argv: string[]) {
const args = new Map<string, string>()
for (let i = 2; i < argv.length; i += 1) {
const key = argv[i]
const value = argv[i + 1]
if (!key.startsWith("--")) throw new Error(`Invalid argument: ${key}`)
if (!value || value.startsWith("--")) throw new Error(`Missing value for ${key}`)
args.set(key.slice(2), value)
i += 1
}
return args
}
function shellQuote(value: string) {
return `'${String(value).replaceAll("'", "'\\''")}'`
}
function readManifest(path: string) {
const parsed = JSON.parse(readFileSync(path, "utf8")) as Manifest
if (!Array.isArray(parsed.variables)) {
throw new Error(`Manifest must contain "variables" array: ${path}`)
}
return parsed.variables
}
function resolveValue(entry: ManifestVariable) {
const raw = process.env[entry.sourceEnv]
if (raw !== undefined && raw !== "") return raw
if (entry.defaultValue !== undefined) return entry.defaultValue
if (entry.required) {
throw new Error(
`Missing required value for ${entry.name} (expected process.env.${entry.sourceEnv})`,
)
}
return ""
}
function main() {
const args = parseArgs(process.argv)
const manifestArg = args.get("manifest")
const outputArg = args.get("output")
if (!manifestArg || !outputArg) {
throw new Error(
"Usage: bun .github/scripts/generate-deploy-env.ts --manifest <path> --output <path>",
)
}
const manifestPath = resolve(manifestArg)
const outputPath = resolve(outputArg)
const manifest = readManifest(manifestPath)
const seen = new Set<string>()
const lines: string[] = []
const missing: string[] = []
for (const entry of manifest) {
if (!entry.name || !entry.sourceEnv) {
throw new Error(`Each manifest entry needs name + sourceEnv: ${JSON.stringify(entry)}`)
}
if (seen.has(entry.name)) throw new Error(`Duplicate variable in manifest: ${entry.name}`)
seen.add(entry.name)
try {
const value = resolveValue(entry)
lines.push(`${entry.name}=${shellQuote(value)}`)
} catch (error) {
missing.push(error instanceof Error ? error.message : String(error))
}
}
if (missing.length) {
throw new Error(`Cannot generate deploy env file:\n- ${missing.join("\n- ")}`)
}
writeFileSync(outputPath, `${lines.join("\n")}\n`, "utf8")
process.stdout.write(`Wrote ${lines.length} variables to ${outputPath}\n`)
}
main()