mirror of
https://github.com/storytold/craft-common-actions.git
synced 2026-10-31 07:48:02 +00:00
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
111 lines
5.3 KiB
Python
111 lines
5.3 KiB
Python
"""Exercise the release workflow's app-name boundary with fixture commands."""
|
|
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
|
|
import yaml
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
WORKFLOW = ROOT / '.github/workflows/release.yml'
|
|
DATA = yaml.load(WORKFLOW.read_text(), Loader=yaml.BaseLoader)
|
|
EXPRESSION = '${{ inputs.app-name }}'
|
|
|
|
|
|
class ReleaseInputTests(unittest.TestCase):
|
|
def run_step(self, job_name, step_name, app_name, cli=False):
|
|
job = DATA['jobs'][job_name]
|
|
step = next(step for step in job['steps'] if step.get('name') == step_name)
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
root = Path(directory)
|
|
tools = root / 'tools'
|
|
tools.mkdir()
|
|
for name, source in {
|
|
'git': 'import sys\nsys.exit(0)\n',
|
|
'cargo': '''import json, os, sys
|
|
from pathlib import Path
|
|
if sys.argv[1] == 'metadata':
|
|
names = [os.environ['TEST_APP_NAME']]
|
|
if os.environ['TEST_CLI'] == 'true':
|
|
names.append(os.environ['TEST_APP_NAME'] + '-cli')
|
|
print(json.dumps({'packages': [{'name': name} for name in names]}))
|
|
else:
|
|
Path('args.json').write_text(json.dumps(sys.argv[1:]))
|
|
sys.exit(31) # Stop before packaging; real archives are covered separately.
|
|
''',
|
|
'tar': '''import json, sys
|
|
from pathlib import Path
|
|
Path('args.json').write_text(json.dumps(sys.argv[1:]))
|
|
''',
|
|
}.items():
|
|
tool = tools / name
|
|
tool.write_text(f'#!{sys.executable}\n' + source)
|
|
tool.chmod(0o755)
|
|
env = dict(os.environ, PATH=str(tools) + os.pathsep + os.environ['PATH'],
|
|
HOME=str(root), TEST_APP_NAME=app_name, TEST_CLI=str(cli).lower())
|
|
configured = {**job.get('env', {}), **step.get('env', {})}
|
|
if job_name == 'freebsd':
|
|
vm = next(item for item in job['steps']
|
|
if item.get('uses', '').startswith('vmactions/freebsd-vm@'))
|
|
forwarded = vm['with']['envs'].split()
|
|
configured = {key: value for key, value in configured.items() if key in forwarded}
|
|
env.update({key: value.replace(EXPRESSION, app_name)
|
|
for key, value in configured.items()})
|
|
env.update(VERSION='1.2.3', INPUT_VERSION='')
|
|
# Model GitHub expression replacement in source as well as env so a
|
|
# regression to interpolation executes the payload in this fixture.
|
|
script = step['run'].replace(EXPRESSION, app_name)
|
|
script = script.replace('${{ matrix.arch }}', 'x86_64')
|
|
script = script.replace('${{ steps.cargo-cache.outcome }}', 'success')
|
|
script = script.replace('/var/tmp/', str(root) + '/')
|
|
shell = 'sh' if job_name == 'freebsd' else 'bash'
|
|
result = subprocess.run([shell, '-eu', '-c', script], cwd=root, env=env,
|
|
capture_output=True, text=True, timeout=10)
|
|
log = root / 'args.json'
|
|
return result, json.loads(log.read_text()) if log.exists() else None, (root / 'injected').exists()
|
|
|
|
def test_freebsd_package_arguments(self):
|
|
for app_name in ('pdfcraft', 'craft-launcher', 'Craft_2'):
|
|
for cli in (False, True):
|
|
with self.subTest(app_name=app_name, cli=cli):
|
|
result, args, injected = self.run_step('freebsd', 'Build and package', app_name, cli)
|
|
self.assertEqual(result.returncode, 31, result.stderr)
|
|
expected = ['build', '--release', '--locked', '-p', app_name]
|
|
if cli:
|
|
expected.extend(['-p', app_name + '-cli'])
|
|
self.assertEqual(args, expected)
|
|
self.assertFalse(injected)
|
|
|
|
def test_app_name_is_literal_at_both_shell_sinks(self):
|
|
for app_name in (
|
|
'fixture$(touch injected)', 'fixture`touch injected`',
|
|
'fixture; touch injected; #', 'fixture"; touch injected; #',
|
|
"fixture'; touch injected; #", 'fixture\ntouch injected\n#',
|
|
'fixture --features injected', 'fixture*',
|
|
):
|
|
for job, step in (('freebsd', 'Build and package'), ('server', 'Check the archive')):
|
|
with self.subTest(app_name=app_name, job=job):
|
|
result, args, injected = self.run_step(job, step, app_name)
|
|
self.assertFalse(injected, result.stderr)
|
|
if job == 'freebsd':
|
|
self.assertEqual(result.returncode, 31, result.stderr)
|
|
self.assertEqual(args, ['build', '--release', '--locked', '-p', app_name])
|
|
else:
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
self.assertEqual(args, ['-tzf', f'dist/release/{app_name}-server-1.2.3-linux-x86_64.tar.gz'])
|
|
|
|
def test_server_archive_name_is_preserved(self):
|
|
result, args, injected = self.run_step('server', 'Check the archive', 'pdfcraft')
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
self.assertEqual(args, ['-tzf', 'dist/release/pdfcraft-server-1.2.3-linux-x86_64.tar.gz'])
|
|
self.assertFalse(injected)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|