Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Added

- `gen circleci`: `--skip-ats` opts an app repo out of the ATS chart tests, suppressing the `run-tests-with-ats` jobs and the `tests/ats/Pipfile`; the chart push then gates directly on `build-chart`.

### Fixed

- `gen precommit`: the generated `schemalint-normalize` and `schemalint-verify` hooks now set `pass_filenames: false`. Without it, pre-commit appended the matched schema file on top of the filename already in `args`, so `schemalint` received two positional arguments, errored with `accepts 1 arg(s)`, and silently did nothing — leaving the schema unnormalized and unverified.
Expand Down
3 changes: 2 additions & 1 deletion cmd/gen/circleci/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ block. Jobs are selected by:
- Dockerfile present -> architect/push-to-registries (buildx + split-china-push)
and architect/sync-china-registry
- app flavour -> architect/push-to-app-catalog (app-build-suite executor)
and architect/run-tests-with-ats
and architect/run-tests-with-ats (--skip-ats opts out
of the ATS chart tests)

The giantswarm/architect orb is pinned to a version baked into devctl (not a
flag): a major orb bump changes the template's required job/param shape, so it
Expand Down
3 changes: 3 additions & 0 deletions cmd/gen/circleci/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
flagImagePlatforms = "image-platforms"
flagImageDockerfile = "image-dockerfile"
flagResourceClass = "resource-class"
flagSkipATS = "skip-ats"
flagFlavour = "flavour"
flagLanguage = "language"
flagRepoName = "repo-name"
Expand All @@ -45,6 +46,7 @@ type flag struct {
ImagePlatforms string
ImageDockerfile string
ResourceClass string
SkipATS bool
Flavours gen.FlavourSlice
Language gen.Language
RepoName string
Expand All @@ -67,6 +69,7 @@ func (f *flag) Init(cmd *cobra.Command) {
cmd.Flags().StringVar(&f.ImagePlatforms, flagImagePlatforms, "", "Override the buildx platform list on the image jobs (push-to-registries `platforms` param). Empty lets the orb default apply (linux/amd64,linux/arm64 when no go-build .platforms file). Set it for single-architecture images (e.g. vllm -> linux/arm64, whose amd64 build has no prebuilt wheels).")
cmd.Flags().StringVar(&f.ImageDockerfile, flagImageDockerfile, "", "Override the Dockerfile path on the image jobs (push-to-registries `dockerfile` param). Set it for repos whose Dockerfile is not at the repo root (e.g. backstage -> packages/backend/Dockerfile); a non-empty value also turns the image pipeline on, since the root-Dockerfile derivation misses a nested Dockerfile. The append-only custom.yml merge cannot set this on a generated job. Empty keeps the orb default.")
cmd.Flags().StringVar(&f.ResourceClass, flagResourceClass, "", `Override the CircleCI resource_class on the cli-flavour go-build job. Empty defaults to "large". Raise it (e.g. "xlarge") for repos that need more RAM/CPU headroom for the cold cross-compile. Only applies to the cli flavour.`)
cmd.Flags().BoolVar(&f.SkipATS, flagSkipATS, false, `Opt the chart pipeline out of app-test-suite (ATS) chart tests. By default an "app" flavour repo runs architect/run-tests-with-ats between build-chart and the chart push, and generation emits the canonical tests/ats/Pipfile. When set, those test jobs and the Pipfile are not generated and the chart push gates directly on build-chart. Only applies to the app flavour.`)
cmd.Flags().VarP(gen.NewFlavourSliceFlagValue(&f.Flavours, gen.FlavourSlice{}), flagFlavour, "f", fmt.Sprintf(`List of project flavours. The "app" flavour selects the chart pipeline. Possible values: <%s>`, strings.Join(gen.AllFlavours(), "|")))
cmd.Flags().VarP(gen.NewLanguageFlagValue(&f.Language, gen.Language("")), flagLanguage, "l", fmt.Sprintf(`The programming language. "go" selects the go-build job. Possible values: <%s>`, strings.Join(gen.AllLanguages(), "|")))
cmd.Flags().StringVarP(&f.RepoName, flagRepoName, "r", "", "Repository name under the giantswarm organization (used for the binary, chart, and job names).")
Expand Down
1 change: 1 addition & 0 deletions cmd/gen/circleci/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func (r *runner) run(ctx context.Context, _ *cobra.Command, _ []string) error {
RepoName: r.flag.RepoName,
Language: r.flag.Language,
Flavours: r.flag.Flavours,
SkipATS: r.flag.SkipATS,
HasDockerfile: hasDockerfile,
AppCatalog: r.flag.AppCatalog,
AppCatalogTest: r.flag.AppCatalogTest,
Expand Down
11 changes: 9 additions & 2 deletions pkg/gen/input/circleci/circleci.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ type Config struct {
// Flavours are the devctl gen flavours. The "app" flavour selects the
// chart pipeline.
Flavours gen.FlavourSlice
// SkipATS opts the chart pipeline out of app-test-suite (ATS) chart tests.
// When set, the run-tests-with-ats jobs and the canonical tests/ats/Pipfile
// are not generated, and the chart push jobs gate directly on build-chart.
// Only applies to a chart/app repo (the "app" flavour).
SkipATS bool
// HasDockerfile selects the image pipeline. The runner derives this from
// the presence of a Dockerfile in the repo.
HasDockerfile bool
Expand Down Expand Up @@ -431,6 +436,7 @@ func New(config Config) (*CircleCI, error) {
Language: config.Language.String(),
HasDockerfile: hasDockerfile,
HasApp: hasApp,
SkipATS: config.SkipATS,
ChartName: chartName,
ForcePublic: config.ForcePublic,
AppCatalog: appCatalog,
Expand Down Expand Up @@ -488,9 +494,10 @@ func (c *CircleCI) Workflows() input.Input {
// call site (devctl gen circleci, the only generator invoked inside align's
// `if (ci && ci.generate)` guard). That makes "ATS Pipfile only when CI is
// generated, and only for chart/app repos" structurally guaranteed rather than
// dependent on a separate, differently-scoped invocation.
// dependent on a separate, differently-scoped invocation. A repo that opts out
// of ATS (SkipATS) gets no Pipfile either, matching the suppressed jobs.
func (c *CircleCI) ATSInputs() []input.Input {
if !c.params.HasApp {
if !c.params.HasApp || c.params.SkipATS {
return nil
}

Expand Down
39 changes: 39 additions & 0 deletions pkg/gen/input/circleci/circleci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1251,6 +1251,45 @@ func Test_ATSPipfileOmittedForNonApp(t *testing.T) {
}
}

// Test_SkipATSOmitsChartTests verifies the ATS opt-out: an app repo with
// SkipATS gets the chart pipeline but no run-tests-with-ats jobs, and the
// chart push jobs gate directly on build-chart instead of the test jobs. The
// canonical Pipfile is suppressed too.
func Test_SkipATSOmitsChartTests(t *testing.T) {
c := Config{
RepoName: repoMCPKubernetes,
Language: gen.LanguageGo,
Flavours: gen.FlavourSlice{gen.FlavourApp},
HasDockerfile: true,
BranchPublish: true,
SkipATS: true,
}

got := render(t, c)

// The chart pipeline itself stays.
for _, want := range []string{"name: build-chart", "name: push-chart", "name: push-chart-release"} {
if !contains(got, want) {
t.Errorf("SkipATS config missing %q:\n%s", want, got)
}
}
// The ATS test jobs are gone.
for _, unwanted := range []string{jobRunTests, "execute-chart-tests", "execute-chart-tests-release"} {
if contains(got, unwanted) {
t.Errorf("SkipATS config should not contain %q:\n%s", unwanted, got)
}
}
// The chart push jobs gate on build-chart now that the test jobs are gone.
if !contains(got, "requires:\n - build-chart") {
t.Errorf("SkipATS chart push should require build-chart directly:\n%s", got)
}

// No canonical ATS Pipfile is emitted.
if inputs := newCircleCI(t, c).ATSInputs(); len(inputs) != 0 {
t.Errorf("expected no ATS inputs with SkipATS, got %d: %+v", len(inputs), inputs)
}
}

// Test_NodeBuildOutputCache verifies the build-output cache (node_modules +
// Yarn install-state) is emitted for the Yarn package managers, keyed on the
// node image version, and is absent for npm (npm ci wipes node_modules) and
Expand Down
1 change: 1 addition & 0 deletions pkg/gen/input/circleci/internal/file/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func NewWorkflowsInput(p params.Params) input.Input {
"Language": p.Language,
"HasDockerfile": p.HasDockerfile,
"HasApp": p.HasApp,
"SkipATS": p.SkipATS,
"ChartName": p.ChartName,
"ForcePublic": p.ForcePublic,
"AppCatalog": p.AppCatalog,
Expand Down
10 changes: 10 additions & 0 deletions pkg/gen/input/circleci/internal/file/workflows.yml.template
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ workflows:
branches:
ignore:
- main
{{- if not .SkipATS }}

# Branch: run chart tests after build-chart. When branchPublish pushes a dev
# image, the test also waits on push-to-registries -- run-tests-with-ats
Expand Down Expand Up @@ -371,6 +372,7 @@ workflows:
only: /^v.*/
branches:
ignore: /.*/
{{- end }}
{{- if .BranchPublish }}

# Branch chart push (opt-in): publish the dev chart after tests + the amd64
Expand All @@ -387,7 +389,11 @@ workflows:
app_catalog_test: {{ .AppCatalogTest }}
chart: {{ .ChartName }}
requires:
{{- if .SkipATS }}
- build-chart
{{- else }}
- execute-chart-tests
{{- end }}
{{- if .HasDockerfile }}
- push-to-registries
{{- end }}
Expand All @@ -412,7 +418,11 @@ workflows:
app_catalog_test: {{ .AppCatalogTest }}
chart: {{ .ChartName }}
requires:
{{- if .SkipATS }}
- build-chart
{{- else }}
- execute-chart-tests-release
{{- end }}
{{- if .HasDockerfile }}
- push-to-registries-release
{{- end }}
Expand Down
6 changes: 6 additions & 0 deletions pkg/gen/input/circleci/internal/params/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ type Params struct {
// Helm chart). It selects the chart pipeline (push-to-app-catalog with the
// app-build-suite executor and run-tests-with-ats).
HasApp bool
// SkipATS opts the chart pipeline out of app-test-suite (ATS) chart tests.
// When true the run-tests-with-ats jobs (execute-chart-tests /
// execute-chart-tests-release) and the canonical tests/ats/Pipfile are not
// emitted, and the chart push jobs gate directly on build-chart instead.
// Only meaningful for a chart/app repo (HasApp); ignored otherwise.
SkipATS bool
// ChartName is the chart name used for the push-to-app-catalog `chart`
// param and the helm/<chart> directory. Defaults to RepoName. Set it for
// repos whose chart directory does not match the repo name (e.g.
Expand Down