Skip to content

[BUG] Draft release is invisible to read-only publication jobs #1190

Description

@Brad-Edwards

Description

The hardened release workflow creates a draft GitHub Release successfully, then fails before verification because the jobs that inspect that draft have only contents: read permission.

Release Please created the v3.4.0 tag and draft Release, but resolve-release failed at gh release view v3.4.0 with release not found. GitHub documents that only identities with push access can receive draft releases. The job's read-only GITHUB_TOKEN therefore cannot resolve the draft it is required to validate.

This is a workflow-permission failure, not a package, test, or OS-identity implementation failure.

Failed run: https://github.com/OpenRAE/rae/actions/runs/33701243875

Relevant workflow:

resolve-release:
needs: release-please
if: >-
always()
&& ((github.event_name == 'push'
&& needs.release-please.result == 'success'
&& needs.release-please.outputs.release_created == 'true')
|| github.event_name == 'workflow_dispatch')
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
release_sha: ${{ steps.resolve.outputs.release_sha }}
base_sha: ${{ steps.resolve.outputs.base_sha }}
tag: ${{ steps.resolve.outputs.tag }}
release_id: ${{ steps.resolve.outputs.release_id }}
release_is_draft: ${{ steps.resolve.outputs.release_is_draft }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
- name: Resolve and bind the immutable release commit
id: resolve
env:
EVENT_NAME: ${{ github.event_name }}
GH_TOKEN: ${{ github.token }}
INPUT_TAG: ${{ inputs.tag }}
RELEASE_PLEASE_TAG: ${{ needs.release-please.outputs.tag_name }}
RELEASE_PLEASE_SHA: ${{ needs.release-please.outputs.sha }}
run: |
set -euo pipefail
if [ "${EVENT_NAME}" = "workflow_dispatch" ]; then
tag="${INPUT_TAG}"
expected_sha=""
else
tag="${RELEASE_PLEASE_TAG}"
expected_sha="${RELEASE_PLEASE_SHA}"
fi
if [[ ! "${tag}" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then
echo "Expected a stable SemVer release tag such as v1.0.0, got '${tag}'" >&2
exit 1
fi
release_json="$(
gh release view "${tag}" --repo "${GITHUB_REPOSITORY}" \
--json databaseId,isDraft,tagName
)"

Draft visibility rule: https://docs.github.com/en/rest/releases/releases#list-releases

Introduced by the exact-SHA release hardening in #1138.

Steps to reproduce

  1. Configure Release Please with draft: true and merge a release PR into main.

  2. Allow the release-please job, which has contents: write, to create the tag and draft Release.

  3. In a subsequent job with contents: read, run:

    gh release view v3.4.0 --repo OpenRAE/rae --json databaseId,isDraft,tagName
  4. Observe release not found even though the draft Release exists and is visible to a push-capable identity.

The current v3.4.0 run reproduces this at commit e0f6325428f26b20e971a7ccce6471e94d689435.

Expected behavior

The publication graph should be able to resolve and validate the exact draft Release created by Release Please, run the exact-SHA verification and required container gate, build and smoke-test the distributions, publish them to PyPI, attach the tested artifacts, and finalize that same numeric GitHub Release.

The fix must retain the anti-race, exact-SHA, numeric-release-ID, artifact-identity, and retry-safety guarantees introduced by #1138.

Actual behavior

resolve-release has contents: read. Its draft lookup returns release not found, so set -euo pipefail terminates the job. All downstream verification, build, PyPI, attachment, finalization, and dev-sync jobs are skipped.

There is a second instance of the same permission mismatch: publish-pypi also has contents: read and re-runs gh release view against the still-draft Release immediately before PyPI publication. Fixing only resolve-release is therefore expected to move the same failure downstream.

The draft Release remains unpublished and PyPI remains on 3.3.0.

Environment

  • RAES SDL version: N/A — repository release workflow
  • Commit: e0f6325428f26b20e971a7ccce6471e94d689435
  • Python version: N/A at failure point
  • OS: GitHub-hosted Ubuntu 24.04 runner

Minimal input

resolve-release:
  permissions:
    contents: read
  steps:
    - env:
        GH_TOKEN: ${{ github.token }}
      run: gh release view v3.4.0 --repo OpenRAE/rae --json databaseId,isDraft,tagName

Acceptance criteria

  • resolve-release can inspect and bind the Release Please-created draft to its numeric Release ID, tag, and exact commit SHA.
  • The pre-PyPI identity revalidation can inspect that same draft after any protected-environment wait.
  • No job relying on read-only draft visibility remains in the publication path.
  • Exact-SHA verification, required unskipped container tests, single-build artifact reuse, tag dereferencing, numeric-ID finalization, artifact byte matching, and retry safety remain enforced.
  • Workflow tests cover the permission/visibility requirement for every draft lookup, not only the command structure.
  • The existing v3.4.0 draft can be resumed or safely republished without changing its bound commit or publishing duplicate artifacts.
  • A successful run publishes the 3.4.0 wheel and sdist to PyPI and makes the corresponding GitHub Release public.

Downstream impact

Brad-Edwards/aptl#918 is waiting for a published RAES release containing #1077. The required implementation is present in the v3.4.0 tag, but APTL cannot consume it through its published, hashed dependency path until this release completes.

Activity

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions