🗃️ (mirrors): Renumber push-mirror migration to V11 after rebase
Changes
3 files changed, +41 -33
MODIFY
docs/maintainers/push-mirrors.md
+1 -1
@@ -6,7 +6,7 @@
6
6
7
7
| Piece | Where | Role |
8
8
|---|---|---|
9
-| `PushMirror`, `MirrorSync` | `model/` | Mirror record (secret encrypted via `@Convert`) and queue row; tables `push_mirror`, `mirror_sync` (migration `V10__push_mirror.sql`) |
9
+| `PushMirror`, `MirrorSync` | `model/` | Mirror record (secret encrypted via `@Convert`) and queue row; tables `push_mirror`, `mirror_sync` (migration `V11__push_mirror.sql`) |
10
10
| `MirrorService` | `mirror/` | Owner-facing CRUD, enqueue-on-push, scheduled drain (`@Scheduled every 10s`), retry/backoff/dead-letter bookkeeping |
11
11
| `MirrorPusher` | `mirror/` | One JGit push attempt: ref-advertisement read, mirror update set, HTTPS credentials or per-mirror SSH session factory |
12
12
| `SecretCrypto`, `EncryptedStringConverter` | `mirror/` | AES-256-GCM at-rest encryption keyed from `gitshark.secret-key` (SHA-256-derived); converter resolves the bean lazily via ArC |
DELETE
src/main/resources/db/migration/V10__push_mirror.sql
+0 -32
@@ -1,40 +0,0 @@
1
-
2
-create table push_mirror
3
-(
4
- id uuid primary key,
5
- repository_id uuid not null references repositories (id) on delete cascade,
6
- remote_url text not null,
7
- auth_type varchar(8) not null check (auth_type in ('HTTPS', 'SSH')),
8
- username varchar(255),
9
- encrypted_secret text not null,
10
- public_key text,
11
- host_key text,
12
- enabled boolean not null default true,
13
- last_attempt_at timestamptz,
14
- last_success_at timestamptz,
15
- last_error text,
16
- created_at timestamptz not null default now()
17
-);
18
-
19
-create index idx_push_mirror_repo on push_mirror (repository_id);
20
-
21
-create table mirror_sync
22
-(
23
- id uuid not null primary key,
24
- mirror_id uuid not null references push_mirror (id) on delete cascade,
25
- state varchar(16) not null default 'PENDING' check (state in ('PENDING', 'SYNCED', 'FAILED')),
26
- attempts int not null default 0,
27
- next_attempt_at timestamptz not null default now(),
28
- last_error text,
29
- created_at timestamptz not null default now()
30
-);
31
-
32
-create index idx_mirror_sync_due on mirror_sync (state, next_attempt_at);
ADD
src/main/resources/db/migration/V11__push_mirror.sql
+40 -0
@@ -0,0 +1,40 @@
1
+-- Push mirrors: replicate a repository to an external remote on every push.
2
+
3
+-- One row per configured mirror. encrypted_secret holds the HTTPS password/token or the SSH
4
+-- private key PEM, encrypted at rest by the application (GITSHARK_SECRET_KEY). public_key and
5
+-- host_key are SSH-only: the generated deploy key shown to the owner, and the remote host key
6
+-- pinned on first successful contact.
7
+create table push_mirror
8
+(
9
+ id uuid primary key,
10
+ repository_id uuid not null references repositories (id) on delete cascade,
11
+ remote_url text not null,
12
+ auth_type varchar(8) not null check (auth_type in ('HTTPS', 'SSH')),
13
+ username varchar(255),
14
+ encrypted_secret text not null,
15
+ public_key text,
16
+ host_key text,
17
+ enabled boolean not null default true,
18
+ last_attempt_at timestamptz,
19
+ last_success_at timestamptz,
20
+ last_error text,
21
+ created_at timestamptz not null default now()
22
+);
23
+
24
+create index idx_push_mirror_repo on push_mirror (repository_id);
25
+
26
+-- Async sync queue, one PENDING row per mirror at most (rapid pushes coalesce). Drained by a
27
+-- scheduled worker with exponential backoff; exhausted rows become FAILED (dead-lettered) and the
28
+-- next repository push enqueues a fresh one.
29
+create table mirror_sync
30
+(
31
+ id uuid not null primary key,
32
+ mirror_id uuid not null references push_mirror (id) on delete cascade,
33
+ state varchar(16) not null default 'PENDING' check (state in ('PENDING', 'SYNCED', 'FAILED')),
34
+ attempts int not null default 0,
35
+ next_attempt_at timestamptz not null default now(),
36
+ last_error text,
37
+ created_at timestamptz not null default now()
38
+);
39
+
40
+create index idx_mirror_sync_due on mirror_sync (state, next_attempt_at);