chadtmiller.com/knotless
git that lives in your Atmosphere account
1
10
A shared step can be passed a secret under the name it asks for
Merged 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), andseenreturns the file name with the granted value. - Nested steps: the map composes through the parent's names, and
parse_stepandexpandeach check the right side of the map. - Grants: grants and
not_grantedstill go by the workflow's names. - Callers: the one other caller of the old
sees, inlib.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.
All checks have passed
9 passed, 1 skipped
Merged as 74a9a2d
What changes
A
usesstep'ssecretscan 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::secretsis nowOption<BTreeMap<String, String>>(the step file's name to the name it is passed from). A small serde visitor inworkflow.rs(passed) reads either form, and refuses a name passed twice (passes the secret <name> twice). The workflow still checks each value against itssecrets, andexpandchecks each key against the step file'ssecrets.Who sees what.
Step::sees(name)becomesStep::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_stepsgives a stepseen's pairs as its own variables, so under docker the renamed name is what goes into-e NAMEand the client's environment. The value never goes into the arguments.Nested shared steps map from their parent's names. When
expandputs a step file's ownusesstep 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_grantedare unchanged. The secrets file, sealed secrets and the==> <name> is not granted to …line all go by the workflow'ssecrets. 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) anddocs/reference/workflows.md(the stepsecretskey, 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.ymlholds its key asDEPLOY_SSH_KEY, andchadtmiller.com/steps/ssh-keyasks forSSH_KEY, so deploy could not use the step without renaming the repository's secret. GitHub does the same thing throughwith: {token: ${{ secrets.X }}}. A map onsecretskeeps secrets apart fromwith, whose values reach steps as plainINPUT_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, andseenwith and without a map.uses::tests: a step file's map form parses and is checked against its ownsecrets.expandwith 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 todocker exec -e SSH_KEYwithSSH_KEYin the client's environment and noDEPLOY_KEY.run.rsa_workflow_uses_a_shared_step: a run passing{KEY: OTHER}sees OTHER's value asKEY(by its length, as the log hides the value) and noOTHERorTOKEN. One through a step file passing{KEY: INNER}, given{INNER: TOKEN}, sees TOKEN's value asKEY. One passing an ungrantedMISSINGlogsMISSING is not granted to, and the step sees noKEY.Built and tested on the runner.
Shortcomings
deploy.ymlis not moved ontossh-keyhere. That is a later pull, once this is deployed, since the runner has to read the map form first.secrets: ~on ausesstep no longer parses as none. Leave the key out instead.🤖 Generated with Claude Code