Prepare versions before CI fanout and remove recursive documentation checks

This commit is contained in:
Nick Sweeting committed 2026-09-27 14:15:46 -07:00
1 parent 224da46da5
commit 29a941bd9f
8 files changed
+88 -84

No files matched your search

+59 -1
View File
@@ -18,37 +18,94 @@ concurrency:
cancel-in-progress: ${{ github.event_name != 'workflow_dispatch' }}
jobs:
prepare:
name: Prepare the version before starting expensive jobs
permissions:
contents: write
runs-on: ubuntu-24.04
outputs:
run_tests: ${{ github.event_name != 'push' || steps.channel.outputs.stable == 'true' || steps.version.outputs.action == 'ready' || steps.version.outputs.action == 'reserved' }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
fetch-depth: 0
submodules: true
token: ${{ github.event_name == 'push' && secrets.RELEASE_GH_TOKEN || github.token }}
- name: Keep synchronized stable branches on the released version
id: channel
if: github.event_name == 'push'
shell: bash
run: |
set -Eeuo pipefail
VERSION="$(sed -nE 's/^version = "([^"]+)".*/\1/p' pyproject.toml | head -n 1)"
git fetch --no-tags origin main
MAIN_SHA="$(git rev-parse origin/main)"
# Stable reconciliation may preserve dev history with a merge commit.
# Its tree still matches main; bumping it would undo synchronization
# before the stable publisher can advance the Docker :dev tag.
if [[ "$GITHUB_REF_NAME" == dev && "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] &&
git merge-base --is-ancestor "$MAIN_SHA" "$GITHUB_SHA" &&
git diff --quiet "$MAIN_SHA" "$GITHUB_SHA"; then
echo 'stable=true' >> "$GITHUB_OUTPUT"
else
echo 'stable=false' >> "$GITHUB_OUTPUT"
fi
- id: version
if: github.event_name == 'push' && steps.channel.outputs.stable != 'true'
uses: ArchiveBox/monorepo/.github/actions/prepare-release-version@main
with:
package: archivebox
branch: ${{ github.ref_name }}
tag-prefix: v
version-scheme: ${{ github.ref_name == 'main' && 'patch' || 'rc' }}
lint:
needs: prepare
if: needs.prepare.outputs.run_tests == 'true'
name: Linters
uses: ./.github/workflows/lint.yml
secrets: inherit
install-cli-platform:
needs: prepare
if: needs.prepare.outputs.run_tests == 'true'
name: Install and CLI platform compatibility
uses: ./.github/workflows/test.yml
secrets: inherit
tests:
needs: prepare
if: needs.prepare.outputs.run_tests == 'true'
name: Discovered test matrix
uses: ./.github/workflows/test-parallel.yml
secrets: inherit
documentation:
needs: prepare
if: needs.prepare.outputs.run_tests == 'true'
name: Documentation and root tests
uses: ./.github/workflows/docs.yml
secrets: inherit
codeql:
needs: prepare
if: needs.prepare.outputs.run_tests == 'true'
name: CodeQL
uses: ./.github/workflows/codeql.yml
secrets: inherit
python-artifacts:
needs: prepare
if: needs.prepare.outputs.run_tests == 'true'
name: Tested Python artifacts
uses: ./.github/workflows/pip.yml
secrets: inherit
docker-digests:
needs: prepare
if: needs.prepare.outputs.run_tests == 'true'
name: Tested Docker images
uses: ./.github/workflows/docker.yml
with:
@@ -57,8 +114,9 @@ jobs:
required:
name: All required CI lanes
if: ${{ always() }}
if: ${{ always() && needs.prepare.outputs.run_tests == 'true' }}
needs:
- prepare
- lint
- install-cli-platform
- tests
-54
View File
@@ -1,54 +0,0 @@
name: Release candidate
on:
push:
branches: [dev, main]
permissions:
actions: read
contents: write
packages: write
concurrency:
group: release-candidate-${{ github.ref_name }}
cancel-in-progress: true
jobs:
prepare:
runs-on: ubuntu-24.04
outputs:
action: ${{ steps.version.outputs.action }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
fetch-depth: 0
submodules: true
token: ${{ secrets.RELEASE_GH_TOKEN }}
- name: Keep synchronized stable branches on the released version
id: channel
shell: bash
run: |
set -Eeuo pipefail
VERSION="$(sed -nE 's/^version = "([^"]+)".*/\1/p' pyproject.toml | head -n 1)"
git fetch --no-tags origin main
MAIN_SHA="$(git rev-parse origin/main)"
# Stable reconciliation may preserve dev history with a merge commit.
# Its tree still matches main; bumping it would undo synchronization
# before the stable publisher can advance the Docker :dev tag.
if [[ "$GITHUB_REF_NAME" == dev && "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] &&
git merge-base --is-ancestor "$MAIN_SHA" "$GITHUB_SHA" &&
git diff --quiet "$MAIN_SHA" "$GITHUB_SHA"; then
echo 'stable=true' >> "$GITHUB_OUTPUT"
else
echo 'stable=false' >> "$GITHUB_OUTPUT"
fi
- id: version
if: steps.channel.outputs.stable != 'true'
uses: ArchiveBox/monorepo/.github/actions/prepare-release-version@main
with:
package: archivebox
branch: ${{ github.ref_name }}
tag-prefix: v
version-scheme: ${{ github.ref_name == 'main' && 'patch' || 'rc' }}
+2 -6
View File
@@ -2,7 +2,7 @@ name: Release
on:
workflow_run:
workflows: [CI, Release candidate]
workflows: [CI]
types: [completed]
branches: [dev, main]
workflow_dispatch:
@@ -111,15 +111,11 @@ jobs:
--jq '[.status, .conclusion, .headSha, .event, .name] | @tsv')"
[[ "$CI_STATUS" == "$(printf 'completed\tsuccess\t%s\tpush\tCI' "$RELEASE_SHA")" ]]
else
CANDIDATE_RUN_ID="$(gh run list --repo "$GITHUB_REPOSITORY" --workflow release-candidate.yml \
--commit "$RELEASE_SHA" --branch "$RELEASE_BRANCH" --event push --limit 1 \
--json databaseId,status,conclusion \
--jq '.[0] | select(.status == "completed" and .conclusion == "success") | .databaseId // empty')"
CI_RUN_ID="$(gh run list --repo "$GITHUB_REPOSITORY" --workflow ci.yml \
--commit "$RELEASE_SHA" --branch "$RELEASE_BRANCH" --event push --limit 1 \
--json databaseId,status,conclusion \
--jq '.[0] | select(.status == "completed" and .conclusion == "success") | .databaseId // empty')"
[[ -n "$CANDIDATE_RUN_ID" && -n "$CI_RUN_ID" ]] || exit 0
[[ -n "$CI_RUN_ID" ]] || exit 0
DIGEST_RUN_ID="$CI_RUN_ID"
fi
ARTIFACT_RUN_ID="$CI_RUN_ID"
+2 -6
View File
@@ -77,11 +77,7 @@ archivebox run
## Verification
Use targeted tests for focused work:
```bash
uv run pytest archivebox/tests/test_cli_add.py::test_add_help_shows_depth_and_tag_options -q
uv run prek run --all-files
```
Run the test suite with `uv run pytest archivebox/tests -x` and repository checks
with `uv run prek run --all-files`. For focused work, select the relevant tests.
Releases are published only by `.github/workflows/release.yml` after complete CI succeeds for the exact commit. Pushes to `main` prepare stable patch releases automatically; `dev` prepares release candidates. Version selection and dependency repinning are owned by CI and the monorepo coordinator. Local development and deployment commands must not publish packages, images, tags, or GitHub releases.
+9 -7
View File
@@ -14,7 +14,7 @@ import yaml
REPO_ROOT = Path(__file__).resolve().parents[2]
RELEASE_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "release.yml"
RELEASE_CANDIDATE_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "release-candidate.yml"
CI_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "ci.yml"
PIP_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "pip.yml"
DOCKER_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "docker.yml"
VERIFY_STAGING_SCRIPT = REPO_ROOT / "bin" / "verify-staging-release.py"
@@ -115,9 +115,7 @@ def test_stable_release_reconciles_concurrent_version_only_dev_bump(tmp_path, de
assert result.returncode == 0, result.stderr
merged = _git(work, "ls-remote", "origin", "refs/heads/dev").split()[0]
channel_step = next(
step for step in yaml.safe_load(RELEASE_CANDIDATE_WORKFLOW.read_text())["jobs"]["prepare"]["steps"] if step.get("id") == "channel"
)
channel_step = next(step for step in yaml.safe_load(CI_WORKFLOW.read_text())["jobs"]["prepare"]["steps"] if step.get("id") == "channel")
def stable_channel(sha, branch="dev"):
output = tmp_path / "channel-output"
@@ -140,7 +138,7 @@ def test_stable_release_reconciles_concurrent_version_only_dev_bump(tmp_path, de
assert _git(work, "rev-parse", f"{merged}^{{tree}}") == _git(work, "rev-parse", f"{stable}^{{tree}}")
assert _git(work, "merge-base", stable, candidate) == base
# Reconciliation creates a new merge commit with the tested main tree. Its
# candidate workflow must not immediately bump dev and undo synchronization.
# version preparation must not immediately bump dev and undo synchronization.
assert stable_channel(merged) == "stable=true"
assert stable_channel(merged, branch="main") == "stable=false"
@@ -184,8 +182,12 @@ def test_release_uses_registered_publisher_and_authorized_tag_credentials():
assert jobs["cascade"]["if"] == "needs.python-release.outputs.release_ready == 'true'"
assert all(step.get("name") != "Verify published PyPI package installs and runs" for step in python_release["steps"])
candidate = yaml.safe_load(RELEASE_CANDIDATE_WORKFLOW.read_text())
assert set(candidate["jobs"]) == {"prepare"}
ci = yaml.safe_load(CI_WORKFLOW.read_text())
assert ci["jobs"]["prepare"]["steps"][-1]["uses"] == "ArchiveBox/monorepo/.github/actions/prepare-release-version@main"
for name, job in ci["jobs"].items():
if name not in {"prepare", "required"}:
assert job["needs"] == "prepare"
assert job["if"] == "needs.prepare.outputs.run_tests == 'true'"
gate = next(step["run"] for step in jobs["candidate"]["steps"] if step.get("id") == "verified")
assert 'ARTIFACT_RUN_ID="$CI_RUN_ID"' in gate
assert 'DIGEST_RUN_ID="$CI_RUN_ID"' in gate
@@ -954,6 +954,17 @@ def test_server_security_modes_in_chrome(
def test_archivewebpage_wacz_preview_serves_real_capture_frame(initialized_archive: Path, browser_runtime, tmp_path: Path) -> None:
from archivebox.core.routes_util import get_snapshot_subdomain
node_binary = Path(browser_runtime["node_binary"])
node_target = node_binary.resolve(strict=True)
node_version = subprocess.check_output([str(node_binary), "--version"], text=True).strip()
def assert_browser_runtime_unchanged(stage):
actual_target = node_binary.resolve(strict=True)
actual_version = subprocess.check_output([str(node_binary), "--version"], text=True).strip()
assert (actual_target, actual_version) == (node_target, node_version), (
f"{stage} changed the browser runtime: {node_target} ({node_version}) -> {actual_target} ({actual_version})"
)
url = "https://example.com"
port = get_free_port()
env = cli_env(
@@ -992,6 +1003,7 @@ def test_archivewebpage_wacz_preview_serves_real_capture_frame(initialized_archi
assert install_result.returncode == 0, (
f"archivebox install archivewebpage failed:\nSTDOUT:\n{install_result.stdout}\nSTDERR:\n{install_result.stderr}"
)
assert_browser_runtime_unchanged("archivebox install archivewebpage")
process = start_daemon_server(
initialized_archive,
@@ -1001,6 +1013,7 @@ def test_archivewebpage_wacz_preview_serves_real_capture_frame(initialized_archi
log_name="archivewebpage_server.log",
)
get_http_response(port, host=f"archivebox.localhost:{port}", path="/")
assert_browser_runtime_unchanged("archivebox server startup")
command_result = run_archivebox_cmd(
["add", "--depth=0", "--max-urls=1", "--plugins=archivewebpage", url],
cwd=initialized_archive,
@@ -1008,6 +1021,7 @@ def test_archivewebpage_wacz_preview_serves_real_capture_frame(initialized_archi
timeout=120,
)
assert command_result.returncode == 0, f"archivebox add failed:\nSTDOUT:\n{command_result.stdout}\nSTDERR:\n{command_result.stderr}"
assert_browser_runtime_unchanged("archivebox add --plugins=archivewebpage")
capture = _get_archivewebpage_capture(initialized_archive, url)
snapshot_host = f"{get_snapshot_subdomain(capture['snapshot_id'])}.archivebox.localhost:{port}"
-6
View File
@@ -54,7 +54,6 @@ version = 2
"16f996904f0eaa96-1" = "run"
"167cab3db82a6aee-1" = "run"
"6a6234b63cd3d0ae-1" = "run"
"396490664ce459e9-1" = "run"
# archivebox/mcp/README.md
"d9ff84abeb97d380-1" = "run"
@@ -69,7 +68,6 @@ version = 2
"ac2c1555d3b9cd8f-1" = "run"
"11a520069efa3387-1" = "run"
"46fe9d81940ea385-1" = "run"
"396490664ce459e9-2" = "run"
# docs/ArchiveBox-Architecture-Diagrams.md
"7442dd337fd0a1dd-1" = "illustration"
@@ -282,7 +280,6 @@ version = 2
"16f996904f0eaa96-1" = "project"
"167cab3db82a6aee-1" = "system"
"6a6234b63cd3d0ae-1" = "collection"
"396490664ce459e9-1" = "project"
"d9ff84abeb97d380-1" = "collection"
"aebc15190116f5cd-1" = "collection"
"0b307d4f1033723f-1" = "collection"
@@ -290,7 +287,6 @@ version = 2
"ac2c1555d3b9cd8f-1" = "project"
"11a520069efa3387-1" = "system"
"46fe9d81940ea385-1" = "collection"
"396490664ce459e9-2" = "project"
"201988374bff6d14-1" = "collection"
"e305c234db136566-1" = "collection"
"798793d9d6b2e12e-1" = "collection"
@@ -363,7 +359,6 @@ version = 2
"16f996904f0eaa96-1" = "ubuntu"
"167cab3db82a6aee-1" = "ubuntu"
"6a6234b63cd3d0ae-1" = "ubuntu"
"396490664ce459e9-1" = "ubuntu"
"d9ff84abeb97d380-1" = "ubuntu"
"aebc15190116f5cd-1" = "ubuntu"
"0b307d4f1033723f-1" = "ubuntu"
@@ -371,7 +366,6 @@ version = 2
"ac2c1555d3b9cd8f-1" = "ubuntu"
"11a520069efa3387-1" = "ubuntu"
"46fe9d81940ea385-1" = "ubuntu"
"396490664ce459e9-2" = "ubuntu"
"201988374bff6d14-1" = "ubuntu"
"e305c234db136566-1" = "ubuntu"
"798793d9d6b2e12e-1" = "ubuntu"
+2 -4
View File
@@ -68,9 +68,7 @@ archivebox run
## Verification
```bash
uv run pytest archivebox/tests/test_cli_add.py::test_add_help_shows_depth_and_tag_options -q
uv run prek run --all-files
```
Run the test suite with `uv run pytest archivebox/tests -x` and repository checks
with `uv run prek run --all-files`. For focused work, select the relevant tests.
Releases are published only by `.github/workflows/release.yml` after the complete `dev` CI workflow succeeds. Local development and deployment commands must not publish packages, images, tags, or GitHub releases.