Skip to content

c3_ci: act image-pull auth failure is reported as a job failure with 'unparsed' output #173

Open

Description

@drknowhow

Symptom

tests/test_ci_act.py::TestActIntegration::test_runs_a_linux_job_and_reports_a_clean_failure fails locally:

AssertionError: 'unparsed' != 'ruff'

It reproduces on a clean main (unrelated to #171/#172 — verified by stashing). It is local-only: the class is @unittest.skipUnless(ACT_READY, ...), so GitHub CI never runs it.

Root cause — not the parser

The container never starts, so the step that echoes the ruff line never runs, so there is nothing to parse. From the run's own log:

[CI/lint] 🚀  Start image=catthehacker/ubuntu:act-latest
[CI/lint]   🐳  docker pull image=catthehacker/ubuntu:act-latest platform= username= forcePull=true
[CI/lint] using DockerAuthConfig authentication for docker pull
[CI/lint] Error response from daemon: authentication required - incorrect username or password
[CI/lint]   ❌  Failure - Set up job
[CI/lint] 🏁  Job failed

docker pull catthehacker/ubuntu:act-latest from the CLI succeeds on the same machine (image present, "up to date"). The difference is that act sends the stored Docker Hub credential (~/.docker/config.json → credsStore: desktop, an auths entry for https://index.docker.io/v1/) where the CLI sends none for a public image — a stale/expired stored token turns a public pull into an auth error. docker logout clears it.

ci_failures.parse("app/thing.py:14:5: F401 unused import") returns ruff correctly, so the parser is fine.

The C3 defects behind it

  1. A setup-phase failure is reported as an ordinary job failure. services/ci_runner.py parses the log with ci_failures.parse whenever status in (FAILED, TIMEOUT), so an image-pull failure surfaces as parser: unparsed with a log tail. A user asking c3_ci(action='failures') gets "0 parsed failures" for what is really "the runner image could not be pulled". It should be recognised (Error response from daemon, ❌ Failure - Set up job, authentication required) and reported as a container-setup failure with that reason.
  2. ACT_READY / c3_ci doctor check that act and Docker exist, not that a runner image can be obtained. On this machine doctor reports the act engine available while every act job fails at setup. The readiness probe should cover image availability so the integration test skips honestly and doctor warns.

Environment

Windows 11, Docker 29.6.2, act 0.2.89, C3 2.128.1.

Activity

  1. drknowhow commented on Sep 8, 2026

    @drknowhow
    OwnerAuthor

    Confirmed by remedy: after docker logout cleared the stale index.docker.io entry, act pulls the runner image and tests/test_ci_act.py is 30/30 green on this machine. The parser was never at fault.

    The two defects this exposed still stand:

    1. A container-setup failure (image pull refused) is reported as an ordinary job failure with parser: unparsed, so c3_ci(action='failures') answers "0 parsed failures" for "the runner image could not be pulled".
    2. ACT_READY / c3_ci doctor check that act and Docker exist but not that a runner image can be obtained, so doctor called the act engine available while every act job failed at setup — and the integration test failed instead of skipping.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions