|
| 1 | +--- |
| 2 | +name: release-core |
| 3 | +description: Use when releasing mx-core server (apps/core) or @mx-space/api-client package — version bump, changelog, git tag, Docker build, GitHub Release, and Dokploy redeploy. Triggers on "发版", "release a new version", "cut a release", "bump version", "publish api-client". |
| 4 | +--- |
| 5 | + |
| 6 | +# mx-core Release Process |
| 7 | + |
| 8 | +mx-core has **two independent release pipelines** in this repo. Confirm with the user which one before doing anything. |
| 9 | + |
| 10 | +| Pipeline | Where | What ships | Triggered by | |
| 11 | +|----------|-------|------------|--------------| |
| 12 | +| **A. Server** | `apps/core` | DockerHub `innei/mx-server` + GitHub Release zip + Dokploy redeploy | git tag `v*` (set by `bump`) | |
| 13 | +| **B. api-client** | `packages/api-client` | npm package `@mx-space/api-client` | `npm publish` from local (run by `bump` after-hook) | |
| 14 | + |
| 15 | +The `bump` CLI (Innei/bump-version, also aliased as `vv`) drives both. Each `package.json` has a `bump` block defining `before` / `after` / `changelog` / `tag` / `commit_message`. |
| 16 | + |
| 17 | +## Pre-flight Checklist (apply to BOTH pipelines) |
| 18 | + |
| 19 | +- [ ] On `master`, working tree clean (`git status`) |
| 20 | +- [ ] In sync with `origin/master` (`git pull --rebase` — bump's `before` will run this anyway, but check first to spot conflicts) |
| 21 | +- [ ] `pnpm lint` passes |
| 22 | +- [ ] `pnpm typecheck` passes |
| 23 | +- [ ] `pnpm test` passes (or scoped to changed area, with the user's call) |
| 24 | +- [ ] CHANGELOG sanity-check: review unreleased commits since last tag with `git log v$(node -p "require('./apps/core/package.json').version")..HEAD --oneline` |
| 25 | +- [ ] No half-merged feature branches expected to ride this release |
| 26 | + |
| 27 | +If anything is dirty/red, **stop and confirm with the user** — do not press through. |
| 28 | + |
| 29 | +## A. Server Release (`apps/core`) |
| 30 | + |
| 31 | +### Where the bump runs |
| 32 | + |
| 33 | +The `apps/core/package.json` `bump` block: |
| 34 | + |
| 35 | +```jsonc |
| 36 | +{ |
| 37 | + "before": [ |
| 38 | + "git pull --rebase", |
| 39 | + "pnpm i", |
| 40 | + "node get-latest-admin-version.js" // syncs latest mx-admin version into package.json |
| 41 | + ], |
| 42 | + "after": [ |
| 43 | + "sh assets-push.sh" // pushes mx-admin static assets to mx-space/assets repo |
| 44 | + ], |
| 45 | + "changelog": true // updates CHANGELOG.md |
| 46 | +} |
| 47 | +``` |
| 48 | + |
| 49 | +`bump` defaults: bumps `version` in `apps/core/package.json` → updates `CHANGELOG.md` → commits as `release: vX.Y.Z` → tags `vX.Y.Z` → pushes commit + tag to `origin`. |
| 50 | + |
| 51 | +### Commands |
| 52 | + |
| 53 | +From repo root (preferred — uses the workspace shortcut): |
| 54 | + |
| 55 | +```bash |
| 56 | +# Preview first (no write, no commit, no push) |
| 57 | +pnpm -C apps/core exec bump --dry-run patch |
| 58 | + |
| 59 | +# Then actually run it |
| 60 | +pnpm publish:core # equivalent to: cd apps/core && npm run publish → bump |
| 61 | +``` |
| 62 | + |
| 63 | +`bump` is interactive if you don't pass a version type. Pass one to skip the prompt: |
| 64 | + |
| 65 | +| Type | Effect | When | |
| 66 | +|------|--------|------| |
| 67 | +| `patch` | `11.4.7 → 11.4.8` | bug fixes only | |
| 68 | +| `minor` | `11.4.7 → 11.5.0` | backwards-compatible features | |
| 69 | +| `major` | `11.4.7 → 12.0.0` | breaking change (rare; flag to user) | |
| 70 | +| `prerelease` / `alpha` | `11.4.7 → 11.4.8-0` → `-1` → … | RC / canary builds | |
| 71 | + |
| 72 | +### What CI does after the tag is pushed |
| 73 | + |
| 74 | +`.github/workflows/release.yml` triggers on `push: tags: v*`: |
| 75 | + |
| 76 | +1. **quality** — `pnpm lint` + `pnpm typecheck` |
| 77 | +2. **build** — `pnpm bundle` → `bash scripts/workflow/test-server.sh` → `apps/core/zip-asset.sh` → uploads `release-linux.zip` as a GitHub Release asset → runs `npx changelogithub` to populate the release notes |
| 78 | +3. **docker** (matrix: `linux/amd64` on `ubuntu-latest`, `linux/arm64` on `ubuntu-24.04-arm`) — builds, runs `bash ./scripts/workflow/test-docker.sh`, pushes by digest to DockerHub `innei/mx-server` |
| 79 | +4. **merge** — combines digests into a single multi-arch manifest and tags it `latest`, `vX.Y.Z`, `X.Y`, `X`, plus the sha |
| 80 | +5. **dokploy** — POSTs to `secrets.DOKPLOY_WEBHOOK_URL` to redeploy production (silently skipped if the secret is unset) |
| 81 | + |
| 82 | +### Common follow-ups |
| 83 | + |
| 84 | +- After CI is green, glance at the GitHub Release page to confirm the changelog rendered well and the zip asset attached. |
| 85 | +- If Dokploy redeploy is the prod path, verify the running version on the server (e.g. `docker ps`/`/api/v2/health` or wherever the deployment exposes it). |
| 86 | + |
| 87 | +## B. api-client Release (`packages/api-client`) |
| 88 | + |
| 89 | +This package ships to npm, **not** through the tag pipeline. It uses its own `bump` block: |
| 90 | + |
| 91 | +```jsonc |
| 92 | +{ |
| 93 | + "before": ["git pull --rebase", "pnpm i", "npm run package"], |
| 94 | + "after": ["npm publish --access=public"], |
| 95 | + "tag": false, |
| 96 | + "commit_message": "chore(release): bump @mx-space/api-client to v${NEW_VERSION}" |
| 97 | +} |
| 98 | +``` |
| 99 | + |
| 100 | +Notes: |
| 101 | + |
| 102 | +- **No git tag** — the bump only commits + pushes a `chore(release): …` commit; there is no `v*` tag and the `release.yml` pipeline does NOT fire. |
| 103 | +- The actual publish happens locally on whoever runs `bump` — they need an npm login with publish rights to `@mx-space/api-client`. |
| 104 | +- `.github/workflows/api-client.yml` runs `pnpm test && pnpm run package` on every PR / push touching `packages/api-client/**`. It validates, but does **not** publish. |
| 105 | + |
| 106 | +### Commands |
| 107 | + |
| 108 | +```bash |
| 109 | +cd packages/api-client |
| 110 | + |
| 111 | +# Preview |
| 112 | +pnpm exec bump --dry-run patch |
| 113 | + |
| 114 | +# Real run |
| 115 | +pnpm exec bump patch |
| 116 | +# or pnpm exec bump minor / major / prerelease |
| 117 | +``` |
| 118 | + |
| 119 | +### Yohaku consumer reminder |
| 120 | + |
| 121 | +`@mx-space/api-client` is consumed by Yohaku web (`apps/web/package.json`) and admin-vue3 by pinned version. After publishing, if the bump introduced behavior the consumer needs, also bump the pin in those repos — but do NOT do that as part of this skill unless the user asks. |
| 122 | + |
| 123 | +## Dry-run is cheap, use it |
| 124 | + |
| 125 | +`bump --dry-run <type>` prints exactly what would happen (commands, version, commit message, tag) without touching anything. **Always run it first** if you're unsure which version segment to bump or whether the working tree is clean enough. |
| 126 | + |
| 127 | +## Rollback / recovery |
| 128 | + |
| 129 | +| Situation | Action | |
| 130 | +|-----------|--------| |
| 131 | +| `bump` failed mid-run, no tag pushed yet | `git status` → `git reset --hard HEAD` (after confirming nothing else was uncommitted) → fix → re-run. Confirm with user before resetting. | |
| 132 | +| Tag pushed but CI failed at quality/build | Fix forward with a follow-up commit + new tag (`bump patch`). Don't try to delete the published tag. | |
| 133 | +| Tag pushed, Docker built & published, but bug is critical | Cut a new patch release with the fix. Do **not** re-tag the same version. | |
| 134 | +| api-client `npm publish` failed after commit pushed | `npm publish --access=public` manually from `packages/api-client` once the issue is resolved. The commit is already on master. | |
| 135 | +| Wrong version published to npm | npm allows `npm unpublish` only within 72h and only if no one depends on it. Usually faster to publish a corrected next version. | |
| 136 | + |
| 137 | +Never force-push to `master` or delete a published tag without user explicit approval — release tags are referenced by Docker manifests and changelog tooling. |
| 138 | + |
| 139 | +## Red flags — STOP and confirm with user |
| 140 | + |
| 141 | +- Working tree dirty before bump |
| 142 | +- `pnpm typecheck` or `pnpm lint` failing |
| 143 | +- Asked to bump `major` (breaking change — confirm scope) |
| 144 | +- Asked to publish from a non-`master` branch |
| 145 | +- `DOKPLOY_WEBHOOK_URL` secret missing yet user expects auto-redeploy |
| 146 | +- Two pipelines being mixed up (e.g. tagging `v*` for an api-client-only change) |
| 147 | + |
| 148 | +## File reference |
| 149 | + |
| 150 | +- `apps/core/package.json` — `bump` config for server |
| 151 | +- `packages/api-client/package.json` — `bump` config for npm package |
| 152 | +- `apps/core/get-latest-admin-version.js` — pulls latest mx-admin release tag and writes it into `package.json` `dashboard.version` |
| 153 | +- `apps/core/assets-push.sh` — force-pushes `assets/` submodule contents to `mx-space/assets` |
| 154 | +- `.github/workflows/release.yml` — server tag → Docker + GitHub Release + Dokploy |
| 155 | +- `.github/workflows/api-client.yml` — api-client CI (test/build only, no publish) |
| 156 | +- `scripts/workflow/test-server.sh` / `test-docker.sh` — smoke tests CI runs against the bundle and image |
0 commit comments