--- kind: operations description: Setting the Action up in a plugin repository, by hand or with a coding agent: secrets, the workflow, permissions, report channels and the deploy service. --- # Installing the Action ## The workflow 1. Add the repository secrets the Action uses. The reusable workflow passes each to the Action under its name below, and only these names reach it: | Secret | Needed for | |---|---| | `DEEPSEEK_API_KEY_DSH_MIGRATE_BOT` | Every migration: the agent sessions | | `DSH_MIGRATE_REPORT_UPGRADE_SKILL_TOKEN`, `DSH_MIGRATE_REPORT_BOT_TOKEN`, `DSH_MIGRATE_REPORT_HARNESS_TOKEN` | A built-in [report channel](#report-channels) that is enabled | | `DSH_MIGRATE_DEPLOY_TOKEN` | A [deploy service](#the-deploy-service) | The `secrets.apiKeyEnv`, `deploy.tokenEnv` and `reports.channels..tokenEnv` keys name the variable the Action reads, and a [report channel](#report-channels) of your own names its token in the last; a name not in the table needs [a copy of the reusable workflow](#a-copy-of-the-reusable-workflow). 2. Copy [examples/workflow.yml](../../examples/workflow.yml) to `.github/workflows/dsh-migrate.yml`, set the cron, and pin the release as [releasing](release.md#what-a-consumer-pins) describes. The file chooses the triggers and calls the reusable workflow [`.github/workflows/migrate.yml`](../../.github/workflows/migrate.yml) of this repository, or [your copy of it](#a-copy-of-the-reusable-workflow), with `secrets: inherit`. 3. Optionally copy [examples/dsh-migrate.yml](../../examples/dsh-migrate.yml) to `.github/dsh-migrate.yml`. Every key is optional and listed in the [configuration reference](../reference/configuration.md); an unknown or renamed key fails the run with a message that names the replacement. 4. In Settings → Actions → General → Workflow permissions, enable **Allow GitHub Actions to create and approve pull requests**. Without it the workflow token pushes the proposal branch and opens the issue, and then gets HTTP 403 when it opens the pull request. The reusable workflow holds the concurrency group that keeps one writer of the state branch at a time, and runs the job each event needs: `migrate` on the schedule and on manual dispatch, `pull-request-closed` when the proposal's pull request closes, and `comment` when a commenter the Action admits ([comment commands](#comment-commands)) writes `/dsh-migrate`. No other pull request or comment starts a job, because GitHub cancels a job waiting in a concurrency group when another is queued behind it; and each `migrate` run first asks GitHub whether the open proposal's pull request was closed, so a close whose job was cancelled anyway is still delivered. The caller grants `contents: write` (the proposal branch and the state branch), `issues: write` and `pull-requests: write`. The reusable workflow takes three inputs, `target` and `force` for a manual run and `config` for a configuration file at another path, and returns the Action's `status`, `target_tag`, `verified_tag`, `pull_request_url`, `log_stream_url` and `command_reply` as its outputs. The Action runs the image `ghcr.io/royenheart/dsh-migrate-bot` of its release. The image is built and self-tested once per release, so every consumer run uses the same agent runtime and the same system packages. The first scheduled run migrates to the target release. When a later run skips a release, and what `force` changes, is in [starting a migration](../design/workflow.md#6-starting-a-migration). ### A copy of the reusable workflow A variable the table above does not name, a renamed one or the token of a report channel of your own, reaches the Action only through a copy of the reusable workflow in the plugin repository: 1. Copy `.github/workflows/migrate.yml` of the release you would pin to `.github/workflows/dsh-migrate-jobs.yml`, and set each such variable in its top-level `env` from its secret. For the major tag, that is the release it points to now: the `vX.Y.Z` tag that `git ls-remote --tags https://github.com/royenheart/dsh-migrate-bot` lists with the major tag's commit, never a release candidate. 2. In the workflow of step 2 above, call `./.github/workflows/dsh-migrate-jobs.yml` instead, still with `secrets: inherit`. The copy runs the release its `uses:` lines name, and its jobs are that release's, so leave them as copied. 3. A major tag moving on no longer upgrades the Action: an upgrade is a new copy of the new release's `migrate.yml`, with the variables set again. The Action step's inputs are in [`action.yml`](../../action.yml). ## Setting it up with an agent A coding agent working in the plugin repository can set the Action up by following this section; the maintainer only answers its questions and adds the secrets. The agent reads the documents of the release it pins, at `https://github.com/royenheart/dsh-migrate-bot/blob//`, because keys and defaults change between releases. The rest of this page and the [configuration reference](../reference/configuration.md) hold the facts it applies. ### Looking before asking The agent first finds out what it can without asking, and reports it: | Fact | How | |---|---| | The repository holds a plugin | A tracked `package.json` that declares `dsh.bundle`, at the root or below it. Without one the Action has nothing to migrate: stop and say so | | The plugin has a browser half | Its `package.json` declares `dsh.client`; only then does the end-to-end check matter | | The plugin has its own checks | `package.json` scripts `build`, `typecheck` and `test`; without any, the mechanical check is skipped unless `tests.commands` names commands | | The v0 Action is installed | A workflow under `.github/workflows/` that uses `royenheart/dsh-migrate-bot@v0`, a `.github/dsh-migrate.yml` with v0 keys, a remote branch `dsh-migrate/e2e`, or open pull requests from `dsh-migrate/-