Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

Docs: final pass for the end state after the GitHub cut-off (#183)

* Docs: final pass for the end state after the GitHub cut-off
test-bot authored 1 parent b9e1252commit cbfc9fad8ff7f3a84a8fc75299a8b77731c18651Browse files
12 files changed+50−17
Files (12)
modifiedREADME.md+24−3View file
@@ -78,6 +78,12 @@
7878 Edit), and zone permission Workers Routes Edit on `diffinery.com`.
7979 - `CLOUDFLARE_ACCOUNT_ID`
8080
81+Agents land `main` through auto-merge, so Deploy (and the live test after it)
82+runs as agent code and gets repository secrets only because the repository has
83+*Give runs of agent code the repository's and organization's secrets* turned on
84+(Settings → Actions). A copy where agents land changes needs the same, or the
85+secrets in a `production` environment limited to protected branches.
86+
8187 On each deploy, `scripts/bootstrap.sh` creates anything that is missing: the D1
8288 database, R2 bucket, queues, the Turnstile widget for anonymous security reports
8389 (`scripts/turnstile.sh`; needs Account → Turnstile → Edit, else it warns) and one
@@ -251,7 +257,11 @@
251257 and without a required check a 422; a pull request that changes a workflow
252258 file needs a person. A push by anyone else turns auto-merge off, the merge
253259 commit carries the `diffinery-agent` header, and the workflows it triggers run
254-under the agent rules. Workflow tokens are held to the same rule. Enabling,
260+under the agent rules. That includes secrets: once an agent has landed on a
261+branch, runs there get no repository or organization secrets unless an admin
262+turns on *Give runs of agent code the repository's and organization's secrets*
263+(`agent_runs_use_secrets`), and only get environment secrets from environments
264+limited to protected branches. A deploy after an agent's merge needs one of the two. Workflow tokens are held to the same rule. Enabling,
255265 disabling, the merge and changes to the setting are audited.
256266
257267 ## Workflows
@@ -391,7 +401,8 @@
391401 `docker` and `gh` installed. `ACTIONS_STEP_DEBUG` and `ACTIONS_RUNNER_DEBUG`
392402 (as secrets or variables) turn on debug logging.
393403
394-**Not supported yet:** Windows and macOS hosted runners, the GraphQL API
404+**Not available:** Windows and macOS hosted runners (Cloudflare Containers run
405+Linux only; those jobs run on self-hosted runners). **Not supported yet:** the GraphQL API
395406 (`github.graphql` in github-script), and `deepen-not` / partial clone filters
396407 on the server (checkout's `filter` falls back to a full fetch). One cache or
397408 artifact upload request goes through the Worker, so it is limited to the
@@ -616,7 +627,10 @@
616627
617628 **Retrying.** Only whoever started an import may retry it, and a retry
618629 needs the GitHub token again (it is never stored past the run). While an import
619-is in progress the target repository is **locked** against other writes, and a
630+is in progress the target repository is **locked** against other writes (pushes,
631+issues, pull requests, labels, webhooks, branch protection, renames and transfers).
632+Actions secrets and variables, environments and collaborators can still be changed,
633+so imported secrets' values can be entered while the history arrives. A
620634 retry refuses to touch a repository that already holds content the import did not
621635 write — it will not adopt or overwrite an existing repository. An agent may not
622636 retry once the repository has been created; a person who administers the target
@@ -651,5 +665,12 @@
651665 data, statuses as required checks, releases with asset uploads and
652666 downloads, issues, reactions, pagination, search and deployments.
653667
668+On Diffinery, CI runs as three jobs (*Typecheck and bundle*, *Unit tests (1/2)*
669+and *(2/2)*) and the end-to-end suite as six shards of about the same length
670+(*git, PRs, Actions*; *real histories*; *large pushes*; *agent reviews, tasks,
671+Today*; *security*; *passkeys, registry, email*). All nine are required checks
672+on `main`, entered one name per line in its branch protection rule, so a pull
673+request lands only when every one of them is green.
674+
654675 Team preferences for product and design decisions are in
655676 [docs/PREFERENCES.md](docs/PREFERENCES.md).
modifiedapps/diffinery/docs/accounts/organizations.md+1−0View file
@@ -368,6 +368,7 @@
368368 - Its members, pending invitations, organization secrets and organization variables are removed.
369369 - Its agents are disabled, and their tokens revoked.
370370 - Its login is freed: anyone can create a user or organization with that name afterwards. Older logins from earlier renames stop redirecting.
371+- Repositories transferred out of it earlier keep their redirects: their old URLs under its name still lead to them, until a repository is created at that owner and name (see [Old URLs after a transfer or rename](/docs/repositories/overview#old-urls-after-a-transfer-or-rename)).
371372 - Its page and API answer `404`.
372373 - The audit log keeps the entries that name it, and records the deletion as `org.delete`. Its import history and agents still refer to it.
373374
modifiedapps/diffinery/docs/actions/compatibility.md+2−2View file
@@ -25,7 +25,7 @@
2525 | Environments | Supported: branch policies, required reviewers (people), wait timers, environment secrets and variables, deployments. | [Secrets, variables and environments](#secrets-variables-and-environments) |
2626 | `GITHUB_TOKEN` | Follows `permissions:` per endpoint, as on GitHub; read-only by default in new repositories | [GITHUB_TOKEN and permissions](#github_token-and-permissions) |
2727 | OIDC | Supported, with Diffinery as the issuer | [OIDC](/docs/actions/oidc) |
28-| Windows and macOS hosted runners | Not supported yet | [Runners](#runners) |
28+| Windows and macOS hosted runners | Not available (Cloudflare Containers run Linux only); use self-hosted runners | [Runners](#runners) |
2929
3030 ## Workflow files
3131
@@ -81,7 +81,7 @@
8181 | --- | --- | --- |
8282 | `ubuntu-latest`, `ubuntu-24.04`, `ubuntu-22.04` | Hosted Ubuntu VM | Hosted Ubuntu 24.04 container, x64. All three labels get the same image. |
8383 | `ubuntu-24.04-arm` and other ARM labels | Hosted ARM runner | No hosted ARM runners. An `ubuntu-*` ARM label runs on the same x64 image as `ubuntu-latest`. For ARM, use `[self-hosted, ...]` labels on an ARM machine. |
84-| `windows-*`, `macos-*` | Hosted Windows or macOS VM | Not supported yet. The job fails with `No Diffinery runner matches runs-on: <labels>. Linux (ubuntu-*) runners are hosted; anything else needs runs-on: [self-hosted, ...] and a registered runner.` |
84+| `windows-*`, `macos-*` | Hosted Windows or macOS VM | Not available: Cloudflare Containers run Linux only. The job fails with `No Diffinery runner matches runs-on: <labels>. Linux (ubuntu-*) runners are hosted; anything else needs runs-on: [self-hosted, ...] and a registered runner.` |
8585 | Larger runners and runner groups | Supported | Not available. `group` is ignored. |
8686 | `[self-hosted, ...]` | Self-hosted runner | Self-hosted runner started with `diffinery runner`, matched on every label. |
8787
modifiedapps/diffinery/docs/actions/environments.md+1−1View file
@@ -840,7 +840,7 @@
840840 - Tags that an agent created or moved never match an environment's tag patterns.
841841 - Agents with write access can create deployments and deployment statuses with the API (with a `write` token), and can read environments and environment variables.
842842
843-Together with branch protection (agents can't push to protected branches unless a rule allows it, and pull requests opened by agents need a human approval), this means an agent can't get production credentials into code that no person reviewed. See [Agents](/docs/agents/overview).
843+Together with branch protection (agents can't push to protected branches unless a rule allows it, and pull requests opened by agents need a human approval), this means an agent can't get production credentials into code that no person reviewed. The exception is a branch whose rule has **Let agents' auto-merges land without an approving review** on (see [Waiving approvals for agents](/docs/repositories/branch-protection#waiving-approvals-for-agents)): there an agent's pull request lands on green required checks alone, and the runs that follow on that branch receive the secrets of environments limited to protected branches. Turn that waiver on only where the required checks are the review you rely on. See [Agents](/docs/agents/overview).
844844
845845 ## Audit log
846846
modifiedapps/diffinery/docs/actions/secrets-and-variables.md+6−0View file
@@ -309,6 +309,11 @@
309309
310310 Runs of code an agent wrote are the other exception. A run whose trigger was an agent, whose branch an agent pushed last, or whose pull request an agent opened or pushed to gets no repository or organization secrets, only its job token. An agent with write access could otherwise push a workflow that sends them anywhere. A repository admin who is a person can allow it under **Settings → Actions** (**Give runs of agent code the repository's and organization's secrets**), or with `PUT /repos/{owner}/{repo}/actions/permissions/workflow` and `"agent_runs_use_secrets": true`. The change is audited. Environment secrets follow the environment's own rules.
311311
312+This includes the default branch once agents land changes on it. When an agent's pull request lands through [auto-merge](/docs/collaboration/pull-requests#auto-merge), the merge is the agent's push, so the branch was last pushed by an agent: every run on it from then on is agent code until a person pushes or merges there. That covers `push` runs and the `workflow_run` runs that follow them, such as a Deploy workflow that runs after CI. Such a run gets empty strings for repository and organization secrets, and the job log doesn't say they were withheld, so a deploy typically fails on its first missing value (`CLOUDFLARE_ACCOUNT_ID is required`, say). If agents land on your default branch, choose one of these:
313+
314+- **Keep deploy credentials in an environment** limited to protected branches, add `environment: <name>` to the deploying job, and protect the branch. Runs of agent code receive that environment's secrets on protected branches only, and never on pull request refs, so no other agent run sees them. This is the tighter option. See [Environments](/docs/actions/environments#who-receives-environment-secrets).
315+- **Turn on Give runs of agent code the repository's and organization's secrets.** Every run of agent code then gets them, branches and pull requests included, so treat write access for an agent as access to those secrets.
316+
312317 In practice: **anyone who can push a branch can run a workflow that uses the repository's secrets**, and so can agents with write access where an admin allows it. Give write access only to people and agents you trust with the repository secrets, and keep production credentials in an [environment](/docs/actions/environments) set to protected branches only (see [Branch protection](/docs/repositories/branch-protection)) rather than in repository secrets. Pull request runs and branches that aren't protected never receive them.
313318
314319 ## Masking in logs
@@ -448,6 +453,7 @@
448453 | `422 value is required (send it over HTTPS; it is encrypted at rest)` | The JSON body has no string `value`. |
449454 | ``422 encrypted_value (sealed box) is not supported yet: send the secret as `value` over HTTPS; it is encrypted at rest`` | The client encrypted the value with a public key, as GitHub requires. Send the plain value as `value`. |
450455 | `secret value is empty` | The CLI got an empty value from `--body` or stdin. |
456+| A secret is empty in a workflow run, or a deploy fails on a missing value such as `CLOUDFLARE_ACCOUNT_ID is required`, though the secret is set | The run is agent code: an agent triggered it, pushed its branch last (an agent's auto-merge counts), or opened or pushed its pull request. It gets no repository or organization secrets. Move the secrets into an environment limited to protected branches, or have an admin turn on **Give runs of agent code the repository's and organization's secrets**. See [Which runs receive secrets](#which-runs-receive-secrets). |
451457 | `403 agents cannot manage secrets` | Use a person's token. |
452458 | `403 agents cannot manage variables` | Agents can't create, change or delete variables. Use a person's token. |
453459 | `403 admin access required` | The token's owner isn't a repository admin, or the token lacks the `admin` scope. |
modifiedapps/diffinery/docs/actions/workflow-permissions.md+2−2View file
@@ -308,14 +308,14 @@
308308 A run is treated as agent code when:
309309
310310 - an agent triggered it,
311-- an agent last pushed the branch it runs on, or
311+- an agent last pushed the branch it runs on (a merge that Diffinery lands for an agent through auto-merge counts as the agent's push), or
312312 - for pull request and merge queue events, an agent opened the pull request or last pushed its head branch.
313313
314314 A re-run of such a run keeps this, whoever starts the re-run, and so does a `workflow_run` run that follows such a run, since it acts on what that run produced (its artifacts and outputs). The jobs of these runs act as an agent, so the [agent guardrails](/docs/agents/overview) hold for code an agent wrote, even when a person triggered the run:
315315
316316 - Pushes to the default branch or a protected branch are refused with `agents may not push to protected or default branches; open a pull request`, unless the branch's protection rule has **Allow agents to push directly** on.
317317 - Merges into those branches are blocked with `agents may not merge into this branch; a human must merge`, unless the rule has **Allow agents to merge pull requests** on. The token can still turn on [auto-merge](/docs/collaboration/pull-requests#auto-merge) where the rule has **Allow agents to land pull requests through auto-merge** and a required check; that rule holds for every job token on those branches, agent code or not.
318-- A pull request the job opens counts as agent-authored, so it needs at least one approval from a person.
318+- A pull request the job opens counts as agent-authored, so it needs at least one approval from a person, unless the base branch's rule [waives approvals for agents' auto-merges](/docs/repositories/branch-protection#waiving-approvals-for-agents).
319319 - A deployment the job records counts as the agent's, so [environment secret rules for agents](/docs/actions/environments#who-receives-environment-secrets) apply.
320320 - The jobs get no repository or organization secrets, only the job token, unless a repository admin who is a person turns on `agent_runs_use_secrets` (see [Which runs receive secrets](/docs/actions/secrets-and-variables#which-runs-receive-secrets)).
321321
modifiedapps/diffinery/docs/agents/mcp.md+1−1View file
@@ -290,7 +290,7 @@
290290 -d '{"jsonrpc":"2.0","id":7,"method":"tools/call","params":{"name":"start_github_import","arguments":{"source":"acme/website","owner":"acme","github_token":"ghp_..."}}}'
291291 ```
292292
293-The result is the import object (`id`, `html_url`, `status`, `source`, `target`, `steps`, `git`, `summary`, `warnings`, `error`). Call `get_import` with the `id` every minute or so until `status` is `succeeded`, `failed` or `cancelled`. While the import runs, every other write to the new repository is refused: pushes with `repository is locked by an import in progress`, and tools such as `create_issue` with `repository is locked by an import in progress; try again when it finishes, or cancel the import`.
293+The result is the import object (`id`, `html_url`, `status`, `source`, `target`, `steps`, `git`, `summary`, `warnings`, `error`). Call `get_import` with the `id` every minute or so until `status` is `succeeded`, `failed` or `cancelled`. While the import runs, every other write to the new repository is refused: pushes with `repository is locked by an import in progress`, and tools such as `create_issue` with `repository is locked by an import in progress; try again when it finishes, or cancel the import`. A person can still set the repository's Actions secrets and variables, environments and collaborators while it runs.
294294
295295 Who can start one:
296296
modifiedapps/diffinery/docs/agents/overview.md+1−1View file
@@ -131,7 +131,7 @@
131131 | No environment changes | Creating, changing or deleting an environment or its deployment branch policies fails with `only repository admins (people, not agents) can manage environments`. | None. |
132132 | Agent reports never satisfy required checks | Commit statuses and check runs an agent reports are shown on the commit, but never count toward a required status check, and aren't counted when a deployment checks the commit's statuses. A failure reported by the real source still fails. | None. Report required checks from workflows or from a person's token. |
133133 | Workflow runs of agent code act as the agent | A run counts as coming from an agent when an agent triggered it, an agent pushed the branch it runs on last, or (for pull request events) an agent opened the pull request or last pushed its head branch. Re-runs of such a run keep this, whoever starts them, and so do `workflow_run` runs that follow it, since they act on what it produced. The run's jobs act as an agent: their `GITHUB_TOKEN` gets the guardrails in this table, so it can't push or merge to the default or protected branches even with `permissions: contents: write`, and their deployments count as an agent's. Agent-written code can't reach a protected branch through a workflow. | The same per-branch settings, **Allow agents to push directly** and **Allow agents to merge pull requests**. |
134-| No repository or organization secrets for agent runs | A run whose code came from an agent (see the row above) gets no repository or organization secrets, only its job token, so an agent can't push a workflow that sends them elsewhere. | A repository admin who is a person ticks **Give runs of agent code the repository's and organization's secrets** under **Settings → Actions** (`agent_runs_use_secrets`). See [Which runs receive secrets](/docs/actions/secrets-and-variables#which-runs-receive-secrets). |
134+| No repository or organization secrets for agent runs | A run whose code came from an agent (see the row above) gets no repository or organization secrets, only its job token, so an agent can't push a workflow that sends them elsewhere. Once an agent lands a pull request on the default branch through auto-merge, runs on that branch are agent code too, so a deploy there gets no repository secrets. | A repository admin who is a person ticks **Give runs of agent code the repository's and organization's secrets** under **Settings → Actions** (`agent_runs_use_secrets`), or, tighter, keeps deploy credentials in an environment limited to protected branches (next row). See [Which runs receive secrets](/docs/actions/secrets-and-variables#which-runs-receive-secrets). |
135135 | No environment secrets for agent runs on open environments | A job with `environment:` in a run whose code came from an agent (see the row above) gets the environment's secrets only when the environment is limited to protected branches. Pull request runs never get environment secrets. | Limit the environment to **protected branches**. |
136136 | Agent tags don't match environment tag rules | A tag last pushed or moved by an agent never matches an environment's tag pattern, so it can't deploy to that environment. | Have a person push the tag. |
137137 | No review dismissal | Dismissing a review fails with `agents can't dismiss reviews`, whatever the agent's role. | None. |
modifiedapps/diffinery/docs/migrate-from-github.md+4−2View file
@@ -626,6 +626,8 @@
626626
627627 Environment secrets (listed as `production/DEPLOY_KEY`) are set with the environments API, as in [Environments and their secrets](#environments-and-their-secrets).
628628
629+You don't have to wait for the import to finish: secrets, variables, environments and collaborators can be set while it is still running (see [Retries, cancelling and the repository lock](#retries-cancelling-and-the-repository-lock)). Set them before your first push, because that push starts the imported workflows.
630+
629631 ### Check the rest
630632
631633 1. Under **Settings → General**, check the default branch, description and visibility.
@@ -814,7 +816,7 @@
814816
815817 | If a workflow... | Do this on Diffinery |
816818 | --- | --- |
817-| Uses `runs-on: windows-*` or `macos-*` | Windows and macOS hosted runners are not supported yet. Run the job on a self-hosted runner (`diffinery runner`). See [Runners](/docs/actions/runners). |
819+| Uses `runs-on: windows-*` or `macos-*` | Diffinery has no Windows or macOS hosted runners: Cloudflare Containers run Linux only. Run the job on a self-hosted runner (`diffinery runner`). See [Runners](/docs/actions/runners). |
818820 | Uses `actions/github-script` | Works with the REST API (`github.rest.*`) and the job's token. `github.graphql` doesn't: Diffinery has no GraphQL API yet. |
819821 | Relies on `GITHUB_TOKEN` writing (comments, labels, statuses, releases, pushes) without a `permissions:` block | Repositories created on Diffinery, imported ones included, give the job token GitHub's restricted default, `contents` and `packages` read. Add a `permissions:` block (for example `contents: write`, `issues: write`, `pull-requests: write`) to the workflow or job, or have an admin set the repository default to write. Each endpoint needs its permission, as on GitHub; a missing one gets `403 Resource not accessible by integration`. See [Workflow permissions](/docs/actions/workflow-permissions). |
820822 | Pushes commits or tags using `GITHUB_TOKEN` | Works with `permissions: contents: write`, as on GitHub, within branch protection. The token can't change files under `.github/workflows/`, and a push made with it starts no new `push` workflows. |
@@ -991,7 +993,7 @@
991993 | `the Git transfer did not finish within 6 hours` | The repository is too large or GitHub was too slow. Retry, or split the repository. |
992994 | `the import container stopped before finishing (exit code ...)` | The transfer is retried once automatically; after that, retry the import. |
993995 | `The Git transfer failed and is being retried: ...` (warning) | The first transfer failed and a second one started. Nothing to do. |
994-| `repository is locked by an import in progress` (on a push), or `423 repository is locked by an import in progress; try again when it finishes, or cancel the import` | You wrote to a repository an import is still filling. Wait for the import to finish, or cancel it. |
996+| `repository is locked by an import in progress` (on a push), or `423 repository is locked by an import in progress; try again when it finishes, or cancel the import` | You wrote to a repository an import is still filling. Wait for the import to finish, or cancel it. Actions secrets and variables, environments and collaborators aren't locked: set them while the import runs. |
995997 | `repository already holds content not written by this import; start a new import` | Someone changed the repository between attempts. Start a new import under another name, or delete the repository first. |
996998 | `skipped (agents cannot manage variables)` | An agent started the import. A person sets variables and secrets afterwards. |
997999 | `skipped (you no longer administer the target)` | You lost admin rights on the target before the variables step ran. |
modifiedapps/diffinery/docs/repositories/branch-protection.md+1−0View file
@@ -160,6 +160,7 @@
160160 - The required checks must pass on the head commit, as always; the setting can't be on without at least one, since `allowAgentAutoMerge` needs one.
161161 - A person's requested changes still block the merge, and a pull request that changes a workflow file still needs a person to merge it.
162162 - It is set per branch rule, only by people with the admin role, and never comes in with an import. Turning `allowAgentAutoMerge` off turns this off too. Every change is audited as `repo.protection.agent_approval_waiver`.
163+- What lands this way is the agent's push, so later runs on the branch are runs of agent code (see [Workflow permissions](/docs/actions/workflow-permissions#runs-whose-code-came-from-an-agent)). They get no repository or organization secrets unless an admin turns on **Give runs of agent code the repository's and organization's secrets**, and they do get the secrets of environments limited to protected branches. A deploy that runs after an agent's merge needs one of the two; see [Which runs receive secrets](/docs/actions/secrets-and-variables#which-runs-receive-secrets).
163164
164165 ### Workflow tokens
165166
modifiedapps/diffinery/docs/self-hosting/configuration.md+6−4View file
@@ -12,7 +12,7 @@
1212 | `apps/diffinery/wrangler.jsonc` | Worker name, route, variables, bindings, container settings, cron, and the `dev` environment. | Yes. This is the source of truth. |
1313 | `apps/diffinery/wrangler.deploy.jsonc` | `wrangler.jsonc` without the `dev` environment, plus the real D1 database ID, `ACCESS_TEAM_DOMAIN`, `ACCESS_AUD`, `TURNSTILE_SITE_KEY`, and the route, `PUBLIC_URL` and `MAIL_FROM` for your hostname. Written by `scripts/render-config.mjs` on every deploy and ignored by git. | No. It is regenerated on each deploy. |
1414 | Worker secrets | `MASTER_KEY` and `OIDC_PRIVATE_KEY`, created by `scripts/ensure-secrets.sh`; `TURNSTILE_SECRET`, set by the deploy from its Turnstile widget; and optionally `GITHUB_OAUTH_CLIENT_SECRET`, which you set yourself. | Only to restore them, or to add the optional one. Never change `MASTER_KEY`. |
15-| Repository secrets and variables | Cloudflare credentials and options for the Deploy workflow, and a token for the live test and sync workflows. | Yes, in your forge's repository settings. |
15+| Repository secrets and variables | Cloudflare credentials and options for the Deploy workflow, and a token for the live test. | Yes, in your forge's repository settings. |
1616 | `apps/diffinery/.dev.vars` | Local secrets for `wrangler dev`, such as `MASTER_KEY`. Ignored by git. | Yes, for local development only. |
1717
1818 ## Worker variables
@@ -311,10 +311,12 @@
311311
312312 Deploy reads `DIFFINERY_DOMAIN`, `DIFFINERY_ZONE` and `MAIL_DOMAIN` from the repository's variables and passes them to bootstrap, so you point it at your own hostname without editing the workflow (see [Deploy your own Diffinery](/docs/self-hosting/deploy#step-1-point-the-code-at-your-domain)). Deploy runs on pushes to `main` on any Diffinery instance, and when started by hand on GitHub.
313313
314-The Deploy job and the Sync job run in an environment named `production`. The Live test and Sync workflows target `https://diffinery.com` and its `codician/diffinery` repository; adapt or delete them for your own instance.
314+The Deploy job runs in an environment named `production` (created by its first run, with no branch policy). The Live test targets `https://diffinery.com`; adapt or delete it for your own instance.
315315
316-The **Import campaign** workflow is a manual test of the importer. Started on GitHub (**Run workflow**), it starts the same workflow on Diffinery and prints its report. On Diffinery it imports a list of public GitHub repositories (the `repos` input) as private repositories named `<owner>/campaign-<github owner>-<github repo>`, replacing copies from earlier campaigns. It can then run their push workflows (`run_workflows`, off by default, because that is third-party code) and writes a report of what came across and what ran.
316+**When agents land changes on `main`.** A merge that Diffinery lands for an agent through auto-merge is the agent's push, so the Deploy and Live test runs after it are [runs of agent code](/docs/actions/workflow-permissions#runs-whose-code-came-from-an-agent). Those get no repository or organization secrets, and Deploy stops with `CLOUDFLARE_ACCOUNT_ID is required`. Either keep the secrets in the `production` environment, limited to protected branches, with `main` protected (add `environment: production` to the Live test job as well), or have an admin turn on **Give runs of agent code the repository's and organization's secrets** under **Settings → Actions**. The environment is the tighter choice: the setting gives the secrets to every agent run, branches included. See [Which runs receive secrets](/docs/actions/secrets-and-variables#which-runs-receive-secrets).
317317
318+The **Import campaign** workflow is a manual test of the importer. Start it on Diffinery (**Run workflow** on its page under **Actions**). Started on a GitHub copy, it relays: it starts the same workflow on Diffinery and prints its report. On Diffinery it imports a list of public GitHub repositories (the `repos` input) as private repositories named `<owner>/campaign-<github owner>-<github repo>`, replacing copies from earlier campaigns. It can then run their push workflows (`run_workflows`, off by default, because that is third-party code) and writes a report of what came across and what ran.
319+
318320 - **Queueing.** Diffinery runs at most 3 repository imports per person at a time and answers `429` beyond that, so the campaign queues the rest and starts each one as an earlier one finishes.
319321 - **Time limit.** Imports still waiting when `minutes` runs out are reported as `not started`.
320322 - **Failures.** When a run fails before writing its report, the GitHub side prints the last 150 lines of the job's log instead.
@@ -322,7 +324,7 @@
322324
323325 It needs `DIFFINERY_LIVE_TOKEN` and, optionally, `IMPORT_GITHUB_TOKEN`.
324326
325-Sync to Diffinery runs only when started by hand on GitHub (`workflow_dispatch`). Since the cut-off, the repository's home is on Diffinery, and pushes to GitHub are no longer copied. A run copies the four variables above to the repository on Diffinery (only those that are set), together with the secrets `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID` and `DIFFINERY_LIVE_TOKEN`, so the copy deploys to the same place. It then copies every branch and tag, moving each ref only if it still points where it did when the run read it, so it never puts back an older commit that changed on Diffinery in the meantime. Branch deletions aren't copied. A run on `main` checks that `main` on Diffinery matches and waits for its Actions runs. Tick **Only copy the secrets and variables** to skip the branches, tags and the wait, for a repository on Diffinery that already has the code.
327+Sync to Diffinery is how this repository moved from GitHub to Diffinery, and it is kept as a record. It runs only when started by hand on GitHub (`workflow_dispatch`). Since the cut-off, the repository's home is on Diffinery, and pushes to GitHub are no longer copied. Don't start it on the frozen GitHub copy: it still names the `codician-team` organization, which no longer exists on Diffinery, so a run would create that organization and a new `codician-team/diffinery` repository, which ends the old URLs' redirect to `codician/diffinery`. A run copies the four variables above to the repository on Diffinery (only those that are set), together with the secrets `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID` and `DIFFINERY_LIVE_TOKEN`, so the copy deploys to the same place. It then copies every branch and tag, moving each ref only if it still points where it did when the run read it, so it never puts back an older commit that changed on Diffinery in the meantime. Branch deletions aren't copied. A run on `main` checks that `main` on Diffinery matches and waits for its Actions runs. Tick **Only copy the secrets and variables** to skip the branches, tags and the wait, for a repository on Diffinery that already has the code.
326328
327329 `scripts/diffinery-wait-runs.sh`, which the sync workflow uses to wait for Actions runs on a commit, reads `DIFFINERY` (the instance origin) and `TOKEN` (a Diffinery token) from the environment:
328330
modifiedapps/diffinery/docs/self-hosting/deploy.md+1−1View file
@@ -66,7 +66,7 @@
6666
6767 `DIFFINERY_DOMAIN` is a bare hostname, without `https://` or a path. Diffinery is always served over HTTPS at the root of that hostname.
6868
69-**Other workflows.** `.github/workflows/live-test.yml` and `.github/workflows/sync-to-diffinery.yml` test and mirror the public `diffinery.com` instance. Delete them, or change their `DIFFINERY` host and organization names before you enable them. The sync workflow runs only on GitHub, and only when started by hand: it copies every branch and tag to the instance, copies the deploy secrets and the `DIFFINERY_DOMAIN`, `DIFFINERY_ZONE`, `MAIL_DOMAIN` and `ACCESS_TEAM_DOMAIN` variables, and for `main` waits for the Actions runs there, so the copy on Diffinery deploys itself (see [Configuration](/docs/self-hosting/configuration#repository-secrets-and-variables-for-the-workflows)). `ci.yml` (typecheck, tests and the end-to-end test) works as is. `dind-probe.yml` is a maintenance probe started by hand; you can delete it. `d1-replication.yml` is optional; see [Architecture](/docs/self-hosting/architecture#d1-and-read-replication).
69+**Other workflows.** `.github/workflows/live-test.yml` tests the public `diffinery.com` instance after each deploy; delete it, or change its `DIFFINERY` host before you enable it. `.github/workflows/sync-to-diffinery.yml` moved this repository from GitHub to `diffinery.com`, and `import-campaign.yml` tests the importer there; both name the public instance's organizations, so delete them or change their names. The sync workflow runs only on GitHub, and only when started by hand: it copies every branch and tag to the instance, copies the deploy secrets and the `DIFFINERY_DOMAIN`, `DIFFINERY_ZONE`, `MAIL_DOMAIN` and `ACCESS_TEAM_DOMAIN` variables, and for `main` waits for the Actions runs there, so the copy on Diffinery deploys itself (see [Configuration](/docs/self-hosting/configuration#repository-secrets-and-variables-for-the-workflows)). `ci.yml` (typecheck, tests and the end-to-end test) works as is. `dind-probe.yml` is a maintenance probe started by hand; you can delete it. `d1-replication.yml` is optional; see [Architecture](/docs/self-hosting/architecture#d1-and-read-replication).
7070
7171 > **Note:** The scripts use fixed resource names: a D1 database `diffinery`, an R2 bucket `diffinery-data`, queues `diffinery-events`, `diffinery-events-dlq`, `diffinery-mail`, `diffinery-mail-dlq` and `diffinery-mail-events`, and a Worker `diffinery`. One Cloudflare account holds one instance unless you rename them in `scripts/bootstrap.sh` and `wrangler.jsonc`.
7272