Compare commits
4 Commits
e1cf2970da
...
8aca116949
| Author | SHA1 | Date | |
|---|---|---|---|
| 8aca116949 | |||
| 3a80ef9859 | |||
| 1a7b025aee | |||
| b3b916c6bc |
@ -104,7 +104,7 @@ npm run write:latest
|
||||
2. 打开 `chrome://extensions`
|
||||
3. 打开右上角 `开发者模式`
|
||||
4. 点击 `加载已解压的扩展程序`
|
||||
5. 选择解压后的插件文件夹
|
||||
5. 选择解压后的 `dist/` 文件夹
|
||||
|
||||
安装后请确认扩展 ID 是:
|
||||
|
||||
|
||||
@ -73,7 +73,7 @@ The pipeline uses the tag as the release version. Recommended format: `0.MMDD.N`
|
||||
2. Open `chrome://extensions`.
|
||||
3. Enable developer mode.
|
||||
4. Click `Load unpacked`.
|
||||
5. Select the unzipped folder.
|
||||
5. Select the unzipped `dist/` folder.
|
||||
6. Confirm the extension ID is `pkjopdibdnomhogjheclhnknmejccffg`.
|
||||
|
||||
## Notes
|
||||
|
||||
188
docs/superpowers/plans/2026-05-25-unified-dist-distribution.md
Normal file
188
docs/superpowers/plans/2026-05-25-unified-dist-distribution.md
Normal file
@ -0,0 +1,188 @@
|
||||
# Unified Dist Distribution 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:** Make first-time install, Git-based install, ZIP-based install, and later updates all use the same unpacked extension directory named `dist/`.
|
||||
|
||||
**Architecture:** Standardize the extension output path through one shared build-path helper, then make ZIP packaging wrap that exact `dist/` directory, and finally update all teammate-facing docs to reference only that path. The release pipeline keeps its existing behavior, but the user-facing artifact shape becomes stable and singular.
|
||||
|
||||
**Tech Stack:** TypeScript, Node.js ESM scripts, Chrome MV3 extension packaging, Vitest
|
||||
|
||||
---
|
||||
|
||||
## File Map
|
||||
|
||||
- Create: `scripts/build-output-path.mjs`
|
||||
- Single source of truth for the unpacked extension output path.
|
||||
- Modify: `scripts/build.mjs`
|
||||
- Write release builds to `dist/`.
|
||||
- Modify: `scripts/package-release.mjs`
|
||||
- Package the shared `dist/` output instead of any alternate directory.
|
||||
- Modify: `scripts/package-release-archive.mjs`
|
||||
- Ensure ZIP output preserves a top-level `dist/` folder.
|
||||
- Modify: `tests/package-release-archive.test.ts`
|
||||
- Verify ZIP layout unpacks as `dist/...`.
|
||||
- Create: `tests/build-output-path.test.ts`
|
||||
- Verify the shared helper resolves `dist/`.
|
||||
- Modify: `playwright.config.js`
|
||||
- Load the extension from `dist/`.
|
||||
- Modify: `e2e-tests/extension-load.spec.js`
|
||||
- Verify files under `dist/`.
|
||||
- Modify: `README.md`
|
||||
- Remove `dist-release` references and describe `dist/` as the only unpacked directory.
|
||||
- Modify: `docs/internal-extension-distribution.md`
|
||||
- Align the release flow language with `dist/`.
|
||||
- Modify: `docs/【给同事】从Git下载使用说明.md`
|
||||
- Instruct coworkers to load `dist/`.
|
||||
- Modify: `.gitignore`
|
||||
- Remove obsolete `dist-release/` ignore entry if no longer needed.
|
||||
- Delete tracked directory: `dist-release/`
|
||||
- Remove the confusing second unpacked extension directory from the repo.
|
||||
|
||||
### Task 1: Lock the single output path in tests
|
||||
|
||||
**Files:**
|
||||
- Create: `tests/build-output-path.test.ts`
|
||||
- Modify: `tests/package-release-archive.test.ts`
|
||||
|
||||
- [ ] **Step 1: Write the failing helper test**
|
||||
|
||||
Create a small test asserting both development and release builds resolve to:
|
||||
|
||||
```ts
|
||||
path.join("/repo", "dist")
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Write the failing ZIP layout assertion**
|
||||
|
||||
Update the archive test so it expects:
|
||||
|
||||
```ts
|
||||
"dist/hello.txt"
|
||||
```
|
||||
|
||||
not a flat file list or any alternate top-level folder.
|
||||
|
||||
- [ ] **Step 3: Run focused tests**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm test -- tests/build-output-path.test.ts tests/package-release-archive.test.ts
|
||||
```
|
||||
|
||||
Expected: FAIL until the shared path helper and ZIP layout are implemented.
|
||||
|
||||
### Task 2: Standardize build and package scripts
|
||||
|
||||
**Files:**
|
||||
- Create: `scripts/build-output-path.mjs`
|
||||
- Modify: `scripts/build.mjs`
|
||||
- Modify: `scripts/package-release.mjs`
|
||||
- Modify: `scripts/package-release-archive.mjs`
|
||||
|
||||
- [ ] **Step 1: Implement the shared output-path helper**
|
||||
|
||||
Add `resolveExtensionBuildDir(projectRoot, buildTarget)` and return `dist/` for both release and development flows.
|
||||
|
||||
- [ ] **Step 2: Update the build script**
|
||||
|
||||
Replace any hard-coded directory switching logic so the release build writes into `dist/`.
|
||||
|
||||
- [ ] **Step 3: Update the package script**
|
||||
|
||||
Point ZIP packaging at the same `dist/` directory.
|
||||
|
||||
- [ ] **Step 4: Keep ZIP layout stable**
|
||||
|
||||
Ensure the archive helper stores files under a top-level `dist/` directory inside the ZIP.
|
||||
|
||||
- [ ] **Step 5: Verify**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm test -- tests/build-output-path.test.ts tests/package-release-archive.test.ts
|
||||
npm run build:release
|
||||
npm run package:internal
|
||||
```
|
||||
|
||||
Expected: PASS, and the ZIP should unpack as `dist/...`.
|
||||
|
||||
### Task 3: Remove `dist-release` from tooling and docs
|
||||
|
||||
**Files:**
|
||||
- Modify: `playwright.config.js`
|
||||
- Modify: `e2e-tests/extension-load.spec.js`
|
||||
- Modify: `README.md`
|
||||
- Modify: `docs/internal-extension-distribution.md`
|
||||
- Modify: `docs/【给同事】从Git下载使用说明.md`
|
||||
- Modify: `.gitignore`
|
||||
- Delete tracked directory: `dist-release/`
|
||||
|
||||
- [ ] **Step 1: Update tool references**
|
||||
|
||||
Point Playwright and debug paths at `dist/`.
|
||||
|
||||
- [ ] **Step 2: Update teammate docs**
|
||||
|
||||
Make every install/update instruction reference only `dist/`.
|
||||
|
||||
- [ ] **Step 3: Remove the obsolete tracked directory**
|
||||
|
||||
Delete the committed `dist-release/` tree so future contributors cannot mistake it for the live extension directory.
|
||||
|
||||
- [ ] **Step 4: Verify references**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
rg -n "dist-release" README.md docs package.json scripts e2e-tests playwright.config.js src tests .gitignore
|
||||
```
|
||||
|
||||
Expected: no remaining user-facing `dist-release` references.
|
||||
|
||||
### Task 4: Final verification
|
||||
|
||||
**Files:**
|
||||
- Modify any of the above only if fixes are required
|
||||
|
||||
- [ ] **Step 1: Run targeted tests**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm test -- tests/build-output-path.test.ts tests/package-release-archive.test.ts tests/manifest.test.ts
|
||||
```
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 2: Rebuild and inspect the artifact**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm run build:release
|
||||
npm run package:internal
|
||||
unzip -l release/star-chart-search-enhancer-internal.zip | sed -n '1,20p'
|
||||
```
|
||||
|
||||
Expected: the archive contents start with `dist/...`.
|
||||
|
||||
- [ ] **Step 3: Full verification**
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
Expected: PASS, or if unrelated pre-existing failures remain, capture them explicitly before completion.
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add scripts/build-output-path.mjs scripts/build.mjs scripts/package-release.mjs scripts/package-release-archive.mjs tests/build-output-path.test.ts tests/package-release-archive.test.ts README.md docs/internal-extension-distribution.md docs/【给同事】从Git下载使用说明.md playwright.config.js e2e-tests/extension-load.spec.js .gitignore
|
||||
git commit -m "chore: unify extension distribution around dist"
|
||||
```
|
||||
|
||||
@ -0,0 +1,122 @@
|
||||
# Unified Dist Distribution Design
|
||||
|
||||
## Goal
|
||||
|
||||
Make first-time installation and later updates use the exact same extension directory structure so coworkers never need to learn different paths or loading rules.
|
||||
|
||||
## Confirmed Direction
|
||||
|
||||
- The only user-facing unpacked extension directory should be `dist/`.
|
||||
- First install and later update must produce the same directory name and shape.
|
||||
- Coworkers should always load the same directory in `chrome://extensions`.
|
||||
|
||||
## Problem
|
||||
|
||||
The current delivery flow has created multiple mental models:
|
||||
|
||||
- sometimes coworkers are told to load `dist-release/`
|
||||
- sometimes the ZIP extracts to a differently named top-level folder
|
||||
- sometimes Git-based installation and ZIP-based installation do not look identical
|
||||
|
||||
This is not user-friendly and increases support cost.
|
||||
|
||||
## Scope
|
||||
|
||||
This change standardizes the user-facing extension directory across:
|
||||
|
||||
- local release builds
|
||||
- ZIP packaging
|
||||
- Git-based teammate installation
|
||||
- later update downloads
|
||||
- installation and update documentation
|
||||
|
||||
This change does not alter:
|
||||
|
||||
- extension runtime behavior
|
||||
- update-check logic itself
|
||||
- popup auth flow
|
||||
- COS manifest format
|
||||
|
||||
## Distribution Rule
|
||||
|
||||
There must be exactly one user-facing extension directory:
|
||||
|
||||
- `dist/`
|
||||
|
||||
This rule must hold in all paths:
|
||||
|
||||
1. Git install
|
||||
- teammate runs the release build
|
||||
- resulting unpacked extension directory is `dist/`
|
||||
2. ZIP install
|
||||
- teammate unzips the package
|
||||
- resulting top-level extension directory is `dist/`
|
||||
3. ZIP update
|
||||
- teammate downloads the newer ZIP
|
||||
- unzip result is also `dist/`
|
||||
- teammate replaces the previous `dist/`
|
||||
|
||||
## Packaging Rule
|
||||
|
||||
The release ZIP should unpack into a single top-level folder named `dist/`.
|
||||
|
||||
Expected unpack result:
|
||||
|
||||
- `dist/manifest.json`
|
||||
- `dist/background/`
|
||||
- `dist/content/`
|
||||
- `dist/popup/`
|
||||
- `dist/assets/`
|
||||
|
||||
The ZIP must not unpack as:
|
||||
|
||||
- a flat file list
|
||||
- `dist-release/`
|
||||
- `star-chart-search-enhancer-internal/`
|
||||
- any other user-facing top-level folder name
|
||||
|
||||
## Build Rule
|
||||
|
||||
Release builds should write the unpacked extension directly to `dist/`.
|
||||
|
||||
There should not be a second extension build directory that teammates might mistake as the correct one.
|
||||
|
||||
If internal scripts need a concept of “release build,” that should be represented by:
|
||||
|
||||
- environment/config
|
||||
- release manifest values
|
||||
- packaging flow
|
||||
|
||||
but not by exposing a second unpacked directory name to users.
|
||||
|
||||
## Documentation Rule
|
||||
|
||||
All teammate-facing docs must say the same thing:
|
||||
|
||||
- first install: load `dist/`
|
||||
- later update: replace `dist/` and reload
|
||||
|
||||
No user-facing doc should mention `dist-release/`.
|
||||
|
||||
## CI / Release Rule
|
||||
|
||||
Drone and local release scripts must publish only one ZIP layout:
|
||||
|
||||
- unzip result is `dist/`
|
||||
|
||||
The release flow must not generate a user ZIP whose folder layout differs from the Git-based install path.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- `npm run build:release` writes the unpacked extension to `dist/`
|
||||
- release ZIP unpacks into a top-level `dist/` folder
|
||||
- first install and later update ZIPs unpack to the same structure
|
||||
- coworker docs consistently reference `dist/`
|
||||
- repository no longer contains a second tracked unpacked extension directory that conflicts with `dist/`
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- changing extension features
|
||||
- changing the update notification UX
|
||||
- switching away from unpacked-extension installation
|
||||
- Chrome Web Store or enterprise force-install deployment
|
||||
@ -18,9 +18,9 @@
|
||||
|
||||
1. 在桌面上找到这个压缩包
|
||||
2. **右键** → 选择"解压到当前文件夹"(或"Extract Here")
|
||||
3. 会多出一个文件夹,名字类似 `star-chart-search-enhancer-internal`
|
||||
3. 会多出一个文件夹,名字是 `dist`
|
||||
|
||||
⚠️ **重要**:这个文件夹要一直放在桌面,不要删、不要改名
|
||||
⚠️ **重要**:这个 `dist` 文件夹要一直放在桌面,不要删、不要改名
|
||||
|
||||
---
|
||||
|
||||
@ -37,9 +37,9 @@
|
||||
|
||||
4. 点击左上角出现的 **"加载已解压的扩展程序"**
|
||||
|
||||
5. 选择刚才解压出来的插件文件夹
|
||||
5. 选择刚才解压出来的 `dist` 文件夹
|
||||
|
||||
⚠️ **重要**:如果文件夹里能看到 `manifest.json`、`content`、`background`、`popup` 这些文件和文件夹,说明选对了。
|
||||
⚠️ **重要**:如果 `dist` 文件夹里能看到 `manifest.json`、`content`、`background`、`popup` 这些文件和文件夹,说明选对了。
|
||||
|
||||
6. 看到绿色的插件卡片出现,就装好了!
|
||||
|
||||
@ -122,7 +122,7 @@ https://xingtu.cn/ad/creator/market
|
||||
- 解压下载到的新版本 zip
|
||||
- 打开 `chrome://extensions`
|
||||
- 找到 `Star Chart Search Enhancer`
|
||||
- 点击 **"重新加载"**,或重新选择解压后的新插件文件夹
|
||||
- 点击 **"重新加载"**,或重新选择解压后的 `dist` 文件夹
|
||||
|
||||
---
|
||||
|
||||
@ -138,7 +138,7 @@ https://xingtu.cn/ad/creator/market
|
||||
⚠️ **如果重新加载后还是旧版本**:
|
||||
- 先点击插件卡片的 **"移除"** 删除旧版本
|
||||
- 然后重新点击 **"加载已解压的扩展程序"**
|
||||
- 再次选择新解压出来的插件文件夹
|
||||
- 再次选择新解压出来的 `dist` 文件夹
|
||||
|
||||
---
|
||||
|
||||
|
||||
Binary file not shown.
@ -6,7 +6,7 @@ import yazl from "yazl";
|
||||
|
||||
export async function createReleaseArchive({
|
||||
archivePath,
|
||||
rootDirName = "star-chart-search-enhancer-internal",
|
||||
rootDirName = "dist",
|
||||
sourceDir
|
||||
}) {
|
||||
const zip = new yazl.ZipFile();
|
||||
|
||||
@ -6,7 +6,7 @@ import { describe, expect, test } from "vitest";
|
||||
import { createReleaseArchive } from "../scripts/package-release-archive.mjs";
|
||||
|
||||
describe("package-release-archive", () => {
|
||||
test("creates a zip archive with a top-level release folder", async () => {
|
||||
test("creates a zip archive with a top-level dist folder", async () => {
|
||||
const tempDir = await mkdtemp(path.join(os.tmpdir(), "release-archive-"));
|
||||
const sourceDir = path.join(tempDir, "source");
|
||||
const archivePath = path.join(tempDir, "archive.zip");
|
||||
@ -21,8 +21,6 @@ describe("package-release-archive", () => {
|
||||
|
||||
const archive = await readFile(archivePath);
|
||||
expect(archive.byteLength).toBeGreaterThan(0);
|
||||
expect(archive.toString("utf8")).toContain(
|
||||
"star-chart-search-enhancer-internal/hello.txt"
|
||||
);
|
||||
expect(archive.toString("utf8")).toContain("dist/hello.txt");
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user