~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

A shared step can be passed a secret under the name it asks for

Merged
Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:run/secret-names

What changes

A uses step's secrets can be a map. Its keys are the names the step file asks for, and its values are the workflow's own secrets: secrets: {SSH_KEY: DEPLOY_SSH_KEY}. The list form stays, and means the same name on both sides. Step::secrets is now Option<BTreeMap<String, String>> (the step file's name to the name it is passed from). A small serde visitor in workflow.rs (passed) reads either form, and refuses a name passed twice (passes the secret <name> twice). The workflow still checks each value against its secrets, and expand checks each key against the step file's secrets.

Who sees what. Step::sees(name) becomes Step::seen(granted). It takes the run's granted secrets, by the workflow's names, and returns those the step sees, by the names it sees them by. A step a shared step was put in place of sees the value under the key's name and nothing under the workflow's. Any other step sees everything granted, as before. run_steps gives a step seen's pairs as its own variables, so under docker the renamed name is what goes into -e NAME and the client's environment. The value never goes into the arguments.

Nested shared steps map from their parent's names. When expand puts a step file's own uses step in place, it composes that step's map with the one passed in. So by the time the nested step is expanded, its values are already the names the run grants by.

Grants and not_granted are unchanged. The secrets file, sealed secrets and the ==> <name> is not granted to … line all go by the workflow's secrets. So a missing grant is still named as the workflow names it, whatever the step calls it.

Docs. docs/design/reusable-workflows.md ("What a shared step can see", and nested steps) and docs/reference/workflows.md (the step secrets key, an example, what a shared step sees, and the parse errors).

Why

A secret could only be passed under the step file's own name. knotless's deploy.yml holds its key as DEPLOY_SSH_KEY, and chadtmiller.com/steps/ssh-key asks for SSH_KEY, so deploy could not use the step without renaming the repository's secret. GitHub does the same thing through with: {token: ${{ secrets.X }}}. A map on secrets keeps secrets apart from with, whose values reach steps as plain INPUT_ variables and are not redacted.

How it was checked

  • workflow::tests::a_step_runs_or_uses: both forms parse, a value the workflow does not name is refused, a name passed twice is refused, a scalar is refused, and seen with and without a map.
  • uses::tests: a step file's map form parses and is checked against its own secrets. expand with a renamed secret is seen under the step file's name alone, and a nested step's map composes onto the run's names.
  • executor::tests::executors: under docker, a renamed secret goes to docker exec -e SSH_KEY with SSH_KEY in the client's environment and no DEPLOY_KEY.
  • run.rs a_workflow_uses_a_shared_step: a run passing {KEY: OTHER} sees OTHER's value as KEY (by its length, as the log hides the value) and no OTHER or TOKEN. One through a step file passing {KEY: INNER}, given {INNER: TOKEN}, sees TOKEN's value as KEY. One passing an ungranted MISSING logs MISSING is not granted to, and the step sees no KEY.

Built and tested on the runner.

Shortcomings

  • deploy.yml is not moved onto ssh-key here. That is a later pull, once this is deployed, since the runner has to read the map form first.
  • A secrets: ~ on a uses step no longer parses as none. Leave the key out instead.

🤖 Generated with Claude Code

Approved

This lets a uses step's secrets be a map from the step file's name to the workflow's name. Step::seen replaces sees, and the run, docker and nested-step paths now go by the renamed names.

I read the diff and the surrounding expand code and found nothing that must change.

  • Renaming: a renamed secret reaches the step under the step file's name only. Run steps get passed (file name → run name), and seen returns the file name with the granted value.
  • Nested steps: the map composes through the parent's names, and parse_step and expand each check the right side of the map.
  • Grants: grants and not_granted still go by the workflow's names.
  • Callers: the one other caller of the old sees, in lib.rs, is updated, and the remaining uses are tests.
  • Tests and docs: the tests cover both forms, a duplicate name, a scalar, a nested map and the docker environment. The docs and changeset are updated.

I did not read the check results, and I did not build or run the tests.

The secrets: ~ behaviour change is already listed under Shortcomings.

Merged as 74a9a2d