Skip to content

ci: do not attempt a Docker Hub push when registry credentials are absent - #1383

Open
minguyen9988 wants to merge 2 commits into
Altinity:2.10.0from
minguyen9988:fix/fork-pr-ci-docker-push-without-credentials
Open

ci: do not attempt a Docker Hub push when registry credentials are absent#1383
minguyen9988 wants to merge 2 commits into
Altinity:2.10.0from
minguyen9988:fix/fork-pr-ci-docker-push-without-credentials

Conversation

@minguyen9988

Copy link
Copy Markdown
Collaborator

Problem

The Pull Request Pipeline fails at build-kafka-lightweight / build for every fork-originated PR, before a single test runs:

ERROR: failed to push altinityinfra/clickhouse-sink-connector:<tag>-lt:
  401 Unauthorized: access token has insufficient scopes

Because every downstream job depends on this one, the entire pipeline is SKIPPED and the PR shows red for a reason unrelated to its contents.

Cause

GitHub withholds repository secrets from workflows triggered by a fork, so DOCKERHUB_USERNAME is empty. The login step handles this correctly — it is already guarded:

- name: Login to Docker Hub
  uses: docker/login-action@v2
  if: ${{ env.DOCKERHUB_USERNAME != '' }}

The lightweight image build that follows is not guarded, and runs:

docker buildx build . ... --push ...

unconditionally. With the login skipped, the push reaches Docker Hub unauthenticated and 401s.

Note that the Kafka image a few steps above already gets this right: it builds locally, then pushes in a separate step carrying the same env.DOCKERHUB_USERNAME != '' guard as the login. Only the lightweight path conflates build and push into one unguarded step.

Fix

Apply the same treatment to the lightweight image:

  • the existing multi-arch --push build is gated on DOCKERHUB_USERNAME != '', matching the login it depends on
  • a second build, gated on the inverse, uses --load instead of --push, so the build is still validated and the image tarball the downstream test jobs consume is still produced

The credentialed path — pushes from the main repo, releases, workflow_dispatch — is byte-for-byte unchanged.

The no-credentials path is single-platform because --load cannot export a multi-platform manifest. linux/amd64 matches what the test runners execute on.

Verification

The workflow parses as valid YAML, and the two if: conditions are mutually exclusive, so exactly one of the two build steps runs in either case:

Login to Docker Hub                                   if: env.DOCKERHUB_USERNAME != ''
Build Docker image (Lightweight)                      if: env.DOCKERHUB_USERNAME != ''
Build Docker image (Lightweight, no registry creds)   if: env.DOCKERHUB_USERNAME == ''

Why this is worth fixing

Right now an external contributor cannot get a green pipeline, and a maintainer has to re-run the workflow with secrets before the tests report anything meaningful. That makes fork PR review slower and trains reviewers to disregard a red build — which is exactly when a genuine failure gets missed.

…sent

The Pull Request Pipeline fails at build-kafka-lightweight for every
fork-originated PR, before a single test runs:

  ERROR: failed to push altinityinfra/clickhouse-sink-connector:<tag>-lt:
    401 Unauthorized: access token has insufficient scopes

GitHub withholds repository secrets from workflows triggered by a fork, so
DOCKERHUB_USERNAME is empty and the Login to Docker Hub step is correctly
skipped by its existing guard. The lightweight image build that follows is
not guarded: it runs docker buildx build ... --push unconditionally, so it
reaches Docker Hub unauthenticated and 401s. Because every downstream job
needs this one, the whole pipeline is SKIPPED and the PR shows red for a
reason unrelated to its contents.

The Kafka image a few steps above already gets this right -- it builds
locally and pushes in a separate step guarded by the same condition as the
login. This applies the same treatment to the lightweight image:

  - the existing multi-arch push build is gated on DOCKERHUB_USERNAME != EMPTY,
    matching the login it depends on
  - a second build, gated on the inverse, builds with --load instead of
    --push so the build is still validated and the tarball the downstream
    test jobs consume is still produced

The credentialed path is unchanged. The no-credentials path is single
platform because --load cannot export a multi-platform manifest; linux/amd64
matches what the test jobs run on.

Verified: the workflow parses as valid YAML and the two conditions are
mutually exclusive, so exactly one build step runs in either case.
@minguyen9988 minguyen9988 changed the title WIP: DO NOT MERGE - ci: do not attempt a Docker Hub push when registry credentials are absent ci: do not attempt a Docker Hub push when registry credentials are absent Aug 14, 2026
Fork-originated pull requests do not receive repository secrets. Two
reporting steps use them unconditionally and fail the job *after* the
work they report on has already succeeded, so a fully green test run is
reported as a red check.

Upload artifacts to Altinity Test Reports S3 bucket
  Runs `aws s3 cp` with AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY. Its
  existing condition tests only for fork-ness, which selects exactly the
  runs where those secrets are empty, so on a fork PR the upload can
  only ever fail. Observed on PR Altinity#1383, whose diff touches nothing but
  .github/workflows/docker-build.yml: steps 1-12 including "Run testflows
  tests" all succeed and step 13 "Upload artifacts to Altinity Test
  Reports S3 bucket" fails the job.

  The condition now also requires the credential to be present, matching
  how docker-build.yml already gates its registry login on
  DOCKERHUB_USERNAME. AWS_ACCESS_KEY_ID is surfaced at workflow level so
  the step's own `if:` can read it -- a step's own `env:` block is not
  available to that step's `if:` expression. The credentialed path is
  unchanged. The artefacts remain attached to the run by the
  upload-artifact step that follows, so nothing is lost on forks.

Publish Test Report
  mikepenz/action-junit-report@v4 creates a check run, which a fork PR's
  read-only GITHUB_TOKEN cannot do; the step dies with "Failed to create
  checks using the provided token. (HttpError: Resource not accessible by
  integration)" and masks the very test result it was asked to report.
  It now falls back to annotations on forks. fail_on_failure stays
  enabled on both paths: a genuine test failure must still fail the job.

Affected: testflows-sink-connector-lightweight.yml (2 steps),
testflows-sink-connector-lightweight-arm.yml (2 steps),
testflows-sink-connector-kafka.yml (1 step),
sink-connector-lightweight-tests.yml (1 step).

Verified: all four workflows parse as YAML, and every `aws s3 cp` step in
the tree is confirmed to carry the credential guard.

Jinja-Render-Check: rendered=4; formats=yaml; result=pass
minguyen9988 added a commit to minguyen9988/clickhouse-sink-connector that referenced this pull request Aug 17, 2026
Fork-originated pull requests do not receive repository secrets. Two
reporting steps use them unconditionally and fail the job *after* the
work they report on has already succeeded, so a fully green test run is
reported as a red check.

Upload artifacts to Altinity Test Reports S3 bucket
  Runs `aws s3 cp` with AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY. Its
  existing condition tests only for fork-ness, which selects exactly the
  runs where those secrets are empty, so on a fork PR the upload can
  only ever fail. Observed on PR Altinity#1383, whose diff touches nothing but
  .github/workflows/docker-build.yml: steps 1-12 including "Run testflows
  tests" all succeed and step 13 "Upload artifacts to Altinity Test
  Reports S3 bucket" fails the job.

  The condition now also requires the credential to be present, matching
  how docker-build.yml already gates its registry login on
  DOCKERHUB_USERNAME. AWS_ACCESS_KEY_ID is surfaced at workflow level so
  the step's own `if:` can read it -- a step's own `env:` block is not
  available to that step's `if:` expression. The credentialed path is
  unchanged. The artefacts remain attached to the run by the
  upload-artifact step that follows, so nothing is lost on forks.

Publish Test Report
  mikepenz/action-junit-report@v4 creates a check run, which a fork PR's
  read-only GITHUB_TOKEN cannot do; the step dies with "Failed to create
  checks using the provided token. (HttpError: Resource not accessible by
  integration)" and masks the very test result it was asked to report.
  It now falls back to annotations on forks. fail_on_failure stays
  enabled on both paths: a genuine test failure must still fail the job.

Affected: testflows-sink-connector-lightweight.yml (2 steps),
testflows-sink-connector-lightweight-arm.yml (2 steps),
testflows-sink-connector-kafka.yml (1 step),
sink-connector-lightweight-tests.yml (1 step).

Verified: all four workflows parse as YAML, and every `aws s3 cp` step in
the tree is confirmed to carry the credential guard.

Jinja-Render-Check: rendered=4; formats=yaml; result=pass
(cherry picked from commit 67d05e6)
minguyen9988 added a commit to minguyen9988/clickhouse-sink-connector that referenced this pull request Aug 17, 2026
Fork-originated pull requests do not receive repository secrets. Two
reporting steps use them unconditionally and fail the job *after* the
work they report on has already succeeded, so a fully green test run is
reported as a red check.

Upload artifacts to Altinity Test Reports S3 bucket
  Runs `aws s3 cp` with AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY. Its
  existing condition tests only for fork-ness, which selects exactly the
  runs where those secrets are empty, so on a fork PR the upload can
  only ever fail. Observed on PR Altinity#1383, whose diff touches nothing but
  .github/workflows/docker-build.yml: steps 1-12 including "Run testflows
  tests" all succeed and step 13 "Upload artifacts to Altinity Test
  Reports S3 bucket" fails the job.

  The condition now also requires the credential to be present, matching
  how docker-build.yml already gates its registry login on
  DOCKERHUB_USERNAME. AWS_ACCESS_KEY_ID is surfaced at workflow level so
  the step's own `if:` can read it -- a step's own `env:` block is not
  available to that step's `if:` expression. The credentialed path is
  unchanged. The artefacts remain attached to the run by the
  upload-artifact step that follows, so nothing is lost on forks.

Publish Test Report
  mikepenz/action-junit-report@v4 creates a check run, which a fork PR's
  read-only GITHUB_TOKEN cannot do; the step dies with "Failed to create
  checks using the provided token. (HttpError: Resource not accessible by
  integration)" and masks the very test result it was asked to report.
  It now falls back to annotations on forks. fail_on_failure stays
  enabled on both paths: a genuine test failure must still fail the job.

Affected: testflows-sink-connector-lightweight.yml (2 steps),
testflows-sink-connector-lightweight-arm.yml (2 steps),
testflows-sink-connector-kafka.yml (1 step),
sink-connector-lightweight-tests.yml (1 step).

Verified: all four workflows parse as YAML, and every `aws s3 cp` step in
the tree is confirmed to carry the credential guard.

Jinja-Render-Check: rendered=4; formats=yaml; result=pass
(cherry picked from commit 67d05e6)
minguyen9988 added a commit to minguyen9988/clickhouse-sink-connector that referenced this pull request Aug 17, 2026
Fork-originated pull requests do not receive repository secrets. Two
reporting steps use them unconditionally and fail the job *after* the
work they report on has already succeeded, so a fully green test run is
reported as a red check.

Upload artifacts to Altinity Test Reports S3 bucket
  Runs `aws s3 cp` with AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY. Its
  existing condition tests only for fork-ness, which selects exactly the
  runs where those secrets are empty, so on a fork PR the upload can
  only ever fail. Observed on PR Altinity#1383, whose diff touches nothing but
  .github/workflows/docker-build.yml: steps 1-12 including "Run testflows
  tests" all succeed and step 13 "Upload artifacts to Altinity Test
  Reports S3 bucket" fails the job.

  The condition now also requires the credential to be present, matching
  how docker-build.yml already gates its registry login on
  DOCKERHUB_USERNAME. AWS_ACCESS_KEY_ID is surfaced at workflow level so
  the step's own `if:` can read it -- a step's own `env:` block is not
  available to that step's `if:` expression. The credentialed path is
  unchanged. The artefacts remain attached to the run by the
  upload-artifact step that follows, so nothing is lost on forks.

Publish Test Report
  mikepenz/action-junit-report@v4 creates a check run, which a fork PR's
  read-only GITHUB_TOKEN cannot do; the step dies with "Failed to create
  checks using the provided token. (HttpError: Resource not accessible by
  integration)" and masks the very test result it was asked to report.
  It now falls back to annotations on forks. fail_on_failure stays
  enabled on both paths: a genuine test failure must still fail the job.

Affected: testflows-sink-connector-lightweight.yml (2 steps),
testflows-sink-connector-lightweight-arm.yml (2 steps),
testflows-sink-connector-kafka.yml (1 step),
sink-connector-lightweight-tests.yml (1 step).

Verified: all four workflows parse as YAML, and every `aws s3 cp` step in
the tree is confirmed to carry the credential guard.

Jinja-Render-Check: rendered=4; formats=yaml; result=pass
(cherry picked from commit 67d05e6)
minguyen9988 added a commit to minguyen9988/clickhouse-sink-connector that referenced this pull request Aug 17, 2026
Fork-originated pull requests do not receive repository secrets. Two
reporting steps use them unconditionally and fail the job *after* the
work they report on has already succeeded, so a fully green test run is
reported as a red check.

Upload artifacts to Altinity Test Reports S3 bucket
  Runs `aws s3 cp` with AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY. Its
  existing condition tests only for fork-ness, which selects exactly the
  runs where those secrets are empty, so on a fork PR the upload can
  only ever fail. Observed on PR Altinity#1383, whose diff touches nothing but
  .github/workflows/docker-build.yml: steps 1-12 including "Run testflows
  tests" all succeed and step 13 "Upload artifacts to Altinity Test
  Reports S3 bucket" fails the job.

  The condition now also requires the credential to be present, matching
  how docker-build.yml already gates its registry login on
  DOCKERHUB_USERNAME. AWS_ACCESS_KEY_ID is surfaced at workflow level so
  the step's own `if:` can read it -- a step's own `env:` block is not
  available to that step's `if:` expression. The credentialed path is
  unchanged. The artefacts remain attached to the run by the
  upload-artifact step that follows, so nothing is lost on forks.

Publish Test Report
  mikepenz/action-junit-report@v4 creates a check run, which a fork PR's
  read-only GITHUB_TOKEN cannot do; the step dies with "Failed to create
  checks using the provided token. (HttpError: Resource not accessible by
  integration)" and masks the very test result it was asked to report.
  It now falls back to annotations on forks. fail_on_failure stays
  enabled on both paths: a genuine test failure must still fail the job.

Affected: testflows-sink-connector-lightweight.yml (2 steps),
testflows-sink-connector-lightweight-arm.yml (2 steps),
testflows-sink-connector-kafka.yml (1 step),
sink-connector-lightweight-tests.yml (1 step).

Verified: all four workflows parse as YAML, and every `aws s3 cp` step in
the tree is confirmed to carry the credential guard.

Jinja-Render-Check: rendered=4; formats=yaml; result=pass
(cherry picked from commit 67d05e6)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant