-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Overview
Evolve runtime_ci_tooling from today’s user-preserved YAML injection (pre-test/post-test/extra-jobs) into a structured, config-driven CI orchestrator that:
- Runs multi-platform CI (macOS/Linux/Windows) across x64 + arm64 using org-managed GitHub-hosted runners where configured.
- Lets downstream consumers register reusable workflow modules (extension blocks) that
manage_cicd init/update/validatecan discover/install/validate/wire automatically. - Supports multi-package repos (root +
sub_packages) with configurable matrix strategies to avoid job explosion. - Enables single consolidated release that aggregates multi-platform build artifacts from the CI run and attaches them to the GitHub Release.
This should generalize the orchestration pattern used in aot_monorepo/.github/workflows/workflow.yaml + reusable-module-composition.yaml into a reusable system for any repo that consumes runtime_ci_tooling.
Background / Current State
What works today
- CI workflow generation is templated (
templates/github/workflows/ci.skeleton.yaml) via Mustache, driven by.runtime_ci/config.jsonci.*. - Update flow is manifest-driven (
templates/manifest.json) and supports categories: overwritable/cautious/templated/mergeable/regeneratable. - CI supports user-preserved sections via markers:
# --- BEGIN USER: pre-test ---# --- BEGIN USER: post-test ---# --- BEGIN USER: extra-jobs ---(added recently)
Gaps / Misalignments we must fix
inithardcodes config defaults (lib/src/cli/commands/init_command.dart) instead of usingtemplates/config.json→ config drift is real (missing keys likeci.platforms/ci.runner_overrides, and differing defaults).validateonly checks syntactic validity (JSON/YAML parse) and does not validate the semantics of.runtime_ci/config.jsonor CI config consistency.- Extensions are currently “copy/paste YAML blocks” with no schema or validation.
- Release flow (
.github/workflows/release.yaml) does not yet aggregate artifacts produced by CI matrix jobs into a single release.
Goals
-
Structured extensibility
- Downstream repos can declare extension workflows/modules in
.runtime_ci/config.json. manage_cicd update --workflows:- installs extension reusable workflows into
.github/workflows/ - validates their
workflow_callinterface - generates static
uses: ./.github/workflows/<ext>.yamljobs (GitHub Actions requires staticuses:)
- installs extension reusable workflows into
- Downstream repos can declare extension workflows/modules in
-
Platform matrix orchestration
- Standardize on a platform config JSON schema usable by base CI + extension modules:
{ platform_id, runner, name, system_information, architecture }
- Support per-org runner overrides (already started via
ci.runner_overrides).
- Standardize on a platform config JSON schema usable by base CI + extension modules:
-
Multi-package repos
- Extend beyond “extra analyze steps” to a pipeline model:
platforms × packages × phases. - Provide configurable strategies to avoid N×M job explosions.
- Extend beyond “extra analyze steps” to a pipeline model:
-
Release aggregation
- Release workflow downloads artifacts from the triggering CI run (
workflow_runevent) usinggithub.event.workflow_run.id. - Aggregate per-platform/per-package build artifacts and attach to the GitHub Release.
- Release workflow downloads artifacts from the triggering CI run (
Non-goals (v1)
- Dynamic
uses:in YAML (not supported by GitHub Actions); generation must emit staticusesblocks. - Arbitrary remote fetching of extension workflows from other repos (v2+). Start with local/monorepo file sources.
Proposed Design (v1)
A) Make init template-driven (eliminate drift)
Problem: init_command.dart currently hardcodes the default config.
Solution:
- Load
templates/config.jsonas the base document. - Overlay detected values:
repository.name,repository.owner, derived labels, etc.
- Write the merged result to
.runtime_ci/config.json.
Files:
- Modify:
lib/src/cli/commands/init_command.dart - Read from:
templates/config.json
Acceptance: init output includes all keys from the template (including new ones as templates evolve).
B) Make validate semantic and CI-aware
Problem: validate only checks parseability.
Solution:
- Parse
.runtime_ci/config.jsonand validate:ci.*viaWorkflowGenerator.validate()extensions.*via newExtensionValidator
- Validate that
ci.platformsandci.runner_overridesare consistent. - Validate that extension workflows exist and have expected
workflow_callinputs/outputs.
Files:
- Modify:
lib/src/cli/commands/validate_command.dart - Modify:
lib/src/cli/utils/ci_constants.dartto include.runtime_ci/config.json(or explicitly load it in validate) - Add:
lib/src/cli/utils/extension_validator.dart(or similar)
C) Add extension registry schema to .runtime_ci/config.json
Add a top-level extensions key (or ci.extensions; top-level recommended).
{
"extensions": {
"workflows": [
{
"id": "ipc-fixtures",
"source": ".runtime_ci/extensions/workflows/ipc-fixtures.yaml",
"destination": ".github/workflows/runtime-ci-ext-ipc-fixtures.yaml",
"required": true,
"validation": {
"require_workflow_call": true,
"required_inputs": ["matrix-config", "dart-sdk"],
"required_outputs": []
}
}
],
"modules": [
{
"id": "ipc-fixtures",
"enabled": true,
"uses": "./.github/workflows/runtime-ci-ext-ipc-fixtures.yaml",
"needs": ["test"],
"platforms": ["windows-x64", "windows-arm64"],
"with": {
"some-module-input": "value"
}
}
]
}
}Notes:
workflows[]tells update how to install reusable workflows into.github/workflows/.modules[]tells the CI generator how to wire jobs that call those workflows.- Each extension workflow must expose
on: workflow_call.
D) Standardize platform config JSON for base + extensions
We already have a JSON-like schema in aot_monorepo/.github/workflows/workflow.yaml and reusable-module-composition.yaml.
Adopt (or align to) that object schema so modules can simply do:
strategy:
matrix:
config:
- ${{ fromJSON(inputs.matrix-config) }}And then runs-on: ${{ matrix.config.runner }}.
runtime_ci_tooling should generate the same shape for its platform include list, so extensions can be platform-aware without ad hoc logic.
E) Update manage_cicd update --workflows to install + wire extensions
Enhance UpdateCommand templated workflow generation:
- Before rendering CI workflow, load
extensions.workflows. - Copy workflow sources to destinations (create directories as needed).
- Validate installed workflows.
- Provide
extensions.modulesto the workflow template rendering context.
Template change:
- In
templates/github/workflows/ci.skeleton.yaml, add a section that emits extension module jobs from context.
Keep existing user-preserved sections for backward compatibility.
F) Multi-package pipeline model (incremental)
Current ci.sub_packages only adds extra analyze steps; it does not provide per-package CI phases or per-platform runs.
Introduce ci.pipeline (or similar) to model:
- packages:
root+sub_packages - phases: analyze/test/build/docs
- matrix strategy:
sequential_steps(today)per_platformper_packageper_package_per_platform(opt-in)
Start with a conservative default that avoids job explosion.
Related: #17 (Multi-package support)
G) Release: aggregate artifacts from CI workflow run
The release pipeline is workflow_run driven. For multi-platform builds, we need a first-class aggregation step.
Implement an aggregate-artifacts job in release workflow that:
- downloads artifacts from the triggering CI run (
github.event.workflow_run.id) - normalizes into a directory like:
release-artifacts/<platform_id>/<package_name>/...
- uploads a single artifact
release-artifacts
Then create-release downloads it and uses gh release upload.
Docs reference: GitHub Docs note that downloading artifacts from a different run requires token + run identifier.
Documentation Updates
Add a clear "Downstream Extensibility" section to:
SETUP.mdUSAGE.md
Include:
- What
extensionsis - The workflow_call interface contract
- Examples (local extensions and monorepo package-provided extensions)
- How
validatereports extension errors
Test Plan
- Unit tests:
initproduces config matching template keys (no missing keys)validatefails on invalidci.platformsvaluesvalidatefails when extension workflow is missing / lacksworkflow_callupdate --workflowsinstalls extension workflows and emits CI jobs calling them
- Golden file tests (optional but valuable):
- render CI YAML from a sample config with extensions and compare to expected output
Acceptance Criteria
-
manage_cicd initoutput config matchestemplates/config.jsonschema (no drift). -
manage_cicd validateperforms semantic validation of.runtime_ci/config.json(platform IDs, runner overrides, extensions). - Consumer repo can define an extension reusable workflow + register it in config;
update --workflowsinstalls + wires it into CI. - CI generation emits static
uses:jobs for extension modules (no runtime YAML hacks). - Release workflow can download artifacts from the triggering CI run, aggregate them, and attach them to a single GitHub Release.
- Multi-package repos have a documented/configurable path to run platform CI without uncontrolled job explosion.
Related Issues
- feat: custom CI/CD step injection for consumer-specific workflows #16 feat: custom CI/CD step injection for consumer-specific workflows
- feat: Multi-package support for CLI commands (analyze, test, autodoc, changelog, release notes) #17 feat: Multi-package support for CLI commands (analyze, test, autodoc, changelog, release notes)
- Add config schema version + platforms to init/reference defaults #14 Add config schema version + platforms to init/reference defaults
- Add sub_packages validation to validate() #9 Add sub_packages validation to validate()
This issue is intended to act as the umbrella/architecture item tying those together with reusable workflow module composition + release artifact aggregation.