Compare commits
No commits in common. "d302614b99f9b11547a91d209b77a9aeeff275ab" and "02d9063a112d48baa093fcb8aa7d0d3e381784c0" have entirely different histories.
d302614b99
...
02d9063a11
34
.drone.yml
34
.drone.yml
@ -1,34 +0,0 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: release-tag
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- tag
|
||||
|
||||
steps:
|
||||
- name: install
|
||||
image: node:20-alpine
|
||||
commands:
|
||||
- npm ci
|
||||
|
||||
- name: test
|
||||
image: node:20-alpine
|
||||
depends_on:
|
||||
- install
|
||||
commands:
|
||||
- npm test
|
||||
|
||||
- name: release
|
||||
image: node:20-alpine
|
||||
depends_on:
|
||||
- test
|
||||
environment:
|
||||
COS_BUCKET: wksgx-1343191620
|
||||
COS_REGION: ap-nanjing
|
||||
COS_SECRET_ID:
|
||||
from_secret: cos_secret_id
|
||||
COS_SECRET_KEY:
|
||||
from_secret: cos_secret_key
|
||||
commands:
|
||||
- npm run release:tag
|
||||
@ -93,8 +93,6 @@ npm run write:latest
|
||||
- 这个压缩包不是给 Chrome 商店上传的
|
||||
- 它是发给公司内部同事使用的交付包
|
||||
- 同事收到后需要解压,再到 `chrome://extensions` 中 `Load unpacked`
|
||||
- COS 发布时,`latest.json` 放在 `star-chart-search-enhancer/latest.json`,ZIP 和 PDF 放在对应版本目录下
|
||||
- 打 tag 后会触发 Drone 发布,推荐格式:`0.MMDD.N`
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
"identity",
|
||||
"storage"
|
||||
],
|
||||
"version": "0.2.0421.2",
|
||||
"web_accessible_resources": [
|
||||
{
|
||||
"matches": [
|
||||
@ -47,7 +48,6 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"version": "0.2.0421.2",
|
||||
"host_permissions": [
|
||||
"https://xingtu.cn/ad/creator/market*",
|
||||
"https://*.xingtu.cn/ad/creator/market*",
|
||||
|
||||
@ -263,7 +263,7 @@
|
||||
}
|
||||
|
||||
// src/shared/update-config.ts
|
||||
var UPDATE_MANIFEST_URL = "https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/latest.json";
|
||||
var UPDATE_MANIFEST_URL = "https://example.com/star-chart-search-enhancer/latest.json";
|
||||
|
||||
// src/popup/index.ts
|
||||
async function bootPopup(options = {}) {
|
||||
|
||||
@ -23,50 +23,19 @@ The popup checks `src/shared/update-config.ts` for the update manifest URL.
|
||||
Before publishing the COS-based update flow:
|
||||
|
||||
1. Upload these files to COS:
|
||||
- `star-chart-search-enhancer/latest.json`
|
||||
- `star-chart-search-enhancer/releases/<version>/star-chart-search-enhancer-internal.zip`
|
||||
- `star-chart-search-enhancer/releases/<version>/星图增强插件-超简单安装使用指南.pdf`
|
||||
- `release/latest.json`
|
||||
- `release/star-chart-search-enhancer-internal.zip`
|
||||
- `release/星图增强插件-超简单安装使用指南.pdf`
|
||||
2. Make the COS path publicly readable.
|
||||
3. Replace the placeholder `UPDATE_MANIFEST_URL` in `src/shared/update-config.ts` if your COS bucket changes.
|
||||
3. Replace the placeholder `UPDATE_MANIFEST_URL` in `src/shared/update-config.ts`.
|
||||
4. Rebuild and package the extension.
|
||||
|
||||
The release manifest can be generated with a real public base URL:
|
||||
|
||||
```bash
|
||||
UPDATE_PUBLIC_BASE_URL="https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/releases/<version>" npm run write:latest
|
||||
UPDATE_PUBLIC_BASE_URL="https://<your-cos-domain>/star-chart-search-enhancer/releases/<version>" npm run write:latest
|
||||
```
|
||||
|
||||
Quick access check:
|
||||
|
||||
```bash
|
||||
curl -I https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/latest.json
|
||||
```
|
||||
|
||||
## Drone Release Flow
|
||||
|
||||
Tag the repo to trigger the release pipeline:
|
||||
|
||||
```bash
|
||||
git tag 0.0525.1
|
||||
git push origin 0.0525.1
|
||||
```
|
||||
|
||||
The Drone job will:
|
||||
|
||||
1. Run `npm ci`.
|
||||
2. Run `npm test`.
|
||||
3. Run `npm run release:tag`.
|
||||
4. Build the release bundle.
|
||||
5. Write `release/latest.json`.
|
||||
6. Upload `latest.json`, the ZIP, and the PDF to COS.
|
||||
|
||||
Drone secrets required:
|
||||
|
||||
- `cos_secret_id`
|
||||
- `cos_secret_key`
|
||||
|
||||
The pipeline uses the tag as the release version. Recommended format: `0.MMDD.N`.
|
||||
|
||||
## Coworker Install Steps
|
||||
|
||||
1. Unzip `star-chart-search-enhancer-internal.zip`.
|
||||
|
||||
@ -1,128 +0,0 @@
|
||||
# COS Extension Update Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Point the popup update flow at the real COS release bucket and keep the generated release manifest, docs, and tests aligned with that COS-based distribution path.
|
||||
|
||||
**Architecture:** Reuse the existing update-check flow already in `src/shared/update-check.ts`, `src/popup/index.ts`, `src/popup/view.ts`, and `src/background/index.ts`. The only behavior change is the source of truth: the popup should fetch a stable COS-hosted `latest.json`, while `scripts/write-latest-manifest.mjs` should keep generating versioned asset URLs under the COS release folder. Everything else stays manual and user-driven.
|
||||
|
||||
**Tech Stack:** TypeScript, Chrome MV3, Vitest, Node.js ESM scripts, Tencent COS public HTTPS URLs
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Lock the popup manifest URL to COS
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/shared/update-config.ts`
|
||||
- Test: `tests/update-config.test.ts`
|
||||
|
||||
- [ ] **Step 1: Write the failing URL test**
|
||||
|
||||
Add a small test that asserts `UPDATE_MANIFEST_URL` points at the stable COS-hosted `latest.json` URL for this bucket:
|
||||
|
||||
```ts
|
||||
expect(UPDATE_MANIFEST_URL).toBe(
|
||||
"https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/latest.json"
|
||||
);
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run the focused test**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm test -- tests/update-config.test.ts
|
||||
```
|
||||
|
||||
Expected: FAIL because the current constant still uses the placeholder example URL.
|
||||
|
||||
- [ ] **Step 3: Update the constant**
|
||||
|
||||
Replace the placeholder string in `src/shared/update-config.ts` with the COS `latest.json` URL above.
|
||||
|
||||
- [ ] **Step 4: Verify**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm test -- tests/update-config.test.ts tests/popup-entry.test.ts
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
### Task 2: Generate release assets from the COS base
|
||||
|
||||
**Files:**
|
||||
- Modify: `scripts/write-latest-manifest.mjs`
|
||||
- Modify: `release/latest.json`
|
||||
- Test: `tests/update-check.test.ts`
|
||||
|
||||
- [ ] **Step 1: Write a manifest generation regression test**
|
||||
|
||||
Add or extend a test that proves the generated manifest uses the COS release base for assets, not `example.com`. Use the COS base:
|
||||
|
||||
```ts
|
||||
https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/releases/0.2.0421.2
|
||||
```
|
||||
|
||||
Assert that `zipUrl` and `guideUrl` are derived from that base.
|
||||
|
||||
- [ ] **Step 2: Run the focused test**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm test -- tests/update-check.test.ts
|
||||
```
|
||||
|
||||
Expected: FAIL until the generator default points at COS.
|
||||
|
||||
- [ ] **Step 3: Update the generator default**
|
||||
|
||||
Change `publicBaseUrl` in `scripts/write-latest-manifest.mjs` to default to the COS release base for this bucket and region, while keeping `UPDATE_PUBLIC_BASE_URL` as the override path for future releases.
|
||||
|
||||
- [ ] **Step 4: Regenerate the tracked manifest**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm run write:latest
|
||||
```
|
||||
|
||||
Then confirm `release/latest.json` contains the COS URLs.
|
||||
|
||||
- [ ] **Step 5: Verify**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm test -- tests/update-check.test.ts tests/popup-entry.test.ts tests/background-index.test.ts
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
### Task 3: Update distribution docs and verify COS access
|
||||
|
||||
**Files:**
|
||||
- Modify: `docs/internal-extension-distribution.md`
|
||||
- Modify: `README.md`
|
||||
|
||||
- [ ] **Step 1: Update the release instructions**
|
||||
|
||||
Document the stable manifest URL, the versioned asset base, and the upload flow to COS. Keep the user-facing manual install steps unchanged.
|
||||
|
||||
- [ ] **Step 2: Add the COS verification command**
|
||||
|
||||
Document a `curl -I` check for the public `latest.json` URL and the uploaded ZIP/PDF so a failed COS ACL is caught before release.
|
||||
|
||||
- [ ] **Step 3: Run the final verification**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm test
|
||||
npm run build:release
|
||||
```
|
||||
|
||||
Expected: PASS, and the generated release bundle should still open the popup update card correctly.
|
||||
|
||||
@ -1,84 +0,0 @@
|
||||
# COS Extension Update Design
|
||||
|
||||
## Goal
|
||||
|
||||
Use COS as the release source for extension updates. When the popup opens, it checks a public `latest.json` on COS. If the COS version is newer than the installed extension version, the popup shows an update card with download actions for the ZIP and the PDF guide, plus manual reload instructions.
|
||||
|
||||
## Confirmed Scope
|
||||
|
||||
- Update prompt appears only in the extension popup.
|
||||
- No star chart page banner in this change.
|
||||
- The user keeps the current manual install flow: download, unzip, replace the folder, then reload in `chrome://extensions`.
|
||||
|
||||
## Reusable Implementation
|
||||
|
||||
The current repo already has most of the flow:
|
||||
|
||||
- `src/shared/update-check.ts` parses the manifest and compares versions.
|
||||
- `src/popup/index.ts` checks for updates when the popup boots.
|
||||
- `src/popup/view.ts` renders the update status and download actions.
|
||||
- `src/background/index.ts` downloads the ZIP/PDF through `chrome.downloads`.
|
||||
- `scripts/write-latest-manifest.mjs` generates `release/latest.json`.
|
||||
|
||||
This change is mostly activation and configuration, not a rewrite.
|
||||
|
||||
## Manifest Contract
|
||||
|
||||
The public COS manifest must keep these fields:
|
||||
|
||||
- `latestVersion`
|
||||
- `minSupportedVersion`
|
||||
- `publishedAt`
|
||||
- `releaseNotes`
|
||||
- `zipUrl`
|
||||
- `guideUrl`
|
||||
|
||||
Rules:
|
||||
|
||||
- All asset URLs must be public HTTPS URLs.
|
||||
- Version comparison stays numeric dotted comparison.
|
||||
- Popup logic only needs `latestVersion` to decide whether to show the update card.
|
||||
- `minSupportedVersion` stays in the manifest for forward compatibility.
|
||||
|
||||
## COS Layout
|
||||
|
||||
Use a fixed release layout like:
|
||||
|
||||
- `https://<cos-domain>/star-chart-search-enhancer/releases/<version>/latest.json`
|
||||
- `https://<cos-domain>/star-chart-search-enhancer/releases/<version>/star-chart-search-enhancer-internal.zip`
|
||||
- `https://<cos-domain>/star-chart-search-enhancer/releases/<version>/星图增强插件-超简单安装使用指南.pdf`
|
||||
|
||||
## User Flow
|
||||
|
||||
1. User opens the popup.
|
||||
2. Popup reads the current extension version.
|
||||
3. Popup fetches COS `latest.json` with `no-store`.
|
||||
4. If `latestVersion` is not newer, show “当前已是最新版本”.
|
||||
5. If `latestVersion` is newer, show “发现新版本” plus release notes.
|
||||
6. User clicks:
|
||||
- `下载更新包` for the ZIP
|
||||
- `下载使用说明` for the PDF
|
||||
7. Popup shows the manual upgrade instructions after download starts.
|
||||
|
||||
## Error Handling
|
||||
|
||||
- If the manifest is missing, invalid, or unreachable, the popup should show a non-blocking update error.
|
||||
- If download fails, the popup should show a download error and keep the plugin usable.
|
||||
- Update check failures must not block auth or normal plugin behavior.
|
||||
|
||||
## Release Process
|
||||
|
||||
1. Build the release package.
|
||||
2. Package the internal ZIP.
|
||||
3. Generate `latest.json` with the real COS base URL.
|
||||
4. Upload `latest.json`, the ZIP, and the PDF to the COS folder.
|
||||
5. Replace the placeholder manifest URL in `src/shared/update-config.ts`.
|
||||
6. Rebuild and verify the popup update card.
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- Automatic in-place extension updates.
|
||||
- Auto-reload after download.
|
||||
- Star chart page update prompts.
|
||||
- Chrome Web Store publishing.
|
||||
|
||||
871
package-lock.json
generated
871
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,6 @@
|
||||
"build": "node scripts/build.mjs",
|
||||
"build:release": "BUILD_TARGET=release node scripts/build.mjs",
|
||||
"mock:protected-api": "node scripts/mock-protected-api.mjs",
|
||||
"release:tag": "node scripts/ci/release-tag.mjs",
|
||||
"package:internal": "npm run build:release && node scripts/package-release.mjs",
|
||||
"package:release": "npm run build:release && node scripts/package-release.mjs",
|
||||
"write:latest": "node scripts/write-latest-manifest.mjs",
|
||||
@ -20,7 +19,6 @@
|
||||
"license": "UNLICENSED",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.59.1",
|
||||
"cos-nodejs-sdk-v5": "^2.15.4",
|
||||
"jsdom": "^29.0.2",
|
||||
"tsup": "^8.5.1",
|
||||
"typescript": "^6.0.3",
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
{
|
||||
"guideUrl": "https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/releases/0.2.0421.2/星图增强插件-超简单安装使用指南.pdf",
|
||||
"guideUrl": "https://example.com/star-chart-search-enhancer/releases/0.2.0421.2/星图增强插件-超简单安装使用指南.pdf",
|
||||
"latestVersion": "0.2.0421.2",
|
||||
"minSupportedVersion": "0.2.0421.2",
|
||||
"publishedAt": "2026-05-25",
|
||||
"publishedAt": "2026-05-19",
|
||||
"releaseNotes": [
|
||||
"支持在插件弹窗中检查新版本",
|
||||
"支持一键下载最新版插件压缩包和使用说明"
|
||||
],
|
||||
"zipUrl": "https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/releases/0.2.0421.2/star-chart-search-enhancer-internal.zip"
|
||||
"zipUrl": "https://example.com/star-chart-search-enhancer/releases/0.2.0421.2/star-chart-search-enhancer-internal.zip"
|
||||
}
|
||||
|
||||
Binary file not shown.
@ -1,71 +0,0 @@
|
||||
import { execFile } from "node:child_process";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { promisify } from "node:util";
|
||||
|
||||
import { resolveReleaseVersion } from "../release-version.mjs";
|
||||
import { uploadReleaseAssets } from "./upload-release-assets.mjs";
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
|
||||
export async function runReleaseTagPipeline(env = process.env) {
|
||||
const projectRoot = resolveProjectRoot();
|
||||
const releaseVersion = resolveReleaseVersion(env);
|
||||
const publicBaseUrl =
|
||||
env.UPDATE_PUBLIC_BASE_URL ??
|
||||
`https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/releases/${releaseVersion}`;
|
||||
|
||||
console.log(`release version: ${releaseVersion}`);
|
||||
console.log("running build:release");
|
||||
await runNpmScript("build:release", projectRoot, {
|
||||
...env,
|
||||
EXTENSION_VERSION: releaseVersion
|
||||
});
|
||||
|
||||
console.log("running package-release");
|
||||
await runNodeScript("scripts/package-release.mjs", projectRoot, {
|
||||
...env,
|
||||
EXTENSION_VERSION: releaseVersion
|
||||
});
|
||||
|
||||
console.log("writing latest manifest");
|
||||
await runNpmScript("write:latest", projectRoot, {
|
||||
...env,
|
||||
EXTENSION_VERSION: releaseVersion,
|
||||
UPDATE_PUBLIC_BASE_URL: publicBaseUrl
|
||||
});
|
||||
|
||||
console.log("uploading release assets to COS");
|
||||
await uploadReleaseAssets({
|
||||
env: {
|
||||
...env,
|
||||
EXTENSION_VERSION: releaseVersion
|
||||
},
|
||||
projectRoot,
|
||||
releaseVersion
|
||||
});
|
||||
}
|
||||
|
||||
async function runNpmScript(scriptName, cwd, env) {
|
||||
await execFileAsync("npm", ["run", scriptName], {
|
||||
cwd,
|
||||
env,
|
||||
stdio: "inherit"
|
||||
});
|
||||
}
|
||||
|
||||
async function runNodeScript(scriptPath, cwd, env) {
|
||||
await execFileAsync("node", [scriptPath], {
|
||||
cwd,
|
||||
env,
|
||||
stdio: "inherit"
|
||||
});
|
||||
}
|
||||
|
||||
function resolveProjectRoot() {
|
||||
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
}
|
||||
|
||||
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
||||
await runReleaseTagPipeline();
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
import COS from "cos-nodejs-sdk-v5";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import path from "node:path";
|
||||
import { buildReleaseUploadTargets } from "../release-assets.mjs";
|
||||
|
||||
export async function uploadReleaseAssets(options = {}) {
|
||||
const env = options.env ?? process.env;
|
||||
const projectRoot = options.projectRoot ?? resolveProjectRoot();
|
||||
const releaseVersion = options.releaseVersion ?? env.EXTENSION_VERSION ?? env.DRONE_TAG;
|
||||
|
||||
if (!releaseVersion) {
|
||||
throw new Error("release version is required for COS upload");
|
||||
}
|
||||
|
||||
const cos = options.cosClient ?? createCosClient(env);
|
||||
const targets =
|
||||
options.targets ??
|
||||
buildReleaseUploadTargets({
|
||||
projectRoot,
|
||||
releaseVersion
|
||||
});
|
||||
|
||||
for (const target of targets) {
|
||||
const body = await readFile(target.localPath);
|
||||
await putObjectAsync(cos, {
|
||||
Bucket: getRequiredEnv(env, "COS_BUCKET"),
|
||||
Body: body,
|
||||
ContentType: getContentType(target.cosKey),
|
||||
Key: target.cosKey,
|
||||
Region: getRequiredEnv(env, "COS_REGION")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function putObjectAsync(client, params) {
|
||||
return await new Promise((resolve, reject) => {
|
||||
client.putObject(params, (error, data) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function createCosClient(env) {
|
||||
return new COS({
|
||||
SecretId: getRequiredEnv(env, "COS_SECRET_ID"),
|
||||
SecretKey: getRequiredEnv(env, "COS_SECRET_KEY")
|
||||
});
|
||||
}
|
||||
|
||||
function getContentType(key) {
|
||||
if (key.endsWith(".json")) {
|
||||
return "application/json";
|
||||
}
|
||||
|
||||
if (key.endsWith(".pdf")) {
|
||||
return "application/pdf";
|
||||
}
|
||||
|
||||
if (key.endsWith(".zip")) {
|
||||
return "application/zip";
|
||||
}
|
||||
|
||||
return "application/octet-stream";
|
||||
}
|
||||
|
||||
function getRequiredEnv(env, name) {
|
||||
const value = env[name];
|
||||
if (!value) {
|
||||
throw new Error(`${name} is required`);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
function resolveProjectRoot() {
|
||||
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
}
|
||||
@ -1,5 +1,3 @@
|
||||
import { resolveReleaseVersion } from "./release-version.mjs";
|
||||
|
||||
const sharedIcons = {
|
||||
16: "assets/icons/icon-16.png",
|
||||
32: "assets/icons/icon-32.png",
|
||||
@ -36,6 +34,7 @@ const sharedManifest = {
|
||||
manifest_version: 3,
|
||||
name: "Star Chart Search Enhancer",
|
||||
permissions: ["downloads", "identity", "storage"],
|
||||
version: "0.2.0421.2",
|
||||
web_accessible_resources: [
|
||||
{
|
||||
matches: [
|
||||
@ -73,7 +72,6 @@ export function createManifest(options = {}) {
|
||||
|
||||
return {
|
||||
...sharedManifest,
|
||||
version: resolveReleaseVersion(),
|
||||
host_permissions: hostPermissions
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
import path from "node:path";
|
||||
|
||||
export function buildReleaseUploadTargets({
|
||||
projectRoot,
|
||||
releaseVersion
|
||||
}) {
|
||||
const releaseDir = path.join(projectRoot, "release");
|
||||
const releasePrefix = "star-chart-search-enhancer";
|
||||
const releaseVersionPrefix = `${releasePrefix}/releases/${releaseVersion}`;
|
||||
|
||||
return [
|
||||
{
|
||||
cosKey: `${releasePrefix}/latest.json`,
|
||||
localPath: path.join(releaseDir, "latest.json")
|
||||
},
|
||||
{
|
||||
cosKey: `${releaseVersionPrefix}/star-chart-search-enhancer-internal.zip`,
|
||||
localPath: path.join(releaseDir, "star-chart-search-enhancer-internal.zip")
|
||||
},
|
||||
{
|
||||
cosKey: `${releaseVersionPrefix}/星图增强插件-超简单安装使用指南.pdf`,
|
||||
localPath: path.join(releaseDir, "星图增强插件-超简单安装使用指南.pdf")
|
||||
}
|
||||
];
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
const RELEASE_VERSION_PATTERN = /^\d+(?:\.\d+)*$/;
|
||||
|
||||
export function normalizeReleaseVersionTag(value) {
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const normalized = value.trim().replace(/^v/i, "");
|
||||
if (!RELEASE_VERSION_PATTERN.test(normalized)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export function resolveReleaseVersion(
|
||||
env = process.env,
|
||||
fallbackVersion = "0.2.0421.2"
|
||||
) {
|
||||
const candidates = [env.EXTENSION_VERSION, env.DRONE_TAG, fallbackVersion];
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const normalized = normalizeReleaseVersionTag(candidate);
|
||||
if (normalized) {
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("unable to resolve a valid release version");
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
export function createLatestManifest(options) {
|
||||
const publishedAt = options.publishedAt ?? new Date().toISOString().slice(0, 10);
|
||||
|
||||
return {
|
||||
guideUrl: `${options.publicBaseUrl}/星图增强插件-超简单安装使用指南.pdf`,
|
||||
latestVersion: options.latestVersion,
|
||||
minSupportedVersion: options.minSupportedVersion,
|
||||
publishedAt,
|
||||
releaseNotes: [
|
||||
"支持在插件弹窗中检查新版本",
|
||||
"支持一键下载最新版插件压缩包和使用说明"
|
||||
],
|
||||
zipUrl: `${options.publicBaseUrl}/star-chart-search-enhancer-internal.zip`
|
||||
};
|
||||
}
|
||||
@ -2,24 +2,28 @@ import { mkdir, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { createManifest } from "./manifest.mjs";
|
||||
import { createLatestManifest } from "./write-latest-manifest-data.mjs";
|
||||
import { resolveReleaseVersion } from "./release-version.mjs";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const projectRoot = path.resolve(__dirname, "..");
|
||||
const releaseDir = path.join(projectRoot, "release");
|
||||
const releaseManifest = createManifest({ target: "release" });
|
||||
const latestVersion =
|
||||
process.env.LATEST_VERSION ?? resolveReleaseVersion(process.env, releaseManifest.version);
|
||||
const latestVersion = process.env.LATEST_VERSION ?? releaseManifest.version;
|
||||
const publicBaseUrl =
|
||||
process.env.UPDATE_PUBLIC_BASE_URL ??
|
||||
`https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/releases/${latestVersion}`;
|
||||
const latestManifest = createLatestManifest({
|
||||
`https://example.com/star-chart-search-enhancer/releases/${latestVersion}`;
|
||||
|
||||
const latestManifest = {
|
||||
guideUrl: `${publicBaseUrl}/星图增强插件-超简单安装使用指南.pdf`,
|
||||
latestVersion,
|
||||
minSupportedVersion: releaseManifest.version,
|
||||
publicBaseUrl
|
||||
});
|
||||
publishedAt: new Date().toISOString().slice(0, 10),
|
||||
releaseNotes: [
|
||||
"支持在插件弹窗中检查新版本",
|
||||
"支持一键下载最新版插件压缩包和使用说明"
|
||||
],
|
||||
zipUrl: `${publicBaseUrl}/star-chart-search-enhancer-internal.zip`
|
||||
};
|
||||
|
||||
await mkdir(releaseDir, { recursive: true });
|
||||
await writeFile(
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
export const UPDATE_MANIFEST_URL =
|
||||
"https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/latest.json";
|
||||
"https://example.com/star-chart-search-enhancer/latest.json";
|
||||
|
||||
@ -66,20 +66,4 @@ describe("manifest", () => {
|
||||
"32": "assets/icons/icon-32.png"
|
||||
});
|
||||
});
|
||||
|
||||
test("uses EXTENSION_VERSION for release builds", () => {
|
||||
const previousVersion = process.env.EXTENSION_VERSION;
|
||||
process.env.EXTENSION_VERSION = "v0.0525.1";
|
||||
|
||||
try {
|
||||
const releaseManifest = createManifest({ target: "release" });
|
||||
expect(releaseManifest.version).toBe("0.0525.1");
|
||||
} finally {
|
||||
if (previousVersion === undefined) {
|
||||
delete process.env.EXTENSION_VERSION;
|
||||
} else {
|
||||
process.env.EXTENSION_VERSION = previousVersion;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
import path from "node:path";
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import { buildReleaseUploadTargets } from "../scripts/release-assets.mjs";
|
||||
|
||||
describe("release-assets", () => {
|
||||
test("maps release files to the COS object keys", () => {
|
||||
expect(
|
||||
buildReleaseUploadTargets({
|
||||
projectRoot: "/repo",
|
||||
releaseVersion: "0.0525.1"
|
||||
})
|
||||
).toEqual([
|
||||
{
|
||||
cosKey: "star-chart-search-enhancer/latest.json",
|
||||
localPath: path.join("/repo", "release", "latest.json")
|
||||
},
|
||||
{
|
||||
cosKey:
|
||||
"star-chart-search-enhancer/releases/0.0525.1/star-chart-search-enhancer-internal.zip",
|
||||
localPath: path.join("/repo", "release", "star-chart-search-enhancer-internal.zip")
|
||||
},
|
||||
{
|
||||
cosKey:
|
||||
"star-chart-search-enhancer/releases/0.0525.1/星图增强插件-超简单安装使用指南.pdf",
|
||||
localPath: path.join("/repo", "release", "星图增强插件-超简单安装使用指南.pdf")
|
||||
}
|
||||
]);
|
||||
});
|
||||
});
|
||||
@ -1,25 +0,0 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import {
|
||||
normalizeReleaseVersionTag,
|
||||
resolveReleaseVersion
|
||||
} from "../scripts/release-version.mjs";
|
||||
|
||||
describe("release-version", () => {
|
||||
test("normalizes a tag by stripping a leading v", () => {
|
||||
expect(normalizeReleaseVersionTag("v0.0525.1")).toBe("0.0525.1");
|
||||
expect(normalizeReleaseVersionTag("0.0525.1")).toBe("0.0525.1");
|
||||
});
|
||||
|
||||
test("prefers EXTENSION_VERSION over DRONE_TAG and fallback", () => {
|
||||
expect(
|
||||
resolveReleaseVersion(
|
||||
{
|
||||
DRONE_TAG: "0.0525.2",
|
||||
EXTENSION_VERSION: "v0.0525.3"
|
||||
},
|
||||
"0.2.0421.2"
|
||||
)
|
||||
).toBe("0.0525.3");
|
||||
});
|
||||
});
|
||||
@ -1,11 +0,0 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import { UPDATE_MANIFEST_URL } from "../src/shared/update-config";
|
||||
|
||||
describe("update-config", () => {
|
||||
test("points popup update checks at the COS latest manifest", () => {
|
||||
expect(UPDATE_MANIFEST_URL).toBe(
|
||||
"https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/latest.json"
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -1,29 +0,0 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import { createLatestManifest } from "../scripts/write-latest-manifest-data.mjs";
|
||||
|
||||
describe("write-latest-manifest-data", () => {
|
||||
test("builds COS asset URLs from the release base", () => {
|
||||
expect(
|
||||
createLatestManifest({
|
||||
latestVersion: "0.2.0421.2",
|
||||
minSupportedVersion: "0.2.0421.2",
|
||||
publicBaseUrl:
|
||||
"https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/releases/0.2.0421.2",
|
||||
publishedAt: "2026-05-25"
|
||||
})
|
||||
).toEqual({
|
||||
guideUrl:
|
||||
"https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/releases/0.2.0421.2/星图增强插件-超简单安装使用指南.pdf",
|
||||
latestVersion: "0.2.0421.2",
|
||||
minSupportedVersion: "0.2.0421.2",
|
||||
publishedAt: "2026-05-25",
|
||||
releaseNotes: [
|
||||
"支持在插件弹窗中检查新版本",
|
||||
"支持一键下载最新版插件压缩包和使用说明"
|
||||
],
|
||||
zipUrl:
|
||||
"https://wksgx-1343191620.cos.ap-nanjing.myqcloud.com/star-chart-search-enhancer/releases/0.2.0421.2/star-chart-search-enhancer-internal.zip"
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user