Start with init
init writes a first version of the two files Sluiceway needs, from what it finds in your repo: the workflow .github/workflows/deploy-dashboard.yml and the settings file sluiceway.yaml.
It writes them into your clone and commits nothing. You read them, change what it could not know, and commit them yourself.
Run it
In the top directory of your clone, with Node 22 or newer:
npx sluiceway initOr bunx sluiceway init with Bun. It runs init where you stand. To run it on another clone, give its directory: npx sluiceway init ../infra. The npm package sluiceway is released with the action, from the same tag and with the same version. To run the init of a release you reviewed, name its version: npx sluiceway@<version> init.
Like the check, init reads the files of your clone and nothing else: no credentials, no token, no infrastructure tool, no GitHub API, no network. It reads untracked files too, so run it on a clean clone.
When the files are written, npx sluiceway check says the same thing the check says in a pull request: which stacks it found, and whether sluiceway.yaml and the workflow are right. It needs no credentials either.
Apart from init and the check, the package has commands that talk to the Sluiceway app with a token you make there, and never to GitHub: the command line explains them, npm i -g sluiceway and the binaries each release carries for a machine with no Node. npx sluiceway scan, resolve, apply and settle stop with a sentence: they need the run’s identity and the workflow token, so they run only in the workflow. npx sluiceway --help lists the commands.
What it looks at
- The stacks. Pulumi projects, found the way a scan finds them. OpenTofu root modules: the ones discovery finds are stacks already, and of the rest, directories of
.tfor.tofufiles that no other directory calls as a module and that are not under amodulesdirectory. Helm charts: everyChart.yamlthat is not a library chart or a subchart. Kubernetes manifests stacks only when asluiceway.yamlthat is there declares them: a directory of YAML says nothing about its cluster (configuration). - The programs’ language and lockfile. For Pulumi programs in JavaScript or TypeScript, the nearest
package-lock.json,pnpm-lock.yaml,yarn.lockorbun.lock, and.nvmrcor.node-version. Programs in another language get their packages withpulumi install. - An env file of secret references. A file named
.env,.env.<something>or<something>.envwith at least one 1Password reference (op://), loaded the way the secret manager example does it. A file of plain values is left alone: it is most often a local development file, andinitcannot tell. To load one in the workflow, name it with theenv-fileinput. - The workflows that are there. A workflow that already runs Sluiceway’s scan, resolve, apply or settle, a step with no mode among them, or a file at
.github/workflows/deploy-dashboard.yml, stopsinitbefore it writes anything. A check workflow does not, with or without its mode.npx sluiceway init --forcewrites.github/workflows/deploy-dashboard.ymlagain, and still stops at any other workflow that runs Sluiceway. The read-only trial writes that file, so runinitbefore the trial, or with--forceafter it.initkeeps asluiceway.yamlthat is there, so take the trial’sdashboard.readOnly: trueout of it yourself. - A
sluiceway.yamlthat is there. It is loaded as a scan loads it, kept as it is, and the workflow is built from it. WithmergeAndDeploy.authors, that is the workflow of merge and deploy.
What it writes
.github/workflows/deploy-dashboard.yml, the whole workflow: one job with one Sluiceway step and noif:, and before that step the steps that install what your stacks need: the language and your packages, Pulumi with its plugin cache, OpenTofu, Helm with the diff plugin, kubectl. The versions and pins are the ones of the example workflows and of credentials.sluiceway.yaml, only when there is none. It declares every OpenTofu root module that discovery leaves out and every Helm chart it found, because files alone cannot name those stacks (configuration). It lists underscan.unrelatedthe globs of the check’s fixed list that cover a file of your repo, and names in a comment the directories whose files no stack claims, with how to give them to a stack asinputs..github/scripts/export-env.sh, only when it loads an env file of secret references and that file is not there yet. It is the script credentials explains, which only a file of references needs: a resolved file, or one of plain values, is loaded by theenv-fileinput with no script.
It never overwrites a file, except .github/workflows/deploy-dashboard.yml with --force.
What it leaves to you
init ends with a list of what it could not know. What is on it depends on your repo:
- Credentials. Apart from an env file of references that it found,
initwrites no step that loads a credential. The workflow says in a comment where yours go. With an env file, it names the secret to create,OP_SERVICE_ACCOUNT_TOKEN. The one job previews and deploys, so it loads the env file that deploys, and names any other it did not use. - The runner. The job runs on
ubuntu-latest, withtimeout-minutes: 60. - The default branch, when your clone does not record it.
- Helm releases. Each chart becomes a release named after it, in a namespace of the same name, with no values files. Set all three to where the release runs. The namespace must exist, so a wrong guess fails its preview and deploys nothing.
- OpenTofu workspaces. A root module with more than one var file becomes one stack per var file, each in a workspace named after the file, so that no two stacks share a state. Rename the workspaces where yours differ.
init writes no tick rule, so once the workflow is merged anyone with write access can tick a box, and a tick deploys unless a GitHub Environment with required reviewers stands in between (a tick asks, an environment decides). Add tickers to sluiceway.yaml before you merge, or leave it at its default and make the people who may deploy the reviewers of that environment.
Then run npx sluiceway check, open a pull request with the files, and merge them when the check finds nothing missing. init does not write the check workflow, so add it to the same pull request if you want the check to run there too.