Skip to content

Releases: extremeshok/poll-ci

v1.5.0 — parallel checks, opt-in caching, self-update

Choose a tag to compare

@extremeshok extremeshok released this 15 Jun 18:04

Highlights

Parallel per-commit checks — on by default. A commit's checks (and the trivy scan) now run concurrently in a bounded pool instead of one at a time. CHECK_CONCURRENCY (default: host CPU count; 1 = serial = old behavior) caps how many run at once; checks share the host CPUs, with optional per-check cpus:/memory: hints. Measured ~2.4× faster on an 8-core host (24m → 10m for an 11-check repo).

Opt-in dependency caching (CACHE=true). A clean, monorepo-aware "golden" cache built by a prime step in an isolated container and copied into each check (never written back, so it can't be poisoned). Off by default — it only pays off for download-heavy checks; compute-bound checks (go test, bundler builds) see no gain, and the copy-in can cost at high concurrency.

Self-update timer — on by default. deploy/install.sh installs a systemd timer that pulls :latest daily and restarts poll-ci only when the image digest changed (--noautoupdate to skip). The systemd-native alternative to the compose watchtower profile.

Upgrading

Existing deployments get parallel checks automatically — no config change. To keep the old serial behavior, set CHECK_CONCURRENCY=1. See the README for the full configuration reference.

poll-ci v1.4.0

Choose a tag to compare

@extremeshok extremeshok released this 11 Jun 16:32

What's changed in v1.4.0

A reliability and hardening release, driven by an audit of poll-ci's production
status output on a busy watched repo plus a full code review.

Fixes

  • Status posts retry on transient failures. A single dropped POST (network
    blip, GitHub 5xx) left that context pending forever — observed in
    production on a green, already-promoted commit. Posts now retry with backoff
    and honor Retry-After; permanent failures (token permissions) still
    surface immediately.
  • A still-running check can no longer be scored as passed. docker start -a returning is no guarantee the container exited, and a running
    container's inspect reports exit code 0. The outcome now comes from the
    container state (plus docker wait), so a broken attach stream can't
    produce a false green that promotes untested code.
  • Crash/restart reconciliation. Runs persist an in-flight marker; on
    startup, statuses stranded pending by a mid-run kill (watchtower recreate,
    reboot, OOM) are resolved as interrupted by restart when the branch has
    moved on. The startup sweep also removes containers and checkouts the dead
    process orphaned (instance-scoped label; prune pre-v1.4 orphans once with
    docker ps -aq -f label=poll-ci | xargs docker rm -f).
  • Short-circuit race fixed. A run that completed every step keeps its
    results (and promotes) even if a newer tip's cancellation raced in at the
    very end.
  • Force-push reverts re-run. Superseded SHAs are no longer marked
    processed, so a branch force-pushed back to one re-tests it instead of
    showing stale superseded by statuses forever.
  • Heartbeat: HEARTBEAT_MAX_LAG defaults to 0 — with 1, a failed
    promotion affecting only the tip commit never alerted. The no-jq fallback
    also extracted the wrong sha from the compare payload; fixed. Existing
    installs keep their env file: set HEARTBEAT_MAX_LAG=0 there to adopt the
    new default.
  • Polish: invalid env values warn instead of being silently ignored,
    scan.path rejects .., and open-PR listing paginates past 100.

Security / hardening

  • The git auth header is passed via environment (GIT_CONFIG_*) instead of
    argv, so it is no longer visible in process listings; log scrubbing also
    redacts the base64 header form. Plain-binary deployments need git >= 2.31.
  • Optional resource limits for check/scan containers: CHECK_MEMORY,
    CHECK_CPUS, CHECK_PIDS.
  • Engine image base bumped to alpine:3.24 with apk upgrade at build time.

Opt-in features (defaults preserve existing behavior)

  • MARK_SKIPPED=true — post a terminal ci status (not tested — superseded by <sha>) on the intermediate commits a fast push skipped.
  • CONCURRENCY=N — sweep multiple repos in parallel.
  • IMAGE_REFRESH_HOURS=N — periodically re-pull present check images so
    :latest tags don't freeze at first pull.
  • PR runs now short-circuit on force-push like branch runs do (under the
    existing SHORT_CIRCUIT).

The state file migrates transparently from older versions, and is now pruned
after ~6 months (a branch's last result is always kept).

Install

docker pull ghcr.io/extremeshok/poll-ci:v1.4.0     # or :latest
go install github.com/extremeshok/poll-ci@v1.4.0

Prebuilt binaries below (verify with poll-ci_v1.4.0_checksums.txt).

poll-ci v1.3.1

Choose a tag to compare

@extremeshok extremeshok released this 08 Jun 16:49

What's changed in v1.3.1

Patch release hardening the v1.3.0 short-circuit feature (found via an
adversarial review pass).

  • No status is left pending on a superseded commit. When a run is
    short-circuited by a newer commit, every status that hadn't finished —
    the in-flight check, the not-yet-started checks, and the ci/trivy scan if
    it was unreached or mid-run — is now resolved to superseded by <sha>.
    Checks that had already finished keep their real result. (v1.3.0 resolved
    only the ci rollup, leaving per-check and scan contexts stuck pending,
    which could block branch protection on the dead commit.)
  • ci/promote no longer strands on shutdown. If the engine is stopped
    mid-promotion, the commit is left unmarked so it re-runs (and re-promotes)
    on restart instead of leaving ci/promote pending forever.

No config changes. Upgrade is a straight image/binary swap.

Install

docker pull ghcr.io/extremeshok/poll-ci:v1.3.1     # or :latest
go install github.com/extremeshok/poll-ci@v1.3.1

Prebuilt binaries below (verify with poll-ci_v1.3.1_checksums.txt).

poll-ci v1.3.0

Choose a tag to compare

@extremeshok extremeshok released this 08 Jun 15:05

What's new in v1.3.0

  • Short-circuit superseded runs. On a busy branch, commits can land faster
    than CI finishes. poll-ci now watches the branch tip during a run and, the
    moment a newer commit appears, aborts the stale run (killing the in-flight
    check container), marks that commit's ci status superseded by <sha>, and
    jumps straight to the newest commit — no more waiting on CI for a commit
    that's already been replaced.

    On by default. The tip is re-checked every POLL_INTERVAL, so only runs longer
    than one interval get cut short. Set SHORT_CIRCUIT=false to run every started
    commit to completion. Applies to branch polling (not PRs or --once).

No config-file changes. Upgrade is a straight image/binary swap.

Install

docker pull ghcr.io/extremeshok/poll-ci:v1.3.0     # or :latest
go install github.com/extremeshok/poll-ci@v1.3.0

Prebuilt binaries below (verify with poll-ci_v1.3.0_checksums.txt).

poll-ci v1.2.1

Choose a tag to compare

@extremeshok extremeshok released this 08 Jun 09:00

What's changed in v1.2.1

Patch release — polish for the scan: feature added in v1.2.0.

  • Clearer ci/trivy failure status. A failing scan now reports
    trivy found issues at HIGH,CRITICAL — see ci/trivy logs instead of a stray
    trivy log line. trivy writes its findings to stdout and INFO logs to stderr
    (the opposite of a normal check), which the previous heuristic scraped; fixed,
    and trivy now runs with --quiet (cleaner logs — the findings report still
    streams). The status colour and promote-gating were already correct; this only
    improves the red status text.

No config changes. Upgrade is a straight image/binary swap.

Install

docker pull ghcr.io/extremeshok/poll-ci:v1.2.1     # or :latest
go install github.com/extremeshok/poll-ci@v1.2.1

Prebuilt binaries below (verify with poll-ci_v1.2.1_checksums.txt).

poll-ci v1.2.0

Choose a tag to compare

@extremeshok extremeshok released this 08 Jun 08:44

What's new in v1.2.0

  • Built-in trivy source scan (scan:). Add a scan: block and poll-ci runs
    a trivy filesystem scan of the checkout as a gate step,
    reported as a ci/trivy commit status. A finding fails the gate — so,
    combined with promote:, vulnerable deps, leaked secrets, or misconfigured
    Dockerfiles/IaC never advance a deploy branch. Shift-left scanning of the
    source, complementary to scanning built images. Needs no GitHub token; the
    trivy DB is cached in a named volume so it isn't re-downloaded each run.

    checks:
      - { name: test, run: go test ./... }
    scan: {}                 # defaults: vuln,secret,misconfig · HIGH,CRITICAL
    promote:
      branch: release        # only green + clean source promotes
  • Promotion-pipeline heartbeat (dead-man's-switch). Optional systemd
    timer + monitor (deploy/heartbeat-monitor.sh) that alerts if the poller
    stops advancing the deploy branch — so a silently-stuck pipeline is noticed.
    Installed by deploy/install.sh.

Install

# Docker
docker run -d --restart always \
  -e GITHUB_TOKEN=github_pat_xxx -e REPO=you/repo -e BRANCH=main \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v poll-ci-state:/var/lib/poll-ci \
  ghcr.io/extremeshok/poll-ci:v1.2.0

# Systemd service (one command)
git clone https://github.com/extremeshok/poll-ci && sudo poll-ci/deploy/install.sh

# Go
go install github.com/extremeshok/poll-ci@v1.2.0

Prebuilt binaries below (verify with poll-ci_v1.2.0_checksums.txt).
Full docs: README.

poll-ci v1.1.0

Choose a tag to compare

@extremeshok extremeshok released this 07 Jun 19:19

What's new in v1.1.0

  • promote: — fast-forward a deploy branch on green. Optional per-repo
    setting: when every check passes on a watched branch, poll-ci fast-forwards a
    target branch (e.g. release) to that commit and reports a ci/promote
    status. Lets a deploy branch be gated behind green CI without GitHub Actions.
    Opt-in, and only this needs the token's Contents: write.

    checks:
      - { name: test, run: go test ./... }
    promote:
      branch: release
  • One-command systemd installer. deploy/install.sh
    installs poll-ci as a boot-managed Docker service (systemd unit, pinned image,
    0600 token env file). Graceful systemctl stop.

  • Optional auto-update. docker compose --profile autoupdate up -d keeps
    poll-ci on the latest image via watchtower (scoped to poll-ci only).

Install

# Docker
docker run -d --restart always \
  -e GITHUB_TOKEN=github_pat_xxx -e REPO=you/repo -e BRANCH=main \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v poll-ci-state:/var/lib/poll-ci \
  ghcr.io/extremeshok/poll-ci:v1.1.0

# Systemd service (one command)
git clone https://github.com/extremeshok/poll-ci && sudo poll-ci/deploy/install.sh

# Go
go install github.com/extremeshok/poll-ci@v1.1.0

Or download a prebuilt binary below (verify with poll-ci_v1.1.0_checksums.txt).
Full docs in the README.

poll-ci v1.0.0

Choose a tag to compare

@extremeshok extremeshok released this 04 Jun 19:03

First release.

A dead-simple, single-container CI for GitHub: it watches repos by polling
(outbound only — no webhooks, no inbound ports), runs each repo's .poll-ci.yml
checks in Docker, and reports results as native GitHub commit statuses. One
process, one container, no database, no UI.

Install

Docker (recommended):

docker build -t poll-ci .
docker run -d --restart always \
  -e GITHUB_TOKEN=github_pat_xxx -e REPO=you/repo -e BRANCH=main \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v poll-ci-state:/var/lib/poll-ci \
  poll-ci

Go:

go install github.com/extremeshok/poll-ci@v1.0.0

Or download a prebuilt binary below (needs git and docker on the host).
Verify with poll-ci_v1.0.0_checksums.txt.

See the README for full usage,
configuration, security notes, and examples.