Skip to content

ci: automate release pipeline (draft release, PyPI trigger, e2e skip fixes)#416

Open
jacalata wants to merge 10 commits into
tableau:developmentfrom
jacalata:jac/release-automation
Open

ci: automate release pipeline (draft release, PyPI trigger, e2e skip fixes)#416
jacalata wants to merge 10 commits into
tableau:developmentfrom
jacalata:jac/release-automation

Conversation

@jacalata

@jacalata jacalata commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Closes #232

Summary

Automates the release pipeline so that merging to `main` is the only manual step beyond reviewing and publishing a draft.

New file: `release-on-merge.yml`

Triggers on push to `main`. Computes the next patch version from the last strict semver tag (`grep -E '^v[0-9]+.[0-9]+.[0-9]+$'`), pushes the tag (which triggers `package.yml` to build Windows/macOS/Linux binaries and attach them to the release), and creates a draft GitHub release with auto-generated notes. Fails loudly if no prior tag is found rather than silently defaulting to a potentially-colliding version.

Modified: `publish-pypi.yml`

  • Removed dead `push: tags: 'pypi'` trigger — this was a literal tag name match (not a glob) that created a secret publish path bypassing the draft-release gate
  • Added `release: [published]` trigger — clicking "Publish release" in the GitHub UI now automatically uploads to PyPI
  • Made publish conditionals explicit using `github.event_name` (no implicit null coercion)

Modified: `run-e2-tests.yml`

  • Added `workflow_call` interface (typed inputs + secrets) so the suite can be called from other workflows
  • Moved credentials into `env:` vars (security: avoids shell injection; GitHub masks secrets placed in env)
  • Added optional boolean inputs for `server_admin`, `site_admin`, `project_admin`, `extract_encryption_enabled` so callers can enable the relevant test groups for their account permissions

Modified: `package.yml`

  • Removed `promote: true` — binaries attach to the draft release without auto-publishing it

Modified: `online_tests.py` and `setup_e2e.py`

  • `site_admin = False` to match actual account permissions (was causing 4 group tests to run and hit 403 instead of skipping)
  • Skip guard on `test_delete_extract` (requires extract encryption not available on test site)
  • Permission flags (`server_admin`, `site_admin`, etc.) now read from env vars so they can be set via workflow inputs without editing the file
  • Suppress argv printing when login credentials (PAT) are present to prevent token leak in CI logs
  • `get_login_args()` returns `None` when `credentials.py` is absent; `_test_command` skips gracefully instead of crashing with `AttributeError`

Modified: `check-coverage.yml`

  • Added `continue-on-error: true` to the PR comment step — `MishaKav/pytest-coverage-comment` started failing on fork PRs due to read-only `GITHUB_TOKEN` permissions; coverage is still collected, only the comment post is allowed to fail

New release checklist (after this merges)

  1. Merge `development → main` PR (human approval required)
  2. `release-on-merge.yml` auto-runs: pushes tag → binary builds start
  3. Edit the draft release notes in GitHub UI
  4. Click Publish release → PyPI upload fires automatically

Security review findings addressed

  • Finding A: Removed `push: tags: 'pypi'` secret publish path
  • Finding B: Strict semver regex filter prevents malformed-tag arithmetic failure
  • Finding C: Explicit `github.event_name` conditionals replace implicit null coercion
  • Finding D: Tracked in issue security: migrate PyPI publish to Trusted Publishing (OIDC) #417 (PyPI trusted publishing / OIDC)
  • Finding E: PAT suppressed from argv print in `online_tests.py`

Test plan

  • YAML lint: all changed workflow files pass
  • `black` formatting clean
  • e2e tests locally: 30 passed, 10 skipped, 0 failed
  • `release-on-merge.yml` fired correctly on fork push to main: created draft `v2.0.1`, pushed tag, all steps green in 7s

🤖 Generated with Claude Code

dependabot Bot and others added 10 commits June 7, 2026 21:50
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v4...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
- release-on-merge.yml: on push to main, auto-computes next patch
  version, pushes the git tag (which triggers package.yml to build
  binaries), and creates a draft GitHub release with auto-generated
  notes for human review before publishing
- publish-pypi.yml: add release:published trigger so clicking
  "Publish release" in GitHub UI automatically uploads to PyPI;
  fix is_draft conditionals to work when triggered without inputs
- run-e2-tests.yml: add workflow_call interface (inputs + secrets)
  so the e2e suite can be called from other workflows; move
  credentials to env vars to avoid shell injection
- online_tests.py: set site_admin=False to match actual account
  permissions; add skip guard on test_delete_extract (requires
  extract encryption, not available on this site)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Binaries are now uploaded to the draft release created by
release-on-merge.yml without auto-publishing it. Release stays draft
until manually published, which then triggers PyPI upload.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- publish-pypi.yml: remove dead `push: tags: 'pypi'` trigger (secret
  publish path bypassing the draft-release gate); make publish
  conditionals explicit using github.event_name so the trigger surface
  is unambiguous rather than relying on null coercion
- release-on-merge.yml: filter tags to strict semver regex before
  sorting (prevents arithmetic failure on malformed tags); fail loudly
  if no prior tag exists instead of silently defaulting to v2.0.1;
  align checkout to actions/checkout@v7
- online_tests.py: suppress argv printing when login args (including
  PAT token) are present, preventing credential leak in CI logs

Tracking: tableau#417 (PyPI trusted publishing / OIDC)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MishaKav/pytest-coverage-comment@main updated and now fails with
permission denied on fork PRs (GITHUB_TOKEN is read-only for pull_request
events from forks). Coverage is still collected and reported; only the
PR comment step fails. Mark it continue-on-error so CI stays green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously server_admin/site_admin/project_admin/extract_encryption_enabled
were hardcoded in online_tests.py. Now they are read from env vars
(E2E_SITE_ADMIN, E2E_SERVER_ADMIN, E2E_PROJECT_ADMIN, E2E_EXTRACT_ENCRYPTION)
so callers can enable the relevant test groups for their account permissions.

workflow_dispatch: adds optional boolean choice inputs for each flag
workflow_call: adds optional boolean inputs (default false)
online_tests.py: reads flags from env via _env_bool(), defaults unchanged

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously get_login_args() raised AttributeError when credentials.py
was not present (ImportError silently set credentials = {}). Now returns
None and _test_command skips with a clear message instead of crashing.
Also removes redundant second call to get_login_args() in _test_command.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Automates the release pipeline by creating a draft GitHub Release and tag on merges to main, publishing to PyPI on “Release published”, and improving e2e workflow reusability/skip behavior.

Changes:

  • Added release-on-merge.yml to auto-tag and create a draft release on pushes to main.
  • Updated PyPI publishing to trigger on GitHub Release publication (and removed the literal pypi tag trigger).
  • Extended e2e workflow inputs and adjusted e2e test code to use env-configured permission flags and skip more gracefully.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/e2e/setup_e2e.py Makes get_login_args() return None when credentials.py is absent (but needs env fallback to keep CI e2e running).
tests/e2e/online_tests.py Reads permission flags from env and skips gracefully when credentials are unavailable; avoids printing argv when login args include sensitive values.
.github/workflows/run-tests.yml Bumps actions/checkout major version.
.github/workflows/run-e2-tests.yml Adds workflow_call and typed inputs/secrets; passes creds/flags via env; bumps actions/checkout major version.
.github/workflows/release-on-merge.yml New workflow to compute next patch tag, push it, and create a draft GitHub release with generated notes.
.github/workflows/publish-pypi.yml Switches publishing trigger to release: published, removes push: tags: pypi, and tightens publish conditionals; bumps actions/checkout major version.
.github/workflows/package.yml Removes promote: true, bumps actions/checkout major version, and bumps actions/upload-artifact major version.
.github/workflows/generate-metadata.yml Bumps actions/checkout major version.
.github/workflows/codeql-analysis.yml Bumps actions/checkout major version.
.github/workflows/check-coverage.yml Bumps actions/checkout major version; makes coverage comment step continue-on-error.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/e2e/setup_e2e.py
Comment on lines 51 to 55
def get_login_args():
if not _has_credentials:
return None
return [
"--server",
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.

2 participants