Ctrl K
ComunidadGuías…

scripts/tests/commit-staged-test.mjs

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import assert from 'node:assert/strict'
import {
  chmodSync,
  copyFileSync,
  existsSync,
  mkdirSync,
  readFileSync,
  rmSync,
  symlinkSync,
} from 'node:fs'
import { join } from 'node:path'
import test from 'node:test'
import { fixture, REPO } from './fixtures.mjs'

const SCRIPT = join(REPO, 'scripts/commit-staged.mjs')

function commitFixture(t) {
  const f = fixture(t)
  f.git('init', '-q')
  f.git('config', 'user.name', 'Fixture')
  f.git('config', 'user.email', 'fixture@example.com')
  f.git('config', 'commit.gpgsign', 'false')
  f.write('old.md', 'old\n')
  f.git('add', '.')
  f.git('commit', '-qm', 'fixture')
  f.base = f.git('rev-parse', 'HEAD').trim()
  f.capture = join(f.root, 'payload.json')
  f.message = f.write('message', 'chore: archive fragments\n\nDetails.\n')
  f.nodeExecutable(
    'bin/gh',
    `import { readFileSync, writeFileSync } from 'node:fs'
writeFileSync(process.env.CAPTURE, readFileSync(0))
console.log(JSON.stringify(process.env.FAIL
  ? { errors: [{ message: 'head moved' }] }
  : { data: { createCommitOnBranch: { commit: { oid: 'signed-oid' } } } }))
`,
  )
  Object.assign(f.env, {
    PATH: `${join(f.root, 'bin')}:${process.env.PATH}`,
    GITHUB_REPOSITORY: 'Start9Labs/fixture',
    CAPTURE: f.capture,
  })
  f.runScript = () =>
    f.run('node', [SCRIPT, f.message, 'master', f.base], { encoding: 'utf8' })
  f.payload = () => JSON.parse(readFileSync(f.capture, 'utf8')).variables.input
  return f
}

test('rename, large content and index ownership', t => {
  const f = commitFixture(t)
  f.git('mv', 'old.md', 'name with spaces.md')
  const contents = 'Large prose.\n'.repeat(20000)
  f.write('name with spaces.md', contents)
  f.git('add', 'name with spaces.md')
  f.write('name with spaces.md', 'unstaged content')
  const result = f.runScript()
  assert.equal(result.status, 0, result.stderr)
  const payload = f.payload()
  assert.equal(payload.expectedHeadOid, f.base)
  assert.deepEqual(payload.branch, {
    repositoryNameWithOwner: 'Start9Labs/fixture',
    branchName: 'master',
  })
  assert.deepEqual(payload.message, {
    headline: 'chore: archive fragments',
    body: 'Details.',
  })
  assert.deepEqual(payload.fileChanges.deletions, [{ path: 'old.md' }])
  const [addition] = payload.fileChanges.additions
  assert.equal(payload.fileChanges.additions.length, 1)
  assert.equal(addition.path, 'name with spaces.md')
  assert.equal(Buffer.from(addition.contents, 'base64').toString(), contents)
})

test('staged binary blob over one MiB', t => {
  const f = commitFixture(t)
  const contents = Buffer.alloc(256 * 8192)
  for (let i = 0; i < contents.length; i++) contents[i] = i % 256
  f.write('large.bin', contents)
  f.git('add', 'large.bin')
  f.write('large.bin', Buffer.from('unstaged'))
  const result = f.runScript()
  assert.equal(result.status, 0, result.stderr)
  assert.equal(result.stdout, 'signed-oid\n')
  const additions = f.payload().fileChanges.additions
  assert.equal(additions[0].path, 'large.bin')
  assert.deepEqual(Buffer.from(additions[0].contents, 'base64'), contents)
})

test('modes are not silently rewritten', t => {
  const f = commitFixture(t)
  for (const mode of ['symlink', 'executable']) {
    f.git('reset', '--hard', f.base)
    const path = join(f.root, 'unsupported')
    rmSync(path, { force: true })
    if (mode === 'symlink') symlinkSync('old.md', path)
    else {
      f.write('unsupported', '#!/bin/sh\n')
      chmodSync(path, 0o755)
    }
    f.git('add', 'unsupported')
    assert.equal(f.runScript().status, 2, mode)
    assert.equal(existsSync(f.capture), false, mode)
  }
})

test('deletion only', t => {
  const f = commitFixture(t)
  f.git('rm', 'old.md')
  const result = f.runScript()
  assert.equal(result.status, 0, result.stderr)
  assert.deepEqual(f.payload().fileChanges, {
    additions: [],
    deletions: [{ path: 'old.md' }],
  })
})

test('existing unsupported modes cannot be deleted or normalized', t => {
  const f = commitFixture(t)
  const originalBase = f.base
  for (const mode of ['symlink', 'executable', 'gitlink']) {
    for (const change of ['delete', 'normalize']) {
      f.git('reset', '--hard', originalBase)
      const path = join(f.root, 'unsupported')
      rmSync(path, { force: true })
      if (mode === 'gitlink') {
        f.git(
          'update-index',
          '--add',
          '--cacheinfo',
          `160000,${originalBase},unsupported`,
        )
      } else {
        if (mode === 'symlink') symlinkSync('old.md', path)
        else {
          f.write('unsupported', '#!/bin/sh\n')
          chmodSync(path, 0o755)
        }
        f.git('add', 'unsupported')
      }
      f.git('commit', '-qm', 'unsupported mode')
      f.base = f.git('rev-parse', 'HEAD').trim()
      rmSync(path, { force: true })
      f.git('update-index', '--force-remove', 'unsupported')
      if (change === 'normalize') {
        f.write('unsupported', 'ordinary file\n')
        f.git('add', 'unsupported')
      }
      const result = f.runScript()
      assert.equal(result.status, 2, `${mode}/${change}: ${result.stderr}`)
      assert.equal(existsSync(f.capture), false, `${mode}/${change}`)
    }
  }
})

test('new gitlink is rejected', t => {
  const f = commitFixture(t)
  f.git('update-index', '--add', '--cacheinfo', `160000,${f.base},submodule`)
  const result = f.runScript()
  assert.equal(result.status, 2, result.stderr)
  assert.equal(existsSync(f.capture), false)
})

test('GraphQL errors fail even with HTTP success', t => {
  const f = commitFixture(t)
  f.write('old.md', 'changed\n')
  f.git('add', 'old.md')
  f.env.FAIL = '1'
  const result = f.runScript()
  assert.notEqual(result.status, 0)
  assert.match(result.stderr, /head moved/)
})

test('tag compiler workflow with local commit API', t => {
  const f = commitFixture(t)
  mkdirSync(join(f.root, 'scripts'))
  for (const name of [
    'changelog.mjs',
    'changelog-version.mjs',
    'commit-staged.mjs',
    'docs-versions.mjs',
  ]) {
    copyFileSync(join(REPO, 'scripts', name), join(f.root, 'scripts', name))
  }
  copyFileSync(join(REPO, '.prettierrc.json'), join(f.root, '.prettierrc.json'))
  const pin = JSON.parse(readFileSync(join(REPO, 'package.json'), 'utf8'))
    .devDependencies.prettier
  f.write(
    'package.json',
    JSON.stringify({ devDependencies: { prettier: pin } }),
  )
  f.write(
    'projects/start-sdk/changelog/patch-fixed-released.md',
    '---\nrelease-notes: true\n---\n\n- Released fix.\n\n- Second released fix.\n',
  )
  f.write(
    'projects/start-sdk/changelog/patch-security-released.md',
    '---\nrelease-notes: true\n---\n\n- Released security fix.\n',
  )
  f.write(
    'projects/start-sdk/changelog/patch-security-released.pl_PL.md',
    '- Poprawka bezpieczeństwa.\n',
  )
  f.write(
    'projects/start-sdk/changelog/patch-fixed-second-released.md',
    '---\nrelease-notes: false\n---\n\n- Third released fix.\n',
  )
  f.write(
    'projects/start-sdk/changelog/patch-fixed-released.pl_PL.md',
    '- Poprawka.\n\n- Druga poprawka.\n',
  )
  f.write(
    'projects/start-sdk/release-notes/1.2.3.pl_PL.md',
    '## Nowości\n\n<!-- highlights -->\n',
  )
  f.write('projects/start-sdk/CHANGELOG.md', '# Changelog\n')
  f.git('add', 'scripts', 'projects', 'package.json', '.prettierrc.json')
  f.git('commit', '-qm', 'release')
  f.git('-c', 'tag.gpgsign=false', 'tag', 'start-sdk/v1.2.3')
  const catalog = 'shared-libs/crates/start-core/locales/release-notes.json'
  f.write(catalog, readFileSync(join(REPO, catalog)))
  f.git('add', 'shared-libs')
  f.git('commit', '-qm', 'compiler labels')
  const remote = join(f.root, 'origin.git')
  f.git('init', '--bare', '-q', remote)
  f.git('remote', 'add', 'origin', remote)
  f.git('push', '-q', 'origin', 'HEAD:master', 'HEAD:live-docs', '--tags')
  f.git('fetch', '-q', 'origin')
  f.git('checkout', '--detach', 'origin/live-docs')
  const mock = join(f.root, 'bin/gh.mjs')
  f.write(
    'bin/gh.mjs',
    String.raw`#!/usr/bin/env node
import assert from 'node:assert/strict'
import { spawnSync } from 'node:child_process'
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'

const payload = JSON.parse(readFileSync(0, 'utf8')).variables.input
const remote = process.env.LOCAL_REMOTE
const env = { ...process.env }
const marker = join(process.env.RUNNER_TEMP, 'raced')
const race = !existsSync(marker)
if (race) {
  writeFileSync(marker, '')
  payload.fileChanges = { deletions: [], additions: [{
    path: 'projects/start-sdk/changelog/patch-fixed-after-tag.md',
    contents: Buffer.from('---\nrelease-notes: false\n---\n\n- New work after the tag.\n').toString('base64'),
  }] }
}
function git(args, input) {
  const result = spawnSync('git', ['--git-dir', remote, ...args], { env, input, maxBuffer: Infinity })
  assert.ifError(result.error)
  assert.equal(result.status, 0, result.stderr.toString())
  return result.stdout.toString().trim()
}
const temp = mkdtempSync(join(tmpdir(), 'local-commit-api-'))
let oid
try {
  env.GIT_INDEX_FILE = join(temp, 'index')
  env.GIT_WORK_TREE = temp
  git(['read-tree', payload.expectedHeadOid])
  for (const deletion of payload.fileChanges.deletions) {
    git(['update-index', '--force-remove', deletion.path])
  }
  for (const addition of payload.fileChanges.additions) {
    const blob = git(['hash-object', '-w', '--stdin'], Buffer.from(addition.contents, 'base64'))
    git(['update-index', '--add', '--cacheinfo', '100644,' + blob + ',' + addition.path])
  }
  const tree = git(['write-tree'])
  oid = git(['-c', 'user.name=Fixture', '-c', 'user.email=fixture@example.com',
    '-c', 'commit.gpgsign=false', 'commit-tree', tree, '-p', payload.expectedHeadOid],
    Buffer.from(payload.message.headline))
  git(['update-ref', 'refs/heads/master', oid, payload.expectedHeadOid])
} finally {
  rmSync(temp, { recursive: true, force: true })
}
console.log(JSON.stringify(race
  ? { errors: [{ message: 'head moved' }] }
  : { data: { createCommitOnBranch: { commit: { oid } } } }))
`,
  )
  chmodSync(mock, 0o755)
  const workflow = readFileSync(
    join(REPO, '.github/workflows/docs-sync-on-tag.yml'),
    'utf8',
  )
  const block = workflow
    .split('      - name: Compile released changelogs onto master\n')[1]
    .split('        run: |\n')[1]
    .split('\n      - name:')[0]
  const shell = block
    .split('\n')
    .map(line => line.slice(10))
    .join('\n')
  const runnerTemp = join(f.root, 'runner-temp')
  mkdirSync(runnerTemp)
  Object.assign(f.env, {
    LOCAL_REMOTE: remote,
    RUNNER_TEMP: runnerTemp,
    GITHUB_REF_NAME: 'start-sdk/v1.2.3',
  })
  let result = f.run('bash', ['-c', shell], { encoding: 'utf8' })
  assert.equal(result.status, 0, result.stdout + result.stderr)
  assert.equal(f.git('status', '--porcelain', '--untracked-files=no'), '')
  assert.equal(
    f.git('rev-parse', 'HEAD'),
    f.git('rev-parse', 'origin/live-docs'),
  )
  const history = f.git('show', 'origin/master:projects/start-sdk/CHANGELOG.md')
  assert.equal(
    history,
    '# Changelog\n\n## [1.2.3]\n\n### Fixed\n\n- Released fix.\n\n- Second released fix.\n\n- Third released fix.\n\n### Security\n\n- Released security fix.\n',
  )
  assert.ok(
    !f
      .git('ls-tree', '-r', '--name-only', 'origin/master', 'projects')
      .includes('patch-fixed-released.md'),
  )
  assert.match(
    f.git(
      'show',
      'origin/master:projects/start-sdk/changelog/patch-fixed-after-tag.md',
    ),
    /New work after the tag\./,
  )
  assert.ok(!history.includes('New work after the tag.'))
  const notesPath = 'projects/start-sdk/release-notes/1.2.3.md'
  const notes = f.git('show', `origin/master:${notesPath}`)
  assert.equal(
    notes,
    '## Highlights\n\n- Released fix.\n\n- Second released fix.\n\n## Security\n\n- Released security fix.\n',
  )
  assert.match(result.stderr, /head moved/)
  const localizedPath = 'projects/start-sdk/release-notes/1.2.3.pl_PL.md'
  const localized = f.git('show', `origin/master:${localizedPath}`)
  assert.equal(
    localized,
    '## Nowości\n\n- Poprawka.\n\n- Druga poprawka.\n\n## Bezpieczeństwo\n\n- Poprawka bezpieczeństwa.\n',
  )
  assert.ok(existsSync(join(runnerTemp, 'scripts/changelog.mjs')))
  assert.deepEqual(
    readFileSync(join(runnerTemp, catalog)),
    readFileSync(join(REPO, catalog)),
  )
  assert.equal(
    f.git('ls-tree', '-r', '--name-only', 'start-sdk/v1.2.3', '--', catalog),
    '',
  )
  assert.ok(
    !f
      .git(
        'ls-tree',
        '-r',
        '--name-only',
        'origin/master',
        'projects/start-sdk/changelog',
      )
      .includes('.pl_PL.md'),
  )
  const master = f.git('rev-parse', 'origin/master')
  result = f.run('bash', ['-c', shell], { encoding: 'utf8' })
  assert.equal(result.status, 0, result.stdout + result.stderr)
  assert.equal(f.git('rev-parse', 'origin/master'), master)
  assert.equal(
    f.git('show', 'origin/master:projects/start-sdk/CHANGELOG.md'),
    history,
  )
  assert.equal(f.git('show', `origin/master:${notesPath}`), notes)
  const flat = f.write(
    'legacy-compiler/flat/changelog.mjs',
    readFileSync(join(REPO, 'scripts/changelog.mjs')),
  )
  f.write(
    'legacy-compiler/flat/changelog-version.mjs',
    readFileSync(join(REPO, 'scripts/changelog-version.mjs')),
  )
  assert.ok(!existsSync(join(f.root, 'legacy-compiler', catalog)))
  const legacy = f.run(
    process.execPath,
    [
      flat,
      'notes',
      'projects/start-sdk',
      '1.2.3',
      '--locale',
      'pl_PL',
      '--ref',
      'start-sdk/v1.2.3',
    ],
    { encoding: 'utf8' },
  )
  assert.equal(legacy.status, 0, legacy.stderr)
  assert.equal(legacy.stdout, localized)
  f.git('read-tree', '-u', '--reset', 'start-sdk/v1.2.3')
  f.env.PROJECT = 'start-sdk'
  const archive = workflow
    .slice(
      workflow.indexOf(
        '          git ls-tree -r --name-only origin/master -- projects/',
      ),
      workflow.indexOf('          git add -A'),
    )
    .split('\n')
    .map(line => line.slice(10))
    .join('\n')
  const copied = f.run('bash', ['-euo', 'pipefail', '-c', archive], {
    encoding: 'utf8',
  })
  assert.equal(copied.status, 0, copied.stdout + copied.stderr)
  assert.equal(f.git('show', `:${notesPath}`), notes)
  assert.equal(f.git('show', `:${localizedPath}`), localized)
})

test('empty index makes no request', t => {
  const f = commitFixture(t)
  assert.equal(f.runScript().status, 0)
  assert.equal(existsSync(f.capture), false)
})