OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay / scripts / write-github-env.mjs

70 lines · javascript ref:
#!/usr/bin/env node

import fs from 'node:fs'

const usage = `
Usage:
  node scripts/write-github-env.mjs <NAME> <VALUE> [--github-env <path>]

Writes one checked NAME=VALUE line to GitHub's environment file.
Values with control characters are rejected so untrusted metadata cannot create
extra environment assignments.
`

const args = parseArgs(process.argv.slice(2))
const githubEnv = args.githubEnv || process.env.GITHUB_ENV || ''

if (!args.name || args.value === undefined) die(usage.trim())
if (!githubEnv) die('GITHUB_ENV is not set; pass --github-env <path>.')
if (!/^[A-Z_][A-Z0-9_]*$/.test(args.name)) {
  die(`Refusing to write malformed GitHub environment variable name: ${JSON.stringify(args.name)}`)
}

const value = String(args.value)
if (hasControlChars(value)) {
  die(`Refusing to write multi-line or control-character value for ${args.name} to GitHub environment file`)
}

fs.appendFileSync(githubEnv, `${args.name}=${value}\n`)

function parseArgs (argv) {
  const out = {}
  const positional = []
  for (let i = 0; i < argv.length; i++) {
    const arg = argv[i]
    if (arg === '--help' || arg === '-h') {
      console.log(usage.trim())
      process.exit(0)
    }
    if (arg === '--github-env') {
      out.githubEnv = readValue(argv, ++i, arg)
      continue
    }
    if (arg.startsWith('--')) die(`Unknown argument: ${arg}`)
    positional.push(arg)
  }
  if (positional.length !== 2) die(usage.trim())
  out.name = positional[0]
  out.value = positional[1]
  return out
}

function readValue (argv, index, flag) {
  const value = argv[index]
  if (!value || value.startsWith('--')) die(`Missing value for ${flag}`)
  return value
}

function hasControlChars (value) {
  for (let i = 0; i < value.length; i++) {
    const code = value.charCodeAt(i)
    if (code <= 31 || code === 127) return true
  }
  return false
}

function die (message) {
  console.error(message)
  process.exit(1)
}