Skip to content

chore(gha): select the CLI by binary name instead of concatenating a version - #438

Merged
jsteinich merged 2 commits into
open-constructs:mainfrom
jsteinich:chore/express-terraform-binary-in-workflows
Sep 17, 2026
Merged

jsteinich merged 2 commits into
open-constructs:mainfrom
jsteinich:chore/express-terraform-binary-in-workflows

Conversation

@jsteinich

Copy link
Copy Markdown
Contributor

Related issue

Prerequisite for adding an OpenTofu axis to any workflow other than integration.yml. Follows #405, which introduced the binary matrix field.

Description

integration.yml sets TERRAFORM_BINARY_NAME from a binary matrix field. Every other workflow still builds the name by concatenating:

TERRAFORM_BINARY_NAME: "terraform${{ matrix.terraform }}"

That makes a non-Terraform runtime impossible to express — there is no version string that turns "terraform${...}" into tofu1.12.6. This removes the concatenation everywhere so the runtime is nameable.

No behaviour change. Every binary resolves to exactly what it did before; this is plumbing only.

workflow change
unit.yml takes terraform_binary in place of terraform_version — the version was never used as a version there, only to build the binary name and key the concurrency group and schema cache
provider-integration.yml keeps terraform_version (also exported as TERRAFORM_VERSION, and drives setup-terraform on the windows path) and gains terraform_binary beside it
pr-unit.yml matrix carries the binary
release.yml both unit.yml fan-outs pass a binary
examples.yml takes it from the matrix
tools/build-example-matrix.mjs emits binary alongside terraform

Provider and schema caches are now keyed by binary rather than version, matching what integration.yml already does — Terraform and OpenTofu resolve providers from different registries into the same TF_PLUGIN_CACHE_DIR, so they must not share a cache entry.

Testing

build-example-matrix.mjs output:

terraform: ["1.16.1"]  binary: ["terraform1.16.1"]
targets: 58  include: 5
sample include: {"target":"@examples/csharp-aws","terraform":"1.16.1",
                 "binary":"terraform1.16.1","hclOutput":true}

prettier --check clean across the workflows and the matrix builder. No "terraform${{ … }}" concatenation remains in .github/workflows/.

The real verification is that this PR's own CI run is unchanged from main — same jobs, same binaries.

Follow-up

This unblocks a scoped OpenTofu entry on the unit matrix, which is where #301 actually lived: the matcher fixture is a unit test, and nothing in CI exercises it under tofu today, so that fix can silently regress.

🤖 Generated with Claude Code

…version

`integration.yml` already sets TERRAFORM_BINARY_NAME from a `binary` matrix
field (open-constructs#405). Every other workflow still built the name by concatenating
"terraform" with a version, which makes a non-Terraform runtime impossible to
express: there is no version string that turns "terraform${...}" into
"tofu1.12.6".

No behaviour change here - every binary resolves to exactly what it did
before. This only makes the runtime nameable, so an OpenTofu entry can be
added to a matrix without touching the plumbing again.

- unit.yml takes `terraform_binary` in place of `terraform_version`. The
  version was never used as a version there, only to build the binary name
  and to key the concurrency group and schema cache.
- provider-integration.yml keeps `terraform_version` - it is also exported as
  TERRAFORM_VERSION and drives setup-terraform on the windows path - and
  gains `terraform_binary` beside it.
- pr-unit.yml and release.yml's two unit fan-outs carry the binary in the
  matrix.
- examples.yml takes it from the matrix, which build-example-matrix.mjs now
  emits.

Terraform and OpenTofu resolve providers from different registries into the
same TF_PLUGIN_CACHE_DIR, so the provider and schema caches are keyed by
binary rather than version, matching what integration.yml already does.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jsteinich
jsteinich marked this pull request as ready for review September 16, 2026 03:12
@jsteinich
jsteinich requested a review from a team as a code owner September 16, 2026 03:12
Review catch on open-constructs#439. I expressed the release matrices as two `include`
entries carrying only `terraform_binary`:

    package: [ ...8 packages... ]
    include:
      - terraform_binary: terraform1.16.1
      - terraform_binary: terraform1.5.7

`include` objects are merged into every existing combination unless they
would overwrite an *original* matrix value. `terraform_binary` is not an
original key here, so both entries applied to all eight package
combinations and the second overwrote the first: eight jobs, all on
terraform1.5.7, with 1.16.1 silently gone from both release channels.

Making it a real axis restores the 8 x 2 cross-product the
terraform_version axis produced before.

Nothing would have caught this: release.yml does not run on pull requests,
so the job count only changes on main and release.

pr-unit.yml's matrix is unaffected - it has no original axis, so each
`include` entry creates its own combination, which is what pairing a version
with a binary needs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sakul-learning

This comment has been minimized.

@sakul-learning

This comment has been minimized.

@jsteinich
jsteinich merged commit 914da56 into open-constructs:main Sep 17, 2026
260 checks passed
@jsteinich
jsteinich deleted the chore/express-terraform-binary-in-workflows branch September 17, 2026 20:11
jsteinich added a commit that referenced this pull request Sep 17, 2026
### Related issue

Closes the CI gap left by #429 / #301. **Stacked on #438** — merge that
first; this branch contains its commit.

### Description

#301 was a unit-level failure: the matcher fixture pinned a Docker
provider version OpenTofu rejects as unsigned. #429 fixed it — but
nothing in CI runs those tests under `tofu`, so it can regress silently
and we would not know.

One matrix entry on `affected_terraform`:

```yaml
- terraform_version: "1.12.6"
  terraform_binary: tofu1.12.6
```

**That is already scoped, which is why it costs one job rather than a
second copy of the unit suite.** The job runs:

```
nx affected -t test --exclude='*,!tag:unit-test:terraform'
```

so it only touches the four projects tagged terraform-dependent —
`cdktn`, `@cdktn/cli-core`, `@cdktn/provider-generator`,
`@cdktn/provider-schema`. Those are exactly the packages whose tests
shell out to a CLI; `cdktn-cli`, `hcl2cdk` and `hcl2json` invoke none
and are already excluded.

The provider schema cache moves from being keyed by version to by binary
— tofu and terraform fetch schemas from different registries and must
not share an entry.

### Cost

One extra job on `depot-ubuntu-24.04-16`, only when a terraform-tagged
project is affected. For comparison, a full OpenTofu leg on the
integration matrix would be +77 jobs and roughly +115 runner-minutes.

### Deliberately not extended to `release.yml`

Its two `unit.yml` fan-outs are a package × version cross-product with
**no tag filter**, so an OpenTofu entry there would also run `hcl2cdk`,
`hcl2json` and `cdktn-cli` under tofu — none of which touch a CLI.
Scoping that properly is a larger change, and worth doing only once this
entry has proven itself on PRs.

### Testing

CI on this PR is the verification, and it is the interesting part: this
is the first time the `cdktn` unit tests — including the #429 matcher
fixture — run against OpenTofu in CI. If #429 were wrong, this job is
what would say so.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

I'm going to lock this pull request because it has been closed for 30 days. This helps our maintainers find and focus on the active issues. If you've found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Oct 18, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants