From 20ebee3cb1eef69f886b98d566aa07552ee0196f Mon Sep 17 00:00:00 2001 From: FredApps <153173854+FredApps@users.noreply.github.com> Date: Fri, 13 Nov 2026 06:33:06 +0100 Subject: [PATCH] fix(ci): provide pinned translations to coverage tests (#227) * fix(ci): provide pinned translations to coverage tests * fix(ci): keep translation checkout out of scan --------- Co-authored-by: FredApps --- .github/workflows/sonarcloud.yml | 17 +++++++++++++++ tests/test_sonarcloud.py | 37 ++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index fd54c11..43eafac 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -225,6 +225,8 @@ jobs: uses: storytold/craft-common-actions/actions/checkout-craft-fonts@main with: ref: ${{ inputs.fonts-ref }} + - name: Check out craft-i18n + uses: storytold/craft-common-actions/actions/checkout-craft-i18n@main - name: Require requested craft-fonts if: inputs.fonts-ref != '' shell: bash @@ -353,6 +355,8 @@ jobs: uses: storytold/craft-common-actions/actions/checkout-craft-fonts@main with: ref: ${{ inputs.fonts-ref }} + - name: Check out craft-i18n + uses: storytold/craft-common-actions/actions/checkout-craft-i18n@main - name: Require requested craft-fonts if: inputs.fonts-ref != '' shell: bash @@ -574,6 +578,10 @@ jobs: uses: storytold/craft-common-actions/actions/checkout-craft-fonts@main with: ref: ${{ inputs.fonts-ref }} + - name: Check out craft-i18n + if: steps.token.outputs.available == 'true' && inputs.shards <= 1 + id: i18n + uses: storytold/craft-common-actions/actions/checkout-craft-i18n@main - name: Require requested craft-fonts if: inputs.fonts-ref != '' && steps.token.outputs.available == 'true' && inputs.shards <= 1 shell: bash @@ -756,6 +764,15 @@ jobs: status=0 npm run --silent -- "$NODE_COVERAGE_SCRIPT" || status=$? echo "status=$status" >>"$GITHUB_OUTPUT" + # The checkout is a build input, not caller source. Moving it after all coverage runs + # prevents an unsharded scan from counting another repository's files as this project. + - name: Move craft-i18n outside scan workspace + if: steps.i18n.outputs.rev != '' + shell: bash + run: | + set -euo pipefail + destination="$(mktemp -d "$RUNNER_TEMP/craft-i18n.XXXXXX")" + mv -- "$GITHUB_WORKSPACE/craft-i18n" "$destination/checkout" - name: SonarCloud Scan if: steps.token.outputs.available == 'true' uses: step-security/sonarqube-scan-action@c2312f8888f2bff4220bd815febb9d4a7cb32433 # v8.2.1 diff --git a/tests/test_sonarcloud.py b/tests/test_sonarcloud.py index a991f76..f2d1a83 100644 --- a/tests/test_sonarcloud.py +++ b/tests/test_sonarcloud.py @@ -143,6 +143,43 @@ class SonarCloudTests(unittest.TestCase): else: self.assertRegex(step['uses'], r'^[^@]+@[0-9a-f]{40}$') + def test_caller_i18n_is_available_before_each_coverage_run(self): + workflow = yaml.load( + (ROOT / '.github/workflows/sonarcloud.yml').read_text(), Loader=yaml.BaseLoader) + for job, runner_name in [('build', 'Build instrumented test archive'), + ('coverage', "Run this shard's tests"), + ('sonarcloud', 'Generate Rust coverage')]: + steps = workflow['jobs'][job]['steps'] + checkout = next(step for step in steps if step.get('name') == 'Check out craft-i18n') + runner = next(step for step in steps if step.get('name') == runner_name) + self.assertEqual(checkout['uses'], 'storytold/craft-common-actions/actions/checkout-craft-i18n@main') + self.assertLess(steps.index(checkout), steps.index(runner)) + if job == 'sonarcloud': + self.assertIn('inputs.shards <= 1', checkout['if']) + self.assertIn("steps.token.outputs.available == 'true'", checkout['if']) + self.assertEqual(checkout['id'], 'i18n') + + steps = workflow['jobs']['sonarcloud']['steps'] + move = next(step for step in steps if step.get('name') == 'Move craft-i18n outside scan workspace') + coverage = next(step for step in steps if step.get('name') == 'Generate Rust coverage') + scan = next(step for step in steps if step.get('name') == 'SonarCloud Scan') + self.assertEqual(move['if'], "steps.i18n.outputs.rev != ''") + self.assertLess(steps.index(coverage), steps.index(move)) + self.assertLess(steps.index(move), steps.index(scan)) + with tempfile.TemporaryDirectory() as temp: + root = Path(temp) + workspace, runner = root / 'workspace', root / 'runner' + (workspace / 'craft-i18n').mkdir(parents=True) + runner.mkdir() + (workspace / 'craft-i18n' / 'catalog').write_text('pinned') + result = subprocess.run( + ['bash', '-e', '-o', 'pipefail', '-c', move['run']], + env={**os.environ, 'GITHUB_WORKSPACE': str(workspace), 'RUNNER_TEMP': str(runner)}, + capture_output=True, text=True) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertFalse((workspace / 'craft-i18n').exists()) + self.assertEqual([p.read_text() for p in runner.glob('craft-i18n.*/checkout/catalog')], ['pinned']) + def test_archive_build_has_the_same_fonts_as_runtime(self): workflow = yaml.load( (ROOT / '.github/workflows/sonarcloud.yml').read_text(), Loader=yaml.BaseLoader)