mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
ci: единый staged→tested→published путь установочных ассетов (#540)
`release-zip.yml` выкладывал `houseplan.zip` в ту же секунду, когда релиз становился публичным — до Validate, Full Performance и E2E; `release.yml` параллельно пересобирал `houseplan-card.js`, а E2E требовал публичного ZIP, чтобы вообще начаться. Публикаторов было четыре, порядок — ни одного. Теперь публикатор стабильных один — `release.yml`: закрепить SHA → релиз в черновике (опубликованный руками немедленно возвращается в черновик) → гейты на SHA (трейлер `Release: <tag>`, контракт `--stable`, Validate, Full Performance, E2E на коммите-кандидате через tarball codeload) → одна сборка, `git archive` ZIP из того же дерева, `SHA256SUMS` → загрузка в черновик → публикация → скачать публичное и сверить с паспортом → анонс. Dispatch на публичный тег — ремонт: догружается только недостающее, расходящийся хеш — отказ. Беты кладут тот же паспорт; локальный публикатор больше не ждёт републикаторов — их нет. - `.github/workflows/release-zip.yml` удалён - `scripts/release-assets.mjs` — паспорт ассетов (`sums`/`check`), чистые функции под юнитами - `scripts/e2e-gate.mjs --ref=<sha>` — под тестом кандидат, `--tag` только для выбора `upgrade_from` - `scripts/release-contract.mjs --stable` - мутанты: независимый публикатор, снятая зависимость от гейта, релиз без возврата в черновик, `--clobber` в ремонте, E2E на теге, слепой паспорт Issue: #540 User-Visible: no
This commit is contained in:
@@ -41,10 +41,15 @@ export function parseVersionSources({
|
||||
};
|
||||
}
|
||||
|
||||
export function validateVersionSources(tag, sources, { requirePrerelease = true } = {}) {
|
||||
export function validateVersionSources(tag, sources, { requirePrerelease = true, requireStable = false } = {}) {
|
||||
const parsed = versionFromTag(tag);
|
||||
if (requirePrerelease && !parsed.prerelease)
|
||||
throw new Error(`Prerelease publication requires a prerelease SemVer tag: ${tag}`);
|
||||
// #540: стабильный путь (release.yml) — зеркальное требование: тег без
|
||||
// пре-релизного суффикса. Режима «любой тег» нет: публикатор всегда знает,
|
||||
// что выпускает.
|
||||
if (requireStable && parsed.prerelease)
|
||||
throw new Error(`Stable publication requires a stable SemVer tag, got prerelease ${tag}`);
|
||||
const mismatches = Object.entries(sources)
|
||||
.filter(([, value]) => value !== parsed.version)
|
||||
.map(([name, value]) => `${name}=${JSON.stringify(value)}`);
|
||||
@@ -133,10 +138,10 @@ export function readReleaseContract(root = process.cwd()) {
|
||||
}
|
||||
|
||||
export function assertReleaseContract({
|
||||
root = process.cwd(), tag, repo = 'Matysh/houseplan-card', requirePrerelease = true,
|
||||
root = process.cwd(), tag, repo = 'Matysh/houseplan-card', requirePrerelease = true, requireStable = false,
|
||||
} = {}) {
|
||||
const contract = readReleaseContract(root);
|
||||
const parsed = validateVersionSources(tag, contract.sources, { requirePrerelease });
|
||||
const parsed = validateVersionSources(tag, contract.sources, { requirePrerelease, requireStable });
|
||||
if (!changelogContainsVersion(contract.changelogRu, tag))
|
||||
throw new Error(`docs/CHANGELOG.ru.md has no dated ${tag} section`);
|
||||
if (!changelogContainsVersion(contract.changelogEn, tag))
|
||||
@@ -152,14 +157,18 @@ if (invokedDirectly) {
|
||||
const args = process.argv.slice(2);
|
||||
const positionals = args.filter((arg) => !arg.startsWith('--'));
|
||||
const repoArgs = args.filter((arg) => arg.startsWith('--repo='));
|
||||
const unknown = args.filter((arg) => arg.startsWith('--') && !arg.startsWith('--repo='));
|
||||
// #540: `--stable` — контракт стабильного релиза (release.yml). Тот же
|
||||
// набор проверок; отличие одно — тег обязан быть БЕЗ пре-релизного суффикса,
|
||||
// как без флага он обязан быть с ним. Третьего режима «любой тег» нет.
|
||||
const stable = args.includes('--stable');
|
||||
const unknown = args.filter((arg) => arg.startsWith('--') && !arg.startsWith('--repo=') && arg !== '--stable');
|
||||
if (positionals.length !== 1) throw new Error('Exactly one release tag is required');
|
||||
if (repoArgs.length > 1 || unknown.length)
|
||||
throw new Error(`Unknown or duplicate release-contract arguments: ${[...repoArgs.slice(1), ...unknown].join(', ')}`);
|
||||
const tag = positionals[0];
|
||||
const repo = repoArgs[0]?.slice('--repo='.length)
|
||||
|| process.env.GITHUB_REPOSITORY || 'Matysh/houseplan-card';
|
||||
const result = assertReleaseContract({ tag, repo, requirePrerelease: true });
|
||||
const result = assertReleaseContract({ tag, repo, requirePrerelease: !stable, requireStable: stable });
|
||||
console.log(JSON.stringify({
|
||||
ok: true, tag: result.tag, version: result.version,
|
||||
prerelease: result.prerelease, sources: result.sources,
|
||||
|
||||
Reference in New Issue
Block a user