Prepare versions before CI fanout and remove recursive documentation checks
This commit is contained in:
8 files changed
+88
-84
No files matched your search
@@ -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
|
||||
|
||||
@@ -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,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"
|
||||
|
||||
@@ -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.
|
||||
@@ -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}"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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.
|
||||
Reference in new issue
Block a user