Skip to content

Commit e736bab

Browse files
committed
feat: add installer sync
1 parent d30fb2a commit e736bab

6 files changed

Lines changed: 367 additions & 75 deletions

File tree

.github/workflows/publish.yml

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,15 @@ jobs:
6969
- name: publish-stable
7070
env:
7171
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
72-
# Optional: HTTP trigger for external FC (GitHub Release → OSS). Leave unset to skip.
73-
BAILIAN_OSS_SYNC_WEBHOOK: ${{ secrets.BAILIAN_OSS_SYNC_WEBHOOK }}
72+
# OSS release channel runs fully in CI: upload + reconcile + manifest.json.
73+
# All values come from repo Settings: credentials via Secrets, the rest
74+
# via Variables. Leave the secrets unset to skip the OSS channel entirely.
75+
BAILIAN_OSS_AK: ${{ secrets.BAILIAN_OSS_AK }}
76+
BAILIAN_OSS_SK: ${{ secrets.BAILIAN_OSS_SK }}
77+
BAILIAN_OSS_BUCKET: ${{ vars.BAILIAN_OSS_BUCKET }}
78+
BAILIAN_OSS_REGION: ${{ vars.BAILIAN_OSS_REGION }}
79+
BAILIAN_OSS_ENDPOINT: ${{ vars.BAILIAN_OSS_ENDPOINT }}
80+
BAILIAN_RELEASE_PREFIX: ${{ vars.BAILIAN_RELEASE_PREFIX }}
7481
run: node tools/release/publish-stable.mjs ${{ inputs.package == 'knowledge-studio-cli' && '--knowledge' || '' }}
7582

7683
publish-channel:
@@ -120,5 +127,11 @@ jobs:
120127
- name: publish-channel
121128
env:
122129
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
123-
BAILIAN_OSS_SYNC_WEBHOOK: ${{ secrets.BAILIAN_OSS_SYNC_WEBHOOK }}
130+
# OSS release channel — same Settings-injected values as stable.
131+
BAILIAN_OSS_AK: ${{ secrets.BAILIAN_OSS_AK }}
132+
BAILIAN_OSS_SK: ${{ secrets.BAILIAN_OSS_SK }}
133+
BAILIAN_OSS_BUCKET: ${{ vars.BAILIAN_OSS_BUCKET }}
134+
BAILIAN_OSS_REGION: ${{ vars.BAILIAN_OSS_REGION }}
135+
BAILIAN_OSS_ENDPOINT: ${{ vars.BAILIAN_OSS_ENDPOINT }}
136+
BAILIAN_RELEASE_PREFIX: ${{ vars.BAILIAN_RELEASE_PREFIX }}
124137
run: node tools/release/publish-channel.mjs ${{ inputs.package == 'knowledge-studio-cli' && '--knowledge' || '' }} --channel "${{ inputs.channel }}"

tools/release/lib/binary-release.mjs

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,24 @@
1010
* binaries); only the rolling `channel-<name>` manifest differs per channel.
1111
*
1212
* Re-runs are idempotent via `gh release upload --clobber` (see gh-release.mjs).
13-
* Optionally notifies BAILIAN_OSS_SYNC_WEBHOOK (see oss-sync-webhook.mjs).
13+
* After the GitHub upload the same assets are pushed straight to OSS from the
14+
* runner, HEAD-reconciled, and (stable only) release/manifest.json is updated —
15+
* all in-process, no external FC (see oss-direct-upload.mjs).
1416
*
1517
* Called by publish-stable.mjs / publish-channel.mjs.
1618
* Debug:
1719
* node tools/release/lib/binary-release.mjs --mode stable --dry-run
1820
* node tools/release/lib/binary-release.mjs --mode channel --channel beta --dry-run
1921
*/
2022
import { existsSync, readdirSync, readFileSync } from "node:fs";
21-
import { join, resolve } from "node:path";
23+
import { basename, join, resolve } from "node:path";
2224
import { fileURLToPath } from "node:url";
2325
import { parseArgs as parseCliArgs } from "node:util";
2426
import { ROOT, readPackageJson, PACKAGES } from "./packages.mjs";
2527
import { buildBinaryArtifacts, matrixAssetNames } from "./binary-build.mjs";
2628
import { channelManifestFileName, normalizeModeChannel } from "./binary-options.mjs";
2729
import { ensureGh, GITHUB_REPOSITORY, upsertRelease } from "./gh-release.mjs";
28-
import { notifyOssSyncWebhook } from "./oss-sync-webhook.mjs";
30+
import { maintainReleaseManifest, mirrorReleaseAssetsToOss } from "./oss-direct-upload.mjs";
2931

3032
const DEFAULT_DIR = join(ROOT, "dist-bin");
3133

@@ -124,14 +126,31 @@ function planDryRunWithoutArtifacts({ version, mode, channel }) {
124126
});
125127
}
126128

129+
/**
130+
* Build the OSS mirror plan — the same tag/asset pairs as the GitHub Release
131+
* upload. `files == null` means dry-run planning without artifacts on disk,
132+
* so bare basenames stand in for real paths.
133+
*/
134+
function ossMirrorPlans({ dir, version, mode, channel, files }) {
135+
const paths = files
136+
? versionBinaryAssets(dir, version, files)
137+
: [...matrixAssetNames(version), "SHA256SUMS"];
138+
const plans = [{ tag: `v${version}`, paths }];
139+
if (mode === "channel") {
140+
const manifest = channelManifestFileName(channel);
141+
plans.push({ tag: `channel-${channel}`, paths: [files ? join(dir, manifest) : manifest] });
142+
}
143+
return plans;
144+
}
145+
127146
/**
128147
* Build (unless skipped / dry-run) and upload binary artifacts to GitHub Releases.
129148
* Called by publish-stable / publish-channel orchestrators.
130149
*
131150
* `--dry-run` never compiles; it plans gh release steps. Prebuilt `dist-bin` is
132151
* optional (used only to list real paths when present).
133152
*/
134-
export function releaseBinaryArtifacts(rawOptions = {}) {
153+
export async function releaseBinaryArtifacts(rawOptions = {}) {
135154
const { mode, channel } = normalizeModeChannel(rawOptions.mode, rawOptions.channel);
136155
const dir = rawOptions.dir ? resolve(rawOptions.dir) : DEFAULT_DIR;
137156
const dryRun = Boolean(rawOptions.dryRun);
@@ -157,7 +176,15 @@ export function releaseBinaryArtifacts(rawOptions = {}) {
157176
if (dryRun && !existsSync(dir)) {
158177
process.stdout.write(`[dry-run] ${dir} missing; planning expected assets\n`);
159178
planDryRunWithoutArtifacts({ version, mode, channel });
160-
notifyOssSyncWebhook({ version, mode, channel, dryRun });
179+
const plans = ossMirrorPlans({ dir, version, mode, channel, files: null });
180+
await mirrorReleaseAssetsToOss({ plans, dryRun: true });
181+
if (mode === "stable") {
182+
await maintainReleaseManifest({
183+
tag: `v${version}`,
184+
assetNames: plans[0].paths.map((path) => basename(path)),
185+
dryRun: true,
186+
});
187+
}
161188
return { version, mode, channel, dryRun };
162189
}
163190

@@ -198,7 +225,18 @@ export function releaseBinaryArtifacts(rawOptions = {}) {
198225
uploadChannel({ dir, version, channel, files, dryRun });
199226
}
200227

201-
notifyOssSyncWebhook({ version, mode, channel, dryRun });
228+
// Push the exact Release assets straight to OSS from the runner, then
229+
// HEAD-reconcile. Stable releases additionally maintain release/manifest.json
230+
// (newer-version guard). Throws on failure — CI is the only OSS writer.
231+
const plans = ossMirrorPlans({ dir, version, mode, channel, files });
232+
const mirror = await mirrorReleaseAssetsToOss({ plans, dryRun });
233+
if (mode === "stable" && !mirror.skipped) {
234+
await maintainReleaseManifest({
235+
tag: `v${version}`,
236+
assetNames: plans[0].paths.map((path) => basename(path)),
237+
dryRun,
238+
});
239+
}
202240

203241
return { version, mode, channel, dryRun };
204242
}
@@ -223,7 +261,7 @@ if (resolve(process.argv[1] ?? "") === fileURLToPath(import.meta.url)) {
223261
process.stdout.write(USAGE);
224262
process.exit(0);
225263
}
226-
releaseBinaryArtifacts({
264+
await releaseBinaryArtifacts({
227265
dir: values.dir ? resolve(values.dir) : undefined,
228266
dryRun: values["dry-run"],
229267
mode: values.mode,

0 commit comments

Comments
 (0)