Skip to content
Open
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
12 changes: 3 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -361,15 +361,9 @@ jobs:
scripts/render-zed-mirror.sh "${RUNNER_TEMP}/zed-mirror" 0.0.0-ci
( cd "${RUNNER_TEMP}/zed-mirror" && cargo build --release --target wasm32-wasip2 )

# The registry listing edits a ~1400-entry file in a repo we do not own,
# and it only ever runs during a tagged release — so it gets its proof
# here, on the PR, rather than the first time it touches upstream. Pure
# text-editing functions only; no network ([ZED-MIRROR]).
- name: Test the zed-industries listing edit
run: |
set -euo pipefail
pip install pytest==9.1.1
python3 -m pytest scripts/test_publish_zed_registry.py -q
# The zed-industries listing edit used to be proved here. It is gone:
# Basilisk is not in that registry and never was, so the only thing the
# script could do is ADD a listing during an unlisting ([ZED-MIRROR]).

# ── Rust coverage + thresholds (runs in parallel) ──────────────────────────
test-rust:
Expand Down
67 changes: 38 additions & 29 deletions delist/00-publish-zed-final.sh
Original file line number Diff line number Diff line change
@@ -1,53 +1,66 @@
#!/usr/bin/env bash
# Publish the FINAL Zed extension — run this BEFORE 01-verify-final-release.sh.
# Replace the public Zed mirror with the notice-only extension.
#
# Implements [WITHDRAWAL-UNLIST] and [ZED-MIRROR]. Zed is the one channel the
# Release workflow does not publish: the `publish-zed` job was removed from
# release.yml after its registry-listing step failed the v0.41.0 release, so
# every other channel ships from the tag and Zed ships from here, by hand.
# Implements [WITHDRAWAL-UNLIST] and [ZED-MIRROR].
#
# Why it still has to ship. Zed users are not reached by the CLI release: their
# extension downloads the binary itself, so once the final binary is inert their
# editor shows "language server failed to start" and never shows the statement.
# The final extension is what replaces that with the statement — it registers no
# language server at all and prints the notice under `/basilisk`.
# Basilisk is NOT in the Zed extension registry and never was. There is no
# `[basilisk]` block in zed-industries/extensions/extensions.toml, no
# extensions/basilisk submodule, and no commit in that repo has ever mentioned
# it — the `publish-zed` job was removed from release.yml after its registry
# step failed the v0.41.0 release, and it never landed before that. So there is
# nothing to bump and nothing to remove there, and opening a listing PR NOW
# would add Basilisk to a registry it was never in, in the middle of unlisting
# it. Do not do that. 06-unlist-zed.sh re-checks this and fails if it changes.
#
# Two things happen here, in order:
# 1. push + tag the rendered tree to Nimblesite/basilisk-zed (the mirror)
# 2. open the PR bumping `basilisk` in zed-industries/extensions to that tag
# What IS public is the mirror, Nimblesite/basilisk-zed. Anyone can read it, and
# Zed installs a dev extension straight from a local clone of exactly this
# layout. Its `main` still serves the OLD extension: a [language_servers.basilisk]
# block that launches `basilisk lsp` — a command the inert CLI no longer has —
# and a description advertising diagnostics, autocomplete, refactoring, and
# profiling. That is a live product claim for a checker that was wrong.
#
# Step 2 lands in someone else's review queue. Until it merges, Zed serves the
# previous version — so `06-unlist-zed.sh` (the removal PR) waits for it.
# This script replaces that tree with the notice-only extension, so the mirror
# says what every other surface says. 06-unlist-zed.sh then archives it.
#
# Needs: gh authenticated; push rights to Nimblesite/basilisk-zed; cargo with
# the wasm32-wasip2 target (the push is gated on a real standalone build).
#
# delist/00-publish-zed-final.sh v0.42.0 [--yes]
# delist/00-publish-zed-final.sh v0.41.2 [--yes]

source "$(dirname "${BASH_SOURCE[0]}")/common.sh"

VERSION="${1:-}"
[ -n "$VERSION" ] || fail "usage: 00-publish-zed-final.sh <tag, e.g. v0.42.0> [--yes]"
[ -n "$VERSION" ] || fail "usage: 00-publish-zed-final.sh <tag, e.g. v0.41.2> [--yes]"
shift
parse_args "$@"
BARE="${VERSION#v}"
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
REGISTRY_TOML="https://raw.githubusercontent.com/zed-industries/extensions/main/extensions.toml"

banner "Zed extension — Nimblesite/basilisk-zed + zed-industries/extensions"
banner "Zed mirror — Nimblesite/basilisk-zed"

require_cmd gh "the registry PR is opened through the GitHub API"
require_cmd gh "the mirror is pushed over an authenticated remote"
require_cmd git "the mirror is pushed as a clone"
require_cmd cargo "the push is gated on a standalone wasm build"
require_cmd curl "the registry is checked before anything is published"

work="$(mktemp -d)"
trap 'rm -rf "$work"' EXIT

# If a listing ever appears, every assumption above is void: publishing would
# then be updating a real listing, and the removal PR in 06 becomes necessary.
step "Confirm Basilisk is still absent from the Zed registry"
if curl -fsSL "$REGISTRY_TOML" | grep -q '^\[basilisk\]'; then
fail "zed-industries/extensions now lists basilisk — re-read 06-unlist-zed.sh before publishing"
fi
ok "no basilisk entry in the registry; this publishes to the mirror only"

step "Render the standalone tree at $BARE"
"$REPO_ROOT/scripts/render-zed-mirror.sh" "$work/render" "$BARE"

# Gate the push on the same build the registry will run. A tree that does not
# compile standalone is a listing that fails on their CI, not ours.
step "Build it exactly as the registry will"
# Gate the push on a real build. A tree that does not compile standalone is a
# broken dev extension for anyone who clones the mirror.
step "Build it standalone"
( cd "$work/render" && cargo build --release --target wasm32-wasip2 )
ok "standalone wasm build passed"

Expand All @@ -63,7 +76,7 @@ grep -q "Basilisk is unlisted" "$work/render/src/withdrawal_notice.txt" ||
fail "the rendered tree carries no withdrawal notice"
ok "no language server, no debug adapter, no grammar; the notice is present"

if confirm "publish the final Zed extension and open the registry bump PR"; then
if confirm "replace the public Zed mirror with the notice-only extension"; then
step "Push the mirror"
# render-zed-mirror.sh replaces the clone's tracked content and preserves
# its .git, so the mirror keeps its history rather than being force-reset.
Expand All @@ -75,10 +88,6 @@ if confirm "publish the final Zed extension and open the registry bump PR"; then
act git -C "$work/mirror" tag "$VERSION"
act git -C "$work/mirror" push origin "$VERSION"

step "Open the registry bump PR"
act python3 "$REPO_ROOT/scripts/publish_zed_registry.py" "$BARE" "$VERSION"

ok "mirror pushed and tagged $VERSION; bump PR opened"
warn "Zed still serves the PREVIOUS version until a maintainer merges that PR."
warn "Do not run 06-unlist-zed.sh until it is merged and live."
ok "mirror replaced and tagged $VERSION"
warn "No registry PR was opened, and none should be: Basilisk is not listed on Zed."
fi
17 changes: 8 additions & 9 deletions delist/01-verify-final-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,24 +71,23 @@ nvim_tag="$(curl -fsSL "https://api.github.com/repos/Nimblesite/basilisk.nvim/ta
check "Nimblesite/basilisk.nvim" "$nvim_tag"

# Zed does not ship from the release workflow — delist/00-publish-zed-final.sh
# pushes the mirror by hand. Check the mirror tag here; the registry entry it
# points at only goes live once a Zed maintainer merges the bump PR, which is a
# separate wait and not a blocker for the other channels ([ZED-MIRROR]).
# pushes the mirror by hand, and the mirror is the whole Zed surface: Basilisk
# is not in the zed-industries registry and never was ([ZED-MIRROR]).
step "Zed mirror tag"
zed_tag="$(curl -fsSL "https://api.github.com/repos/Nimblesite/basilisk-zed/tags" |
python3 -c 'import json,sys; print(json.load(sys.stdin)[0]["name"].lstrip("v"))' 2>/dev/null || echo "")"
check "Nimblesite/basilisk-zed" "$zed_tag"

# Not a version check: an entry appearing here at all would mean Basilisk got
# listed on Zed during its unlisting, and both Zed scripts refuse to run.
step "Zed registry entry"
zed_listed="$(curl -fsSL "https://raw.githubusercontent.com/zed-industries/extensions/main/extensions.toml" |
python3 -c 'import sys,tomllib; print(tomllib.loads(sys.stdin.read()).get("basilisk", {}).get("version", ""))' 2>/dev/null || echo "")"
if [ "$zed_listed" = "$BARE" ]; then
ok "Zed registry is at $BARE"
elif [ -z "$zed_listed" ]; then
warn "Zed registry lists no basilisk entry — nothing to unlist there"
if [ -z "$zed_listed" ]; then
ok "Zed registry lists no basilisk entry — as expected; nothing to unlist there"
else
warn "Zed registry is still at '$zed_listed' — the bump PR has not merged yet."
warn "Do not run 06-unlist-zed.sh until it lands."
warn "Zed registry now lists basilisk at '$zed_listed' — it was never listed before."
warn "Re-read delist/06-unlist-zed.sh: a removal PR is needed after all."
fi

echo
Expand Down
78 changes: 43 additions & 35 deletions delist/06-unlist-zed.sh
Original file line number Diff line number Diff line change
@@ -1,49 +1,57 @@
#!/usr/bin/env bash
# Open the PR that removes Basilisk from the Zed extension registry.
# Archive the Zed extension mirror.
#
# Implements [WITHDRAWAL-UNLIST]. The Zed registry is zed-industries/extensions,
# a repo we do not own: the entry is a `[basilisk]` block in extensions.toml
# plus a git submodule. Removing it is a pull request, so this script prepares
# and opens that PR — a human on their side merges it.
# Implements [WITHDRAWAL-UNLIST] and [ZED-MIRROR].
#
# Needs: gh, authenticated; a fork of zed-industries/extensions is created if
# one does not exist.
# This script used to open a PR removing `basilisk` from zed-industries/extensions.
# There is nothing there to remove. Basilisk is not in the Zed registry and never
# was: no `[basilisk]` block in extensions.toml, no extensions/basilisk submodule,
# and no commit in that repo has ever mentioned it. The `publish-zed` job was
# removed from release.yml after its registry step failed the v0.41.0 release,
# and it had not landed before that. A removal PR would ask a maintainer of
# someone else's repo to delete an entry that does not exist.
#
# The mirror, Nimblesite/basilisk-zed, IS the listing: it is public, and Zed
# installs a dev extension straight from a clone of that layout. 00 replaces its
# contents with the notice-only extension; this archives it. Archived rather
# than deleted, for the same reason as the Neovim mirror — deleting breaks every
# pinned clone and erases the record, while archiving is read-only and visibly
# dead.
#
# Needs: gh, authenticated with admin access to Nimblesite/basilisk-zed.
#
# delist/06-unlist-zed.sh [--yes]

source "$(dirname "${BASH_SOURCE[0]}")/common.sh"
parse_args "$@"
banner "Zed extension registryzed-industries/extensions"
banner "Zed extension mirrorNimblesite/basilisk-zed"

require_cmd gh "the PR is opened through the GitHub API"
require_cmd git "the registry is edited as a clone"
require_cmd gh "the repo is edited through the GitHub API"
require_cmd curl "the registry is re-checked before archiving"

work="$(mktemp -d)"
trap 'rm -rf "$work"' EXIT
branch="remove-basilisk"
REGISTRY_TOML="https://raw.githubusercontent.com/zed-industries/extensions/main/extensions.toml"

body="Please remove the \`basilisk\` extension from the registry.

Basilisk's type checker was producing incorrect results. We asked for it to be
removed from the python/typing conformance results, and it has been removed
(https://github.com/python/typing/pull/2330). The code responsible is not
isolated to a known set of rules, so we cannot say how many rules are affected.
A code-quality tool that does not produce correct results is worse than useless,
so Basilisk is being unlisted from every distribution channel and its CLI is
inert — the extension can no longer start a language server.
# Re-checked rather than assumed. If a listing ever appears, archiving the
# mirror strands it — the registry entry points at a submodule of this repo —
# and a removal PR becomes the right move after all.
step "Confirm Basilisk is absent from the Zed registry"
if curl -fsSL "$REGISTRY_TOML" | grep -q '^\[basilisk\]'; then
fail "zed-industries/extensions now lists basilisk — open a removal PR there BEFORE archiving the mirror"
fi
ok "no basilisk entry in the registry — nothing to remove there"

Full statement: https://www.basilisk-python.dev/"
step "Confirm the mirror carries the statement"
manifest="$(curl -fsSL https://raw.githubusercontent.com/Nimblesite/basilisk-zed/main/extension.toml 2>/dev/null || echo "")"
case "$manifest" in
*"[language_servers"*) warn "the mirror still declares a language server — run 00-publish-zed-final.sh first" ;;
*"unlisted"*) ok "the mirror manifest already carries the statement" ;;
*) warn "could not read the mirror manifest — check it by hand before archiving" ;;
esac

if confirm "open a PR removing basilisk from zed-industries/extensions"; then
act gh repo fork zed-industries/extensions --clone=false --remote=false
act gh repo clone zed-industries/extensions "$work/extensions" -- --depth 1
act git -C "$work/extensions" checkout -b "$branch"
act git -C "$work/extensions" submodule deinit -f extensions/basilisk
act git -C "$work/extensions" rm -f extensions/basilisk
act python3 "$(dirname "${BASH_SOURCE[0]}")/remove_registry_entry.py" "$work/extensions/extensions.toml" basilisk
act git -C "$work/extensions" commit -am "Remove basilisk"
act git -C "$work/extensions" push --set-upstream "$(gh api user --jq .login)" "$branch"
act gh pr create --repo zed-industries/extensions \
--title "Remove basilisk" --body "$body" --head "$branch"
ok "PR opened — track it until merged, then confirm the extension is gone from Zed's registry"
if confirm "archive Nimblesite/basilisk-zed (read-only, permanent-ish)"; then
act gh repo edit Nimblesite/basilisk-zed \
--description "Basilisk's type checker produced incorrect results. Basilisk is unlisted and is being rebuilt from the ground up as a new product." \
--homepage "https://www.basilisk-python.dev"
act gh repo archive Nimblesite/basilisk-zed --yes
ok "archived — confirm at https://github.com/Nimblesite/basilisk-zed"
fi
47 changes: 46 additions & 1 deletion delist/08-verify-unlisted.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,56 @@ gone() {
}

step "Channels that must 404"
# The Marketplace item page is a real signal, checked against controls: it
# returns 200 for live extensions (ms-python.python, rust-lang.rust-analyzer)
# and 404 once an extension is unpublished. The gallery `extensionquery` API
# keeps answering for an unpublished extension — with `unpublished` among its
# flags — so the API is the wrong thing to ask here.
gone "VS Code Marketplace" "https://marketplace.visualstudio.com/items?itemName=Nimblesite.basilisk"
gone "Open VSX" "https://open-vsx.org/api/Nimblesite/basilisk"
gone "Homebrew formula" "https://raw.githubusercontent.com/Nimblesite/homebrew-tap/main/Formula/basilisk.rb"
gone "Scoop manifest" "https://raw.githubusercontent.com/Nimblesite/scoop-bucket/main/bucket/basilisk.json"
gone "Zed registry entry" "https://raw.githubusercontent.com/zed-industries/extensions/main/extensions/basilisk/extension.toml"

# Zed is NOT a `gone` URL check. Registry entries are git SUBMODULES, so the
# parent repo serves no files under extensions/<name>/ and that path 404s for
# every extension in the registry — checking it reported "gone" for `ty` and
# `pyrefly`, which are both listed. A check that cannot fail is worse than no
# check. Ask the file that actually holds the listing ([ZED-MIRROR]).
step "Zed registry entry"
if curl -fsSL "https://raw.githubusercontent.com/zed-industries/extensions/main/extensions.toml" |
grep -q '^\[basilisk\]'; then
printf "%b✗ Zed registry: STILL LISTED — a [basilisk] entry exists in extensions.toml%b\n" "$RED" "$RESET"
still_listed=$((still_listed + 1))
else
ok "Zed registry: no [basilisk] entry (it was never listed there)"
fi

# The mirror IS the Zed listing — public, and Zed installs a dev extension from
# a clone of it. Archived, not deleted, so it must still resolve.
step "Zed mirror archived"
zed_archived="$(curl -fsSL "https://api.github.com/repos/Nimblesite/basilisk-zed" |
python3 -c 'import json,sys; print(json.load(sys.stdin).get("archived"))' 2>/dev/null || echo "unreachable")"
case "$zed_archived" in
True) ok "Nimblesite/basilisk-zed is archived (read-only)" ;;
False)
printf "%b✗ Nimblesite/basilisk-zed is NOT archived — run 06-unlist-zed.sh%b\n" "$RED" "$RESET"
still_listed=$((still_listed + 1))
;;
*) warn "could not read Nimblesite/basilisk-zed — check by hand" ;;
esac

# Same for the Neovim mirror: plugin managers install straight from the repo.
step "Neovim mirror archived"
nvim_archived="$(curl -fsSL "https://api.github.com/repos/Nimblesite/basilisk.nvim" |
python3 -c 'import json,sys; print(json.load(sys.stdin).get("archived"))' 2>/dev/null || echo "unreachable")"
case "$nvim_archived" in
True) ok "Nimblesite/basilisk.nvim is archived (read-only)" ;;
False)
printf "%b✗ Nimblesite/basilisk.nvim is NOT archived — run 05-unlist-nvim-mirror.sh%b\n" "$RED" "$RESET"
still_listed=$((still_listed + 1))
;;
*) warn "could not read Nimblesite/basilisk.nvim — check by hand" ;;
esac

step "PyPI — yanked, not deleted"
# Yanking keeps the files installable by exact pin (so existing lockfiles do not
Expand Down
Loading
Loading