Skip to main content

releasing

Shipping weft: merging into main through a PR, what the release workflow publishes, the record tags that decide which stores publish, and the store rules that have actually bitten us. Load before merging to main, bumping an extension version, or debugging a red publish job.

Quellinformationen

Repository
WeaveMindAI/weft
Letzte Quellaktivität
10. Oktober 2026 um 10:33
Erkannte Sprache von SKILL.md
Englisch
Sterne
2.002
Forks
219

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
releasing
description
Shipping weft: merging into main through a PR, what the release workflow publishes, the record tags that decide which stores publish, and the store rules that have actually bitten us. Load before merging to main, bumping an extension version, or debugging a red publish job.
How a change gets from the working tree to the stores, and the traps that cost a round trip the last time each one was hit. ## The path `main` is the branch that ships. `poc` carries the retired proof of concept and nothing merges there. Work lands on a feature branch, goes into `main` through a PR, and the merge is what publishes. 1. Commit on the feature branch (only when the [user] says so). If the change touches `extension-vscode/`, `packages/weft-graph/`, `packages/weft-syntax/` or `packages/weft-connect/` (the VS Code extension ships all four), bump `extension-vscode`; if it touches `extension-browser/` or `packages/weft-connect/` (its connections page is built on the connect library), bump that one too. Bump IN THE SAME PR (`pnpm version patch --no-git-tag-version` in the package directory): a merge without a bump publishes nothing to the stores. The `extension versions bumped` CI check refuses a PR that forgot; `scripts/check-extension-bump.sh origin/main` is the same check locally. In the same PR, write what changed into `CHANGELOG.md`, for the people who update their weft: what they will notice, what they have to do (a `./setup.sh` that asks, a command to run again, a setting that moved), and anything breaking first. Each release gets its own section, newest first, headed with its date and its version, the VS Code extension's version the PR bumped to (`## 2026-10-09 (0.2.267)`); a release that bumps no extension names its merge's short commit instead. Work not merged yet stays under `## Unreleased`, and the PR that ships it renames that heading. Write it plainly, for a person reading it before they run `./setup.sh`, never as a list of commits. 2. `gh pr create --base main --head <branch>`. 3. Never `--auto`. Wait for every check to finish (`gh pr checks <n> --watch`), then read what the PR collected besides the checks before merging: - the code-scanning alerts it opened (CodeQL comments on the diff): `gh api "repos/WeaveMindAI/weft/code-scanning/alerts?state=open&ref=refs/pull/<n>/merge"`; - any review comment (`gh pr view <n> --comments`). Fix each real one on the branch and push, which runs the checks again. Dismiss a false positive only with the [user]'s say-so, with the reason in the dismissal. Only when every check is green and nothing is left open, `gh pr merge <n> --merge`. Earlier PRs into `main` are merge commits, so match that. 4. The push to `main` runs `release.yml`, which builds the images, the CLI binaries, the `.vsix` and the browser zips, updates the rolling `latest` release, and then publishes to each store. CI runs on `pull_request` into `main` only. Every check is its own job, so they run side by side. The main ruleset requires four names: `extension versions bumped` (PRs only), `cargo test --features db-tests`, and two gates that are green only when every job under them is: `cargo test + clippy` (nextest, doc tests, clippy, the parse-only build, the examples, the install's `terraform validate`) and `graph + editor` (each JS package, the VS Code extension, the WhatsApp bridge, the browser extension). The docs book builds beside them. On `main`, `release.yml` runs the same suite as its gate, and starts the builds (binaries, .vsix, browser zips) beside it; only what publishes waits for the gate. ## Before every push to a PR, run what the PR runs Before you push a commit to a branch with a PR (the first push that opens it, and every fix pushed after), run locally everything the PR's checks run, not only the tests your change reaches. This is the one place the [test scope] does not apply: a red PR costs a full CI round trip, and twice a PR has gone red on a test in a crate the change only touched indirectly. Background the run, and fix everything before the push, not after. Locally the cargo commands go one after another (they share one build directory, which cargo locks, and overlapping cargo runs have crashed this machine); the JS checks and the docs build run beside them. The PR runs `.github/workflows/ci.yml` and `.github/workflows/docs.yml`; read them for the current list. At the time of writing: - `scripts/check-extension-bump.sh origin/main` - `cargo nextest run --workspace --locked` - `cargo test --workspace --locked --doc` - `cargo clippy --workspace --all-targets --locked -- -D warnings` - `cargo check -p weft-compiler --no-default-features --locked` - `scripts/validate-examples.sh` - the install's Terraform, validated in a container (no Terraform needed here, nothing written to the checkout): `docker run --rm -v "$PWD/deploy/terraform/gcp:/w:ro" --entrypoint sh hashicorp/terraform:latest -c 'cp -r /w /tmp/w && cd /tmp/w && terraform init -backend=false -input=false >/dev/null && terraform validate'` - `scripts/run-db-tests.sh` (every crate, no filter) - `pnpm -C packages/weft-graph test`, `pnpm -C packages/weft-connect test`, `pnpm -C packages/weft-syntax test`, `pnpm -C extension-vscode test`, `pnpm -C extension-vscode run compile` - `node --test catalog/bailey/bridge/images/bridge/src/*.test.js` - `pnpm -C extension-browser exec tsc --noEmit`, `pnpm -C extension-browser check` - the docs build: `cd docs && mdbook-mermaid install . && mdbook build` Clippy on the crates you edited is not the same as the workspace line above, and has sent a PR red on a lint in a crate the change only touched indirectly. `scripts/validate-examples.sh` compiles every example. It fails on ERRORS only, so a warning is advice an example may carry. If an example starts failing after a language change, the question is whether the example is wrong or the diagnostic is, and the answer has been "the diagnostic" as often as not. ## The record tags decide what publishes Each successful publish is recorded as a git tag, `<prefix>-<store>-v<version>`: `vscode-marketplace-v0.2.239`, `browser-firefox-v1.0.62`. Before publishing, the workflow asks `git ls-remote origin refs/tags/<tag>` per store; a store whose tag exists gets no job at all. So **a store publishes exactly when its tag is missing**, and the version in the workspace's `package.json` is what the tag names. Without a version bump, a release republishes nothing. Two things follow, and both have bitten: **Bumping is the release gesture.** `extension-vscode/package.json` and `extension-browser/package.json` carry their own versions. `./setup.sh --bump` (with `--vscode` and/or `--browser`) moves them; so does `pnpm version patch --no-git-tag-version` in the workspace. Push a bump and that store publishes. **A tag that is missing when the store already has the version is a stuck release.** The tag is written after the publish succeeds, so a successful publish whose tag push failed leaves the repo believing the store still owes one. The next run submits a duplicate, the store refuses, and only a hand-made tag ever clears it. That is why `.github/actions/publish-and-record` treats a refusal saying the version is already there as published and records the tag. Every other failure still fails the job. If you ever widen that pattern, the failure mode you are risking is a tag written for a publish that never happened, which skips that store forever. To check the state before a release, or to work out why a job ran: ```bash git ls-remote --tags origin | grep -E "vscode|browser" ``` And to record something a store already has (a manual upload, a publish whose tag was lost), tag the commit whose content is live: ```bash git tag vscode-marketplace-v0.2.239 <commit> && git push origin vscode-marketplace-v0.2.239 ``` ## The stores **VS Code Marketplace.** Publishes with `vsce publish --azure-credential` from the `marketplace-publish` environment. A brand-new publisher gets blocked with "Your extension has suspicious content. Please fix your extension metadata, or contact support if you need assistance", which names nothing and is not documented anywhere. It survived removing an ad-carrying dependency, trimming the package and fixing every link. What cleared it was uploading the `.vsix` by hand at `marketplace.visualstudio.com/manage/publishers/weavemind` ("New extension"). Once the publisher has an accepted extension, CI should work; the next bump is what proves it. If it is blocked again, the question for `vsmarketplace@microsoft.com` is sharp: the package is byte-identical to one they accepted by hand, so the automated path is the only difference. Every documented case of this ends at support. **Open VSX** (`ovsx`) is the store VSCodium, Cursor and Windsurf read. It has never refused anything. Its namespace must exist before the first publish and creating it twice is refused, which the workflow handles. **Chrome, Firefox, Edge** go through `wxt submit` from `extension-browser`. AMO refuses a duplicate version with a 409 naming the version, which is the case the self-heal was written for. Firefox also needs a sources zip (`zip:firefox` writes it) because AMO reviews the source behind a bundle. ## Marketplace package rules worth knowing before packaging Checked against the published rules, and all of these are enforced: - The icon may not be an SVG and must be at least 128x128. - Images in the README must resolve to `https` URLs and may not be SVGs. Relative links are rewritten by `vsce` using the repository field against the `main` branch. Prefer absolute links to the docs site. - Badges are only allowed from approved providers. - `categories` must come from the fixed list; `keywords` caps at 30. - `displayName` must be unique Marketplace-wide. - A licence file must ship. `release.yml` copies the repo `LICENSE` into `extension-vscode/` at package time. `pnpm dlx @vscode/vsce@3.9.2 ls --no-dependencies` lists exactly what would ship, which is how to catch things like compiled tests riding along because `out/` was never cleaned. ## Deployments show red forever The repo's Deployments panel lists the `marketplace-publish` environment with a red mark from a failed run. GitHub keeps the last status per deployment and never revises it, and a job that is SKIPPED creates no deployment at all, so a later green run does not clear it. It is a record of a past attempt, not the current state. The truth is the run's own conclusion and the store itself: ```bash curl -s -X POST 'https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json;api-version=7.2-preview.1' \ -d '{"filters":[{"criteria":[{"filterType":7,"value":"weavemind.weft-vscode"}],"pageSize":5,"pageNumber":1}],"flags":914}' ``` ## A publish job that fails with an empty log `.github/actions/publish-and-record` captures the store's output so it can read the refusal. `shell: bash` runs the step under `-e`, and a `set -uo pipefail` does not lift that, so until the capture was wrapped in `set +e` a failing publish exited on the capture line and the log ended at the `PUBLISH:` echo with nothing from the store. If that shape ever comes back, the store's answer is missing because the script died before printing it, not because the store said nothing. ## What ships even when a store fails Each store publish is its own job, so one refusal never blocks another, and the rolling `latest` release goes out as long as the `.vsix` packaged and the images stitched. That release is what a fresh `./setup.sh` pulls prebuilts from, so a failed store publish costs the listing on that store and nothing else. Say so plainly rather than reporting a release as broken. ## Install and e2e before a merge `./setup.sh` and the e2e are yours to run, the way `MEMORY.md` lays out ("Every fix and feature ends with setup.sh and the e2e that cover it"): the branch you merge has passed them on its final code. Packaging the `.vsix` (`pnpm run vscode:prepublish && pnpm dlx @vscode/vsce@3.9.2 package --no-dependencies`) is yours too: it touches nothing outside `extension-vscode/`.
Auf GitHub ansehen