Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,32 @@ jobs:
- name: Verify rendering (non-blocking)
continue-on-error: true
run: pnpm wcli:verify

build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
with:
persist-credentials: false
ref: ${{ github.event.pull_request.head.sha || github.sha }}

- name: Set up pnpm
uses: pnpm/setup@v3
with:
version: 12.14.0
runtime: node@22
cache: true
install: false

- name: Install dependencies
run: pnpm install --frozen-lockfile

# Build the shipped artifacts so a broken bundle is caught on a PR, not
# after it lands. `pnpm web build` runs vite build + type-check (the same
# command deploy uses); the CLI build is the fork's published bundle.
- name: Build web app
run: pnpm web build

- name: Build md-web-cli
run: pnpm --filter @dane.dai/md-web-cli build
19 changes: 15 additions & 4 deletions .github/workflows/sync-upstream.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ name: Sync upstream doocs/md
# the default token do not trigger workflows. The verification that already
# passed here, recorded in the PR body, is what the human merges on.
#
# The sync PR is merged with a **squash** (the only merge method main allows
# per docs/adr/0004-pr-first-landing.md). Squashing collapses the upstream
# commit range, so upstream/main's commits stop being ancestors of main and
# the next sync re-applies them from the last common ancestor before fork
# divergence; this is a known, accepted trade-off for now. Landing as a merge
# commit to preserve ancestry is tracked separately in issue #34.
#
# Failure modes (all surface as job failure → GitHub's built-in Actions
# notification; no PR is opened, nothing is pushed):
# 1. Merge conflict — "Merge upstream main" step fails.
Expand Down Expand Up @@ -130,6 +137,14 @@ jobs:
if: steps.upstream.outputs.new == 'true'
run: pnpm exec playwright install --with-deps chromium

# Unit tests run before the verify gate so a red gate (a known state per
# docs/adr/0003-single-verify-gate.md) never hides a CLI test regression —
# a test failure is cheap and reports even when byte-exact verification
# is not yet green.
- name: Run package unit tests
if: steps.upstream.outputs.new == 'true'
run: pnpm --filter @dane.dai/md-web-cli test

- name: Verify rendering (wcli:verify)
id: verify
# Failure here = failure mode 2 or 3: the build inside the gate or the
Expand All @@ -150,10 +165,6 @@ jobs:
fi
echo "result=PASSED" >> "$GITHUB_OUTPUT"

- name: Run package unit tests
if: steps.upstream.outputs.new == 'true'
run: pnpm --filter @dane.dai/md-web-cli test

- name: Push sync branch
# force-with-lease: a second dispatch while the PR is open re-creates
# the branch from the latest main and force-updates it — the open PR
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ Web 主应用与部分浏览器扩展 UI 支持 **zh-CN**、**zh-TW**、**en-US*
- **提交信息 / PR 标题:** 遵循 Conventional Commits(`feat`、`fix`、`docs`、`style`、`refactor`、`perf`、`test`、`build`、`chore`),**一律使用英文**(见 `CONTRIBUTING.md`)
- **分支命名:** `feat/description`、`fix/description`、`docs/description`;其他类型用 `<type>/`
- **PR 说明:** 按 [`.github/pull_request_template.md`](./.github/pull_request_template.md) 填写;无关联 Issue 时不要写 Related Issue 占位符
- **Fork-local 工作流:** 本 fork 自有改动(`md-web-cli` 包、其发布工作流与 fixture)直接推 `main`,不开 PR、不走上游 review;上游更新以 merge commit 进入 `main`。详见 [ADR-0001](./docs/adr/0001-fork-local-workflow.md)
- **PR-first 落地:** 所有改动(含 `md-web-cli` 包、其发布工作流与 fixture)一律通过 PR 进入 `main`,禁止直推。上游更新经 `sync-upstream.yml` 的 sync PR 以 squash 合入(merge commit 方案见 #34)。详见 [ADR-0004](./docs/adr/0004-pr-first-landing.md)

## Skills

Expand Down
8 changes: 4 additions & 4 deletions GLOSSARY.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# doocs/md

A WeChat Markdown editor that renders Markdown into article HTML for the WeChat official account editor. This glossary covers the vocabulary of the fork-local headless rendering work.
A WeChat Markdown editor that renders Markdown into article HTML for the WeChat official account editor. This glossary covers the vocabulary of the fork's headless rendering work.

## Language

Expand Down Expand Up @@ -36,6 +36,6 @@ _Avoid_: snapshot gate, fidelity check
A marker the renderer leaves where asynchronous hydration has not completed — diagram loading text, a formula placeholder, an unregistered-language marker. The CLI treats any occurrence as a hard failure.
_Avoid_: loading state, stub, TODO marker

**Fork-local change**:
A change that exists only in this fork and is never offered upstream.
_Avoid_: local patch, downstream change
**Fork-local package**:
A package that exists only in this fork, such as `@dane.dai/md-web-cli` and its release workflows and fixtures. It is ordinary repository content: changes land through pull requests like everything else.
_Avoid_: fork patch, downstream package
3 changes: 3 additions & 0 deletions docs/adr/0001-fork-local-workflow.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Fork-local development workflow

> **Status: superseded by [0004-pr-first-landing.md](./0004-pr-first-landing.md).**
> Every change now lands on `main` through a pull request; there is no direct-push lane.

This fork carries changes that are deliberately never offered to `doocs/md` upstream: a headless rendering CLI, its two release workflows, and its fixtures. We therefore develop fork-local: our own commits go straight to `main` with no pull request and no review cycle, while upstream arrives through a sync pull request — created by the sync workflow, verified there before it is opened, and merged by a human after reviewing the diff. Upstream is merged into ours rather than rebased.

## Consequences
Expand Down
16 changes: 16 additions & 0 deletions docs/adr/0004-pr-first-landing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# PR-first landing for `main`

Every change to this fork's `main` enters through a pull request; direct pushes to `main` are disallowed (except the documented `pull_request` bypass for the repository admin, which exists as an escape hatch for when CI is broken, not as the normal path). This supersedes ADR-0001 in full: there is no "fork-local changes go straight to `main`" lane and no separate review-free path.

Upstream `doocs/md` changes still arrive through a sync pull request created by `sync-upstream.yml`. Today that PR is merged with a **squash** (matching the single merge method `main` allows); the option of landing it as a merge commit to preserve upstream ancestry is tracked separately in issue #34 and explicitly deferred.

## Status

Supersedes: [0001-fork-local-workflow.md](./0001-fork-local-workflow.md)

## Consequences

- Every push to `main` is still a release candidate, but now every such push is the result of a reviewed pull request; the human review replaces the review latency that the direct-push lane previously skipped.
- The ruleset `Protect main (PR + status checks)` is the enforcement point: `allowed_merge_methods` is `["squash"]`, required status checks are `lint`, `type-check`, `test`, `build`, and the admin bypass is `pull_request` mode.
- The sync PR is created with `GITHUB_TOKEN`, so it carries no checks; its landing relies on the admin `pull_request` bypass after the human reviews the diff. Verification evidence is the `verify` and unit-test output recorded in the sync workflow, not a check on the PR.
- `md-web-cli` and the other fork-owned packages are ordinary repository content now: they change through PRs like everything else.
Loading