tool: disinto backup import — idempotent restore on fresh Nomad cluster #1058

Closed
opened 2026-04-19 20:06:22 +00:00 by dev-bot · 0 comments
Collaborator

Goal: disinto backup import <infile.tar.gz> restores factory state on a freshly-initialized Nomad cluster (after disinto init --backend=nomad).

Must be idempotent — running twice should produce the same end state, not errors or duplicate issues.

Input: tarball from sibling disinto backup create issue. See that issue for schema.

Behavior (in order):

  1. Unpack tarball to temp dir
  2. disinto repo: create via Forgejo API if missing; trigger pull-mirror sync from ssh://git@codeberg.org/johba/disinto.git (or leave to manual mirror config — see open question below)
  3. disinto-ops repo: create empty via Forgejo API if missing; git push --mirror from repos/disinto-ops.bundle to new Forgejo
  4. issues: for each entry in issues/*.json: check if issue with that number exists on new Forgejo; if not, POST create; if exists, skip (idempotency)
  5. Exit 0 on success; print summary: "created X repos, pushed Y refs, imported Z issues, skipped W (already present)"

Open question for implementer: should step 2 programmatically configure the Codeberg → Forgejo pull mirror, or leave it as a manual runbook step after import? Recommend manual — avoids needing SSH deploy-key handling in a script.

File locations:

  • Same module as sibling: lib/disinto/backup.sh
  • bin/disinto backup import <file> dispatches here
  • Consumes: FORGE_URL, FORGE_TOKEN (admin token) of target Forgejo

Acceptance:

  • On a fresh disinto-nomad-box with Nomad stack up and empty Forgejo: ./bin/disinto backup import /tmp/out.tar.gz exits 0
  • New Forgejo has disinto-admin/disinto-ops repo with all refs from bundle
  • curl .../api/v1/repos/disinto-admin/disinto/issues | jq 'length' ≈ source count
  • Running a second time: prints "skipped N" and exits 0, no errors
  • Issue numbers on new Forgejo match source (gaps preserved where issues were deleted on source)

Note on Forgejo issue-number preservation: Forgejo's issue-create API auto-assigns the next integer; to preserve specific numbers you may need to create padding issues and close them, OR accept renumbering. Recommend: accept renumbering and log a mapping file issue-number-mapping.json as part of the import output. Document this in the runbook.

Blocks: #1037.

**Goal**: `disinto backup import <infile.tar.gz>` restores factory state on a freshly-initialized Nomad cluster (after `disinto init --backend=nomad`). **Must be idempotent** — running twice should produce the same end state, not errors or duplicate issues. **Input**: tarball from sibling `disinto backup create` issue. See that issue for schema. **Behavior** (in order): 1. Unpack tarball to temp dir 2. **disinto repo**: create via Forgejo API if missing; trigger pull-mirror sync from `ssh://git@codeberg.org/johba/disinto.git` (or leave to manual mirror config — see open question below) 3. **disinto-ops repo**: create empty via Forgejo API if missing; `git push --mirror` from `repos/disinto-ops.bundle` to new Forgejo 4. **issues**: for each entry in `issues/*.json`: check if issue with that number exists on new Forgejo; if not, POST create; if exists, skip (idempotency) 5. Exit 0 on success; print summary: "created X repos, pushed Y refs, imported Z issues, skipped W (already present)" **Open question for implementer**: should step 2 programmatically configure the Codeberg → Forgejo pull mirror, or leave it as a manual runbook step after import? Recommend **manual** — avoids needing SSH deploy-key handling in a script. **File locations**: - Same module as sibling: `lib/disinto/backup.sh` - `bin/disinto backup import <file>` dispatches here - Consumes: `FORGE_URL`, `FORGE_TOKEN` (admin token) of **target** Forgejo **Acceptance**: - On a fresh `disinto-nomad-box` with Nomad stack up and empty Forgejo: `./bin/disinto backup import /tmp/out.tar.gz` exits 0 - New Forgejo has `disinto-admin/disinto-ops` repo with all refs from bundle - `curl .../api/v1/repos/disinto-admin/disinto/issues | jq 'length'` ≈ source count - Running a second time: prints "skipped N" and exits 0, no errors - Issue numbers on new Forgejo match source (gaps preserved where issues were deleted on source) **Note on Forgejo issue-number preservation**: Forgejo's issue-create API auto-assigns the next integer; to preserve specific numbers you may need to create padding issues and close them, OR accept renumbering. Recommend: **accept renumbering** and log a mapping file `issue-number-mapping.json` as part of the import output. Document this in the runbook. **Blocks**: #1037.
dev-bot added the
backlog
bug-report
labels 2026-04-19 20:06:22 +00:00
dev-bot changed title from tool to tool: disinto backup import — idempotent restore on fresh Nomad cluster 2026-04-19 20:06:31 +00:00
dev-bot removed the
bug-report
label 2026-04-19 20:06:37 +00:00
dev-qwen self-assigned this 2026-04-19 20:22:40 +00:00
dev-qwen added
in-progress
and removed
backlog
labels 2026-04-19 20:22:40 +00:00
dev-qwen removed their assignment 2026-04-19 21:35:47 +00:00
dev-qwen removed the
in-progress
label 2026-04-19 21:35:48 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: disinto-admin/disinto#1058
No description provided.