When $old != zero and $new is not a descendant of $old (detected via
git merge-base --is-ancestor), the hook now forwards +$new:$ref so the
upstream accepts the force push instead of rejecting it as a
non-fast-forward.
Closes#233
- Strip pipelock from all unit and integration test fixtures:
proxy_plan fields removed from DockerBottlePlan/SmolmachinesBottlePlan
constructors; pipelock-specific test classes deleted or renamed
- Update test_sidecar_init: remove test_pipelock_loses_egress_tokens,
rename "pipelock" daemon fixtures to "git-gate" throughout
- Remove test_pipelock_binary_present_and_versioned from integration test
- Remove test_pipelock_answers_on_bundle_ip from smolmachines launch test
- Update _SANDBOX_BLOCK_MARKERS: remove "pipelock" marker (egress blocks)
- Dockerfile.sidecars: remove pipelock build stage and COPY; update layout
comments and port table
- egress_entrypoint.sh: update comments now that egress is sole proxy
- Clean up pipelock references in comments/docstrings across backend,
network, manifest, supervise, git_gate, yaml_subset, agent_provider,
sidecar_bundle, sidecar_init, egress_addon_core modules
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove 35+ unused imports across 20+ files (W0611). Wrap 19 lines
to fit under 100 character limit (C0301). Add type casts and
annotations in egress_addon_core.py to resolve pyright errors
caused by JSON parsing of untyped objects.
Key changes:
- Remove unused imports (abstractmethod, mock utilities, etc)
- Split long lines at logical breaks (method calls, error messages)
- Add typing.cast() for proper type inference in JSON parsing
- Explicit type annotations for dict/list accesses
Results:
- Pylint rating: 8.73/10
- egress_addon_core.py: 0 pyright errors (was 15)
- All W0611 and C0301 issues fixed
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- manifest_git.py: add ProvisionedKeyConfig dataclass; extend GitEntry
with ProvisionedKey field (optional); make IdentityFile default to ""
so provisioned_key entries can be constructed without a static path;
add _parse_provisioned_key_config; update from_repos_entry to accept
provisioned_key as an alternative to identity (mutually exclusive,
parser rejects both-or-neither)
- deploy_key_provisioner.py (new): DeployKeyProvisioner ABC with create()
and delete() abstract methods; get_provisioner() factory with lazy
contrib import for gitea
- contrib/gitea/deploy_key_provisioner.py (new): GiteaDeployKeyProvisioner
generating ed25519 keypairs via ssh-keygen and managing them through
the Gitea deploy-key API (POST/DELETE); 404 on delete is success;
all other errors raise RuntimeError
- git_gate.py: add _provision_dynamic_key() called in GitGate.prepare()
for entries with ProvisionedKey — generates key, writes private key
and key ID files to stage_dir, patches GitGateUpstream.identity_file;
add revoke_git_gate_provisioned_keys() for teardown — raises on failure
- docker/launch.py: call revoke_git_gate_provisioned_keys() in teardown()
after stack.close() so revocation runs after containers stop and
failures propagate (not suppressed)
- smolmachines/launch.py: extract _teardown_smolmachines() helper that
catches stack.close() errors (warn + re-raise) then calls revocation;
same fatal-on-failure contract as docker backend
- test_manifest_git.py: 9 new cases for provisioned_key parsing
- test_deploy_key_provisioner.py (new): factory smoke tests
- test_contrib_gitea_deploy_key.py (new): create/delete/error/split tests
Closes#169
Use shlex.quote() on name and upstream_url in git_gate_render_entrypoint()
so special characters (single quotes, spaces, semicolons) cannot break or
inject into the generated sh script.
Add _GIT_NAME_RE validation in GitEntry.from_repos_entry() to restrict
repo names to [A-Za-z0-9._-]+, making the manifest the first line of
defence and shlex.quote() the belt-and-suspenders backstop.
Closes#155
A new ref made the pre-receive hook scan the full ancestry
(`log_opts="$new"`), so historical test-fixture findings rejected every
new-branch push (#106). Scope it to `$new --not --all` — only commits
new to the gate, which (since the bare repo is populated solely by
upstream mirror-fetch and gitleaks-gated pushes) loses no coverage on
what a push actually brings to the upstream. Also add BatchMode=yes +
ConnectTimeout=10 to both the forward and access-hook ssh so an
unreachable upstream fails fast instead of hanging.
Refs #106
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>