mirror of
https://github.com/storytold/craft-common-actions.git
synced 2026-10-31 07:48:02 +00:00
130 lines
4.8 KiB
Python
130 lines
4.8 KiB
Python
"""Unit tests for actions/resolve-version/action.yml."""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
import re
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
|
|
import yaml
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
ACTION = ROOT / 'actions/resolve-version/action.yml'
|
|
|
|
|
|
class ResolveVersionTests(unittest.TestCase):
|
|
def setUp(self):
|
|
self.data = yaml.safe_load(ACTION.read_text())
|
|
self.step = self.data['runs']['steps'][0]
|
|
|
|
def _run_action(self, input_version="", version_env="", app_title="Test App", env_sh=None):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
work = Path(tmpdir)
|
|
if env_sh:
|
|
pkg = work / "packaging"
|
|
pkg.mkdir()
|
|
(pkg / "env.sh").write_text(env_sh)
|
|
output_file = work / "output"
|
|
summary_file = work / "summary"
|
|
env = {
|
|
**os.environ,
|
|
'INPUT_VERSION': input_version,
|
|
'VERSION': version_env,
|
|
'APP_TITLE': app_title,
|
|
'GITHUB_OUTPUT': str(output_file),
|
|
'GITHUB_STEP_SUMMARY': str(summary_file),
|
|
'GITHUB_SHA': 'abcdef1234567890',
|
|
}
|
|
res = subprocess.run(
|
|
['bash', '-euo', 'pipefail', '-c', self.step['run']],
|
|
cwd=work,
|
|
env=env,
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
outputs = {}
|
|
if output_file.exists():
|
|
for line in output_file.read_text().splitlines():
|
|
if '=' in line:
|
|
k, v = line.split('=', 1)
|
|
outputs[k] = v
|
|
summary = summary_file.read_text() if summary_file.exists() else ""
|
|
return res, outputs, summary
|
|
|
|
def test_valid_versions(self):
|
|
cases = [
|
|
("1.2.3", "1.2.3", "false"),
|
|
("v1.2.3", "1.2.3", "false"),
|
|
("0.1.0-alpha.1", "0.1.0-alpha.1", "true"),
|
|
("2.0.0-rc-1", "2.0.0-rc-1", "true"),
|
|
("10.20.30", "10.20.30", "false"),
|
|
]
|
|
for input_ver, expected_ver, expected_pre in cases:
|
|
with self.subTest(input_ver=input_ver):
|
|
res, outputs, summary = self._run_action(input_version=input_ver)
|
|
self.assertEqual(res.returncode, 0, f"{res.stderr}\n{res.stdout}")
|
|
self.assertEqual(outputs.get('version'), expected_ver)
|
|
self.assertEqual(outputs.get('prerelease'), expected_pre)
|
|
self.assertRegex(outputs.get('date', ''), r'^[0-9]{4}-[0-9]{2}-[0-9]{2}$')
|
|
self.assertIn(f"v{expected_ver}", summary)
|
|
|
|
def test_app_title_crlf_stripped_from_summary(self):
|
|
res, outputs, summary = self._run_action(
|
|
input_version="1.2.3",
|
|
app_title="My\r\nApp\nTitle",
|
|
)
|
|
self.assertEqual(res.returncode, 0, f"{res.stderr}\n{res.stdout}")
|
|
self.assertNotIn("\r", summary)
|
|
self.assertEqual(summary.count("\n"), 1)
|
|
self.assertIn("My App Title", summary)
|
|
|
|
def test_fallback_to_version_env_and_env_sh(self):
|
|
res, outputs, _ = self._run_action(version_env="3.4.5")
|
|
self.assertEqual(res.returncode, 0)
|
|
self.assertEqual(outputs.get('version'), "3.4.5")
|
|
|
|
res, outputs, _ = self._run_action(env_sh='VERSION="4.5.6"\n')
|
|
self.assertEqual(res.returncode, 0)
|
|
self.assertEqual(outputs.get('version'), "4.5.6")
|
|
|
|
def test_newlines_and_cr_rejected(self):
|
|
bad_versions = [
|
|
"1.2.3\ndate=2026-01-01",
|
|
"1.2.3\r\nversion=fake",
|
|
"\n1.2.3",
|
|
"1.2.3\n",
|
|
"1.2.3\r",
|
|
"1.2.3\r\ndate=2026-01-01",
|
|
]
|
|
for bad_ver in bad_versions:
|
|
with self.subTest(bad_ver=repr(bad_ver)):
|
|
res, outputs, _ = self._run_action(input_version=bad_ver)
|
|
self.assertNotEqual(res.returncode, 0)
|
|
self.assertIn("must not contain carriage returns or newlines", res.stdout + res.stderr)
|
|
self.assertEqual(outputs, {})
|
|
|
|
def test_invalid_semver_rejected(self):
|
|
invalid_versions = [
|
|
"1.2",
|
|
"1.2.3.4",
|
|
"01.2.3",
|
|
"1.02.3",
|
|
"foo",
|
|
"1.2.3; touch injected",
|
|
"$(touch injected)",
|
|
"`touch injected`",
|
|
"1.2.3-",
|
|
"1.2.3+",
|
|
]
|
|
for bad_ver in invalid_versions:
|
|
with self.subTest(bad_ver=bad_ver):
|
|
res, outputs, _ = self._run_action(input_version=bad_ver)
|
|
self.assertNotEqual(res.returncode, 0)
|
|
self.assertIn("is not a version like 1.2.3 or 1.2.3-rc.1", res.stdout + res.stderr)
|
|
self.assertEqual(outputs, {})
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|