v3 : publication — un envoi refusé repart, un dépôt neuf reçoit l'historique
ci/woodpecker/push/app Pipeline was successful
ci/woodpecker/push/maquette Pipeline was successful

Douzième relecture (850f9c4 : ok), défauts anciens de publish.rs mis en
jeu par le nouveau dépôt :
- un commit que le dépôt n'a jamais reçu (premier envoi refusé, clé sans
  droit d'écriture) repart au passage suivant, au lieu d'une file marquée
  faite avec un dépôt vide ;
- un changement de remote vers un dépôt neuf et vide lui envoie
  l'historique ;
- au démarrage, ce qui attendait repart aussitôt (le délai croissant
  pouvait atteindre 6 h).
trustinWallet montre l'état de la publication (en attente, dernier échec,
dernier commit) et offre « Publier maintenant ».

Boucle : 69 tests Rust, svelte-check, 9 vitest, e2e 13/13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-10-21 21:30:52 +02:00
co-authored by Claude Opus 5.5
parent 850f9c46b0
commit 744d157b01
10 changed files with 208 additions and 15 deletions
+25 -1
View File
@@ -7,9 +7,14 @@
import { i18n, t, type Key } from '$lib/i18n/index.svelte';
import { Remote } from '$lib/load.svelte';
import { session } from '$lib/session.svelte';
import { toasts } from '$lib/toast.svelte';
interface Overview {
publication: { remote: string | null; publicKey: string | null };
publication: {
remote: string | null;
publicKey: string | null;
status?: { pending: number; lastError: string | null; lastPublishedAt: string | null; lastCommit: string | null };
};
groups: { slug: string; name: string; policy: string; hidden: boolean; members: { identityId: string; grantedAt: string }[] }[];
identities: { id: string; kind: 'g1' | 'invite' | 'dev'; displayName: string; g1Member: boolean; admin: boolean; lastSeenAt: string | null; teamLink: string | null }[];
invitations: { id: string; label: string; admin: boolean; groups: string[]; expiresAt: string }[];
@@ -57,6 +62,13 @@
});
}
async function publishNow() {
await act(async () => {
await api.post('/access/publication/retry');
toasts.show(t('access.publication.queued'));
});
}
// A new sign-in link for an invited person (another device, a lost session).
async function relink(id: string, name: string) {
await act(async () => {
@@ -166,6 +178,15 @@
<div class="card block">
{#if data.value.publication.remote}
<p class="small">{t('access.publication.remote', { remote: data.value.publication.remote })}</p>
{#if data.value.publication.status}
{@const st = data.value.publication.status}
<p class="small">
{#if st.lastPublishedAt}{t('access.publication.last', { date: i18n.date(st.lastPublishedAt), commit: (st.lastCommit ?? '').slice(0, 7) })}{:else}{t('access.publication.never')}{/if}
{#if st.pending} · {i18n.plural('access.publication.pending', st.pending)}{/if}
</p>
{#if st.pending && st.lastError}<p class="small faint err">{t('access.publication.error', { error: st.lastError })}</p>{/if}
{#if st.pending}<button class="btn small" type="button" onclick={publishNow}>{t('access.publication.now')}</button>{/if}
{/if}
{#if data.value.publication.publicKey}
<p class="small muted">{t('access.publication.key')}</p>
<code class="key">{data.value.publication.publicKey}</code>
@@ -277,6 +298,9 @@
padding: 0.6rem 0.8rem;
border-radius: var(--r-input);
}
.err {
word-break: break-word;
}
.fb .body {
white-space: pre-wrap;
}