Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
4ba86e9
docs: add golden-vector parity spec and implementation plan (PLT-1735)
kurodo3[bot] Jun 18, 2026
267fd1a
docs: sync corrected implementation plan (PLT-1735)
kurodo3[bot] Jun 18, 2026
18bac84
feat: add golden fixture tests/golden/include_metadata_v0.3.json (PLT…
kurodo3[bot] Jun 19, 2026
b797287
test: add cross-language golden parity tests for include_metadata (PL…
kurodo3[bot] Jun 19, 2026
c0384a1
fix: add ensure_ascii=False to _serialized_schema for non-ASCII field…
kurodo3[bot] Jun 19, 2026
02b8981
ci: add golden-sync-check drift gate (PLT-1735)
kurodo3[bot] Jun 19, 2026
f079780
ci: add manual release workflow (PLT-1735)
kurodo3[bot] Jun 19, 2026
8915879
fix: update fixture description, add defensive error check to golden-…
kurodo3[bot] Jun 19, 2026
d57d90a
fix: address PR review — pin actions to full SHAs, add permissions bl…
kurodo3[bot] Jun 19, 2026
633db5f
fix: address Copilot review — spec accuracy, fork guard, version norm…
kurodo3[bot] Jun 20, 2026
e09e0a0
fix: correct release architecture in spec — crates.io for Rust, no ma…
kurodo3[bot] Jun 20, 2026
f4e9f22
fix: update spec — crates.io uses trusted publishing, no API token ne…
kurodo3[bot] Jun 20, 2026
0c3b7c9
fix: assert key_reorder fixture invariant; add pull-requests: read to…
kurodo3[bot] Jun 20, 2026
e0e918d
fix: open fixture with explicit utf-8 encoding
kurodo3[bot] Jun 21, 2026
9ce01f6
refactor: merge publish.yml into release.yml; pin all action SHAs
kurodo3[bot] Jun 21, 2026
f256d6c
fix: defer tag push until after build; update docs for merged release…
kurodo3[bot] Jun 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 53 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ on:
pull_request:
branches: [main]

permissions:
contents: read

Comment on lines +9 to +11

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit 0c3b7c9. Added an explicit permissions block to the dependency-review job with contents: read and pull-requests: read. The workflow-level block stays at contents: read only; the extra permission is scoped to only the job that needs it.

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Install uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5

- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}
Expand All @@ -30,10 +33,10 @@ jobs:
license-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Install uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5

- name: Install dependencies
run: uv sync --dev
Expand All @@ -47,11 +50,14 @@ jobs:
dependency-review:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
permissions:
contents: read
pull-requests: read # required by actions/dependency-review-action to fetch PR diff
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Dependency review
uses: actions/dependency-review-action@v4
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4
with:
deny-licenses: >-
GPL-2.0-only, GPL-2.0-or-later,
Expand All @@ -60,3 +66,44 @@ jobs:
LGPL-2.0-only, LGPL-2.0-or-later,
LGPL-2.1-only, LGPL-2.1-or-later,
LGPL-3.0-only, LGPL-3.0-or-later

golden-sync-check:
runs-on: ubuntu-latest
# Secrets are not available to fork PRs, so skip the check there.
# Internal PRs and pushes to main always run it.
if: >
github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository
permissions:
contents: read
steps:
Comment on lines +70 to +79

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Added a job-level if guard to golden-sync-check that skips the job entirely for PRs from forks (github.event.pull_request.head.repo.full_name == github.repository must be true). Pushes to main and internal PRs still always run it.

- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3
with:
app-id: ${{ secrets.STARFIX_APP_ID }}
private-key: ${{ secrets.STARFIX_APP_PRIVATE_KEY }}
repositories: starfix

- name: Fetch authoritative fixture from starfix
run: |
gh api repos/nauticalab/starfix/contents/tests/golden/include_metadata_v0.3.json \
--jq '.content' | base64 -d > /tmp/upstream.json
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}

- name: Fail on fixture drift
run: |
if [ ! -s /tmp/upstream.json ]; then
echo "ERROR: Could not fetch fixture from nauticalab/starfix main."
echo "Ensure nauticalab/starfix#main has tests/golden/include_metadata_v0.3.json"
echo "(starfix PLT-1735 PR must be merged before this check can pass)"
exit 1
fi
if ! diff tests/golden/include_metadata_v0.3.json /tmp/upstream.json; then
echo "ERROR: tests/golden/include_metadata_v0.3.json has drifted from nauticalab/starfix main."
echo "Copy the updated fixture from the starfix repo and commit it."
exit 1
fi
104 changes: 0 additions & 104 deletions .github/workflows/publish.yml

This file was deleted.

150 changes: 150 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
name: release

on:
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g. 0.3.0)'
required: true
type: string

# Minimal default; individual jobs declare only what they need.
permissions:
contents: read

jobs:
test:
name: Test (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Install uv
uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5

- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}

- name: Install dependencies
run: uv sync --dev --python ${{ matrix.python-version }}

- name: Run tests
run: uv run --python ${{ matrix.python-version }} pytest tests/ -v

build:
name: Build distribution
needs: test
runs-on: ubuntu-latest
permissions:
contents: write # required to push the release tag
outputs:
version: ${{ steps.normalize.outputs.version }}
steps:
# Strip a leading 'v' once here; all downstream steps use the output.
- name: Normalize version
id: normalize
run: |
VERSION="${{ inputs.version }}"
VERSION="${VERSION#v}"
echo "version=${VERSION}" >> "${GITHUB_OUTPUT}"

- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0 # required: hatch-vcs derives the package version from git tags

- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

# Create the tag locally so hatch-vcs can derive the package version during
# `uv build`. The tag is pushed to origin only AFTER a successful build to
# avoid leaving a dangling remote tag if the build fails.
- name: Create local release tag
run: git tag "v${{ steps.normalize.outputs.version }}"

- name: Install uv
uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5

- name: Build wheel and sdist
run: uv build

# Fail fast if the tag already exists on origin (e.g. re-running the workflow
# for the same version) before attempting to push, to surface a clear error
# rather than a confusing "already exists" git message.
- name: Push release tag
run: |
if git ls-remote --exit-code --tags origin \
"refs/tags/v${{ steps.normalize.outputs.version }}" > /dev/null 2>&1; then
echo "ERROR: tag v${{ steps.normalize.outputs.version }} already exists on origin" >&2
exit 1
fi
git push origin "v${{ steps.normalize.outputs.version }}"

- name: Upload dist artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: dist
path: dist/
if-no-files-found: error

# IMPORTANT: The PyPI and TestPyPI Trusted Publisher configurations must reference
# this workflow file (`.github/workflows/release.yml`). If they still point to the
# former `publish.yml`, OIDC token exchange will be rejected by PyPI/TestPyPI.
# Update both configs at https://pypi.org and https://test.pypi.org before running
# this workflow for the first time.
publish-testpypi:
name: Publish → TestPyPI
needs: build
runs-on: ubuntu-latest
environment:
name: testpypi
url: https://test.pypi.org/p/starfix
permissions:
id-token: write # required for OIDC trusted publishing
steps:
- name: Install uv
uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5

- name: Download dist artifact
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: dist
path: dist/

- name: Publish to TestPyPI
run: uv publish --publish-url https://test.pypi.org/legacy/ dist/*

Comment on lines +100 to +121

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in commit f256d6c with a prominent YAML comment block before the publish-testpypi job:

# IMPORTANT: The PyPI and TestPyPI Trusted Publisher configurations must reference
# this workflow file (.github/workflows/release.yml). If they still point to the
# former publish.yml, OIDC token exchange will be rejected by PyPI/TestPyPI.
# Update both configs at https://pypi.org and https://test.pypi.org before running
# this workflow for the first time.

The actual Trusted Publisher reconfiguration is a manual step on pypi.org/test.pypi.org — it can't be done in code.

publish-pypi:
name: Publish → PyPI
needs: [build, publish-testpypi]
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/starfix
permissions:
id-token: write # required for OIDC trusted publishing
contents: write # required for creating the GitHub Release
steps:
- name: Install uv
uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5

- name: Download dist artifact
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: dist
path: dist/

- name: Publish to PyPI
run: uv publish dist/*

- name: Create GitHub Release
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
with:
tag_name: "v${{ needs.build.outputs.version }}"
generate_release_notes: true
files: dist/*
Loading
Loading