feat(gate): support caller setup commands (#224)

This commit is contained in:
Dylan M. Taylor authored and GitHub committed 2026-11-12 21:51:38 -05:00
1 parent 804f702057
commit fd88e26a87
3 files changed
+49

No files matched your search

+15
View File
@@ -17,6 +17,11 @@ on:
type: string
required: false
default: "cargo xtask ci"
setup-command:
description: "Optional setup script, run from the repository root before the gate (for example, fetch SHA-verified corpora)"
type: string
required: false
default: ""
windows-command:
description: "The gate on Windows legs; empty runs `command`"
type: string
@@ -274,6 +279,16 @@ jobs:
save-if: ${{ github.event_name != 'pull_request' && (github.ref_name == github.event.repository.default_branch || (inputs.cache-save-on-dispatch && github.event_name == 'workflow_dispatch')) }}
cache-on-failure: true
- name: Caller setup
if: inputs.setup-command != ''
shell: bash
env:
SETUP: ${{ inputs.setup-command }}
run: |
set -euo pipefail
printf '%s\n' "$SETUP" > "$RUNNER_TEMP/gate-setup.sh"
bash -euo pipefail "$RUNNER_TEMP/gate-setup.sh"
- name: Gate
shell: bash
env:
+7
View File
@@ -513,6 +513,8 @@ The quality gate for an app's pull requests and pushes to main. It runs `command
- the app and craft-fonts (at the suite's pin, with `CRAFT_FONTS_REQUIRED=1`) checked out without
persisted credentials, and craft-i18n when the app has `craft-i18n.rev`;
- `packages` installed through `actions/install-apt-packages` on Linux legs (none when empty);
- an optional `setup-command` run from the repository root before the gate, for fetching pinned
test data such as licensed corpora; its environment changes can be written to `$GITHUB_ENV`;
- the channel from `rust-toolchain.toml`, or `toolchain`, with clippy, rustfmt and `targets`;
- prebuilt cargo tools from `tools` (by default `cargo-nextest@0.9.150`);
- `CARGO_PROFILE_DEV_DEBUG=line-tables-only` (set `dev-debug: ""` to keep the repository's
@@ -541,6 +543,11 @@ check, can be a second call with its own `command`, `os`, `tools` and `targets`,
command: packaging/web/package.sh
```
`setup-command` is also passed through the environment, then run with Bash from the checkout root.
Use it for caller-specific test inputs whose contents are pinned and verified by the caller's
fetcher. For example, a corpus-enabled workspace can fetch its locked corpus before running the
gate and export `CRAFT_PSD_CORPUS` through `$GITHUB_ENV`; a failed fetch stops the job before tests.
#### Caller Example:
```yaml
name: CI
+27
View File
@@ -135,6 +135,33 @@ class CallerEnvironmentTests(unittest.TestCase):
self.assertEqual(self.run_step(ALL=f'GOOD=1\n{line}')[0], 1)
class CallerSetupTests(unittest.TestCase):
STEP = step('Caller setup')
def run_step(self, setup):
with tempfile.TemporaryDirectory() as directory:
github_env = Path(directory, 'github_env')
github_env.touch()
result = subprocess.run(
['bash', '--noprofile', '--norc', '-eo', 'pipefail', '-c', self.STEP['run']],
cwd=directory, capture_output=True, text=True,
env={**os.environ, 'SETUP': setup, 'RUNNER_TEMP': directory,
'GITHUB_ENV': str(github_env)})
return result.returncode, github_env.read_text().splitlines(), Path(directory, 'setup-ran').exists()
def test_setup_input_is_passed_through_env_before_the_gate(self):
self.assertEqual(set(self.STEP['env']), {'SETUP'})
self.assertLess(STEPS.index(self.STEP), STEPS.index(step('Gate')))
self.assertNotIn('${{', self.STEP['run'])
def test_setup_can_provision_data_and_export_its_path(self):
setup = 'touch setup-ran\necho "CRAFT_PSD_CORPUS=/corpus" >> "$GITHUB_ENV"'
self.assertEqual(self.run_step(setup), (0, ['CRAFT_PSD_CORPUS=/corpus'], True))
def test_setup_failure_stops_the_gate_job(self):
self.assertEqual(self.run_step('exit 17')[0], 17)
class ProfileCacheTests(unittest.TestCase):
def key(self, manifest):
with tempfile.TemporaryDirectory() as directory: