build: harden just publish with token lookup and dry run
Build & Publish Package / publish (push) Successful in 58s
Package Extension / package-extension (push) Successful in 1m17s
Testing / test (3.10) (push) Successful in 1m15s
Testing / test (3.12) (push) Successful in 1m8s
Testing / test (3.15) (push) Successful in 9m38s
Testing / remote-protocol-compat (0.15.0) (push) Successful in 9m20s
Testing / remote-protocol-compat (0.16.0) (push) Successful in 8m54s
Testing / test (3.14) (push) Successful in 55s
Build & Publish Package / publish (push) Successful in 58s
Package Extension / package-extension (push) Successful in 1m17s
Testing / test (3.10) (push) Successful in 1m15s
Testing / test (3.12) (push) Successful in 1m8s
Testing / test (3.15) (push) Successful in 9m38s
Testing / remote-protocol-compat (0.15.0) (push) Successful in 9m20s
Testing / remote-protocol-compat (0.16.0) (push) Successful in 8m54s
Testing / test (3.14) (push) Successful in 55s
- Move token lookup into scripts/pypi_token.sh, shared by both recipes - Resolve UV_PUBLISH_TOKEN, then .env, then pass api/packages/pypi - Fail with a clear hint instead of dropping into an interactive prompt - Never print the token, only its length - Gate publish behind version-check so version drift stops the build - Add publish-dry, same path as publish but with uv publish --dry-run - Pass --check-url so re-runs skip files already on PyPI - Hoist dist dir, token entry, and check URL into justfile variables - Add .env and .env.* to .gitignore The old recipe sourced .env for credentials, but .env was never ignored, so a token file dropped there would have been committed and shipped inside the sdist. Verified token precedence for env, .env and password-store, the missing-token exit code, the version-check gate, and a dry run against an unpublished version.
This commit is contained in:
@@ -9,6 +9,8 @@ dist/
|
||||
secrets/
|
||||
*.pem
|
||||
*.pem.gpg
|
||||
.env
|
||||
.env.*
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
# Default browser profile for `install` / quick checks
|
||||
browser := "brave"
|
||||
|
||||
# Where `publish` builds, and where it looks up the PyPI token
|
||||
dist_dir := "/tmp/dist-browser-cli"
|
||||
pypi_token_entry := "api/packages/pypi"
|
||||
pypi_check_url := "https://pypi.org/simple/"
|
||||
|
||||
# Show available recipes
|
||||
default:
|
||||
@just --list
|
||||
@@ -74,17 +79,27 @@ version-check:
|
||||
ext=$(grep -m1 '"version"' extension/manifest.json | cut -d'"' -f4); \
|
||||
if [ "$py" = "$ext" ]; then echo "ok: $py"; else echo "MISMATCH pyproject=$py manifest=$ext"; exit 1; fi
|
||||
|
||||
# Build into /tmp/dist-browser-cli and publish using credentials from .env
|
||||
publish:
|
||||
# Build and upload to PyPI. Token: UV_PUBLISH_TOKEN, else .env, else password-store.
|
||||
publish: version-check
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
set -a
|
||||
[ ! -f .env ] || source .env
|
||||
set +a
|
||||
rm -rf /tmp/dist-browser-cli
|
||||
mkdir -p /tmp/dist-browser-cli
|
||||
uv build --out-dir /tmp/dist-browser-cli
|
||||
uv publish /tmp/dist-browser-cli/*
|
||||
source scripts/pypi_token.sh
|
||||
load_pypi_token "{{pypi_token_entry}}" || exit 1
|
||||
rm -rf "{{dist_dir}}"
|
||||
mkdir -p "{{dist_dir}}"
|
||||
uv build --out-dir "{{dist_dir}}"
|
||||
uv publish --check-url "{{pypi_check_url}}" "{{dist_dir}}"/*
|
||||
|
||||
# Same build and token path as `publish`, but uploads nothing
|
||||
publish-dry: version-check
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
source scripts/pypi_token.sh
|
||||
load_pypi_token "{{pypi_token_entry}}" || exit 1
|
||||
rm -rf "{{dist_dir}}"
|
||||
mkdir -p "{{dist_dir}}"
|
||||
uv build --out-dir "{{dist_dir}}"
|
||||
uv publish --dry-run --check-url "{{pypi_check_url}}" "{{dist_dir}}"/*
|
||||
|
||||
# ── Demos ──────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
# Resolve the PyPI token for `uv publish` without ever printing it.
|
||||
#
|
||||
# Order: an already exported UV_PUBLISH_TOKEN, then .env in the repo root, then
|
||||
# the password-store entry passed as $1. The repo intentionally ships no .env,
|
||||
# so the password-store path is the normal one on a dev machine.
|
||||
|
||||
load_pypi_token() {
|
||||
local entry="${1:-}"
|
||||
|
||||
if [ -z "${UV_PUBLISH_TOKEN:-}" ] && [ -f .env ]; then
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
source .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
if [ -z "${UV_PUBLISH_TOKEN:-}" ] && [ -n "$entry" ] && command -v pass >/dev/null 2>&1; then
|
||||
UV_PUBLISH_TOKEN="$(pass "$entry" 2>/dev/null | head -1 || true)"
|
||||
fi
|
||||
|
||||
if [ -z "${UV_PUBLISH_TOKEN:-}" ]; then
|
||||
echo "error: no PyPI token found." >&2
|
||||
echo " export UV_PUBLISH_TOKEN=..., put it in .env, or store it in: pass ${entry:-<entry>}" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
export UV_PUBLISH_TOKEN
|
||||
echo "Using PyPI token (${#UV_PUBLISH_TOKEN} chars) for upload."
|
||||
}
|
||||
Reference in New Issue
Block a user