oxipng-pybind 10.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. oxipng_pybind-10.1.1/.github/workflows/api-matrix.yml +36 -0
  2. oxipng_pybind-10.1.1/.github/workflows/ci.yml +33 -0
  3. oxipng_pybind-10.1.1/.github/workflows/dependency-health.yml +144 -0
  4. oxipng_pybind-10.1.1/.github/workflows/release-tag.yml +134 -0
  5. oxipng_pybind-10.1.1/.github/workflows/retry-failed-checks.yml +32 -0
  6. oxipng_pybind-10.1.1/.github/workflows/upstream-bump.yml +173 -0
  7. oxipng_pybind-10.1.1/.github/workflows/wheels.yml +316 -0
  8. oxipng_pybind-10.1.1/.gitignore +15 -0
  9. oxipng_pybind-10.1.1/.gitlint +9 -0
  10. oxipng_pybind-10.1.1/.markdownlint-cli2.jsonc +7 -0
  11. oxipng_pybind-10.1.1/.pre-commit-config.yaml +66 -0
  12. oxipng_pybind-10.1.1/AGENTS.md +12 -0
  13. oxipng_pybind-10.1.1/CLAUDE.md +124 -0
  14. oxipng_pybind-10.1.1/CONTRIBUTING.md +82 -0
  15. oxipng_pybind-10.1.1/CONVENTIONS.md +89 -0
  16. oxipng_pybind-10.1.1/Cargo.lock +410 -0
  17. oxipng_pybind-10.1.1/Cargo.toml +22 -0
  18. oxipng_pybind-10.1.1/LICENSE +22 -0
  19. oxipng_pybind-10.1.1/Makefile +164 -0
  20. oxipng_pybind-10.1.1/PKG-INFO +67 -0
  21. oxipng_pybind-10.1.1/PYPI-DESCRIPTION.md +39 -0
  22. oxipng_pybind-10.1.1/README.md +84 -0
  23. oxipng_pybind-10.1.1/THIRD_PARTY_NOTICES.md +188 -0
  24. oxipng_pybind-10.1.1/deny.toml +26 -0
  25. oxipng_pybind-10.1.1/docs/README.md +44 -0
  26. oxipng_pybind-10.1.1/docs/api-surface/oxipng-10.1.1.toml +116 -0
  27. oxipng_pybind-10.1.1/docs/architecture/api-compatibility.md +75 -0
  28. oxipng_pybind-10.1.1/docs/architecture/options-surface.md +86 -0
  29. oxipng_pybind-10.1.1/docs/architecture/overview.md +105 -0
  30. oxipng_pybind-10.1.1/docs/plans/unfinished-work.md +57 -0
  31. oxipng_pybind-10.1.1/docs/process/dependency-health.md +101 -0
  32. oxipng_pybind-10.1.1/docs/process/github-settings.md +44 -0
  33. oxipng_pybind-10.1.1/docs/process/lint-deviations.md +82 -0
  34. oxipng_pybind-10.1.1/docs/process/local-development.md +51 -0
  35. oxipng_pybind-10.1.1/docs/process/release-artifacts.md +105 -0
  36. oxipng_pybind-10.1.1/docs/process/upstream-bumps.md +113 -0
  37. oxipng_pybind-10.1.1/docs/process/writing-style.md +47 -0
  38. oxipng_pybind-10.1.1/docs/usage/build-from-source.md +90 -0
  39. oxipng_pybind-10.1.1/docs/usage/file-optimization.md +91 -0
  40. oxipng_pybind-10.1.1/docs/usage/memory-optimization.md +83 -0
  41. oxipng_pybind-10.1.1/docs/usage/pyoxipng-migration.md +227 -0
  42. oxipng_pybind-10.1.1/docs/usage/raw-image.md +209 -0
  43. oxipng_pybind-10.1.1/docs/usage/untrusted-input.md +70 -0
  44. oxipng_pybind-10.1.1/oxipng/__init__.py +627 -0
  45. oxipng_pybind-10.1.1/oxipng/__init__.pyi +286 -0
  46. oxipng_pybind-10.1.1/oxipng/_pyoxipng_compat.py +94 -0
  47. oxipng_pybind-10.1.1/oxipng/py.typed +0 -0
  48. oxipng_pybind-10.1.1/pyproject.toml +148 -0
  49. oxipng_pybind-10.1.1/scripts/__init__.py +1 -0
  50. oxipng_pybind-10.1.1/scripts/ai_filter_log.py +59 -0
  51. oxipng_pybind-10.1.1/scripts/audit_github_settings.py +217 -0
  52. oxipng_pybind-10.1.1/scripts/bump_upstream.py +278 -0
  53. oxipng_pybind-10.1.1/scripts/check_wheel_tags.py +105 -0
  54. oxipng_pybind-10.1.1/scripts/classify_dependency_refresh.py +292 -0
  55. oxipng_pybind-10.1.1/scripts/generate_third_party_notices.py +175 -0
  56. oxipng_pybind-10.1.1/scripts/scan_upstream_surface.py +351 -0
  57. oxipng_pybind-10.1.1/scripts/smoke_wheel.py +113 -0
  58. oxipng_pybind-10.1.1/scripts/update_github_actions.py +152 -0
  59. oxipng_pybind-10.1.1/scripts/validate_release_tag.py +151 -0
  60. oxipng_pybind-10.1.1/scripts/verify_release_artifacts.py +194 -0
  61. oxipng_pybind-10.1.1/scripts/verify_release_checks.py +137 -0
  62. oxipng_pybind-10.1.1/scripts/verify_release_version.py +63 -0
  63. oxipng_pybind-10.1.1/src/lib.rs +1254 -0
  64. oxipng_pybind-10.1.1/tests/conftest.py +39 -0
  65. oxipng_pybind-10.1.1/tests/test_api.py +1448 -0
  66. oxipng_pybind-10.1.1/tests/test_bump_upstream.py +523 -0
  67. oxipng_pybind-10.1.1/tests/test_dependency_refresh_classification.py +287 -0
  68. oxipng_pybind-10.1.1/tests/test_docs_examples.py +384 -0
  69. oxipng_pybind-10.1.1/tests/test_github_settings_audit.py +84 -0
  70. oxipng_pybind-10.1.1/tests/test_makefile.py +75 -0
  71. oxipng_pybind-10.1.1/tests/test_real_pngs.py +139 -0
  72. oxipng_pybind-10.1.1/tests/test_release_artifacts.py +175 -0
  73. oxipng_pybind-10.1.1/tests/test_release_checks.py +157 -0
  74. oxipng_pybind-10.1.1/tests/test_release_version.py +38 -0
  75. oxipng_pybind-10.1.1/tests/test_scan_upstream_surface.py +356 -0
  76. oxipng_pybind-10.1.1/tests/test_scripts.py +261 -0
  77. oxipng_pybind-10.1.1/tests/test_third_party_notices.py +167 -0
  78. oxipng_pybind-10.1.1/tests/test_update_github_actions.py +82 -0
  79. oxipng_pybind-10.1.1/tests/test_validate_release_tag.py +225 -0
  80. oxipng_pybind-10.1.1/tests/test_wheel_tags.py +91 -0
  81. oxipng_pybind-10.1.1/tests/test_workflows.py +663 -0
  82. oxipng_pybind-10.1.1/tests/typing_filter_options.py +28 -0
  83. oxipng_pybind-10.1.1/uv.lock +738 -0
@@ -0,0 +1,36 @@
1
+ name: api-matrix
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ branches: [main]
7
+ tags:
8
+ - "v*"
9
+ pull_request:
10
+ branches: [main]
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ public-api:
17
+ name: public api py${{ matrix.python-version }}
18
+ runs-on: ubuntu-latest
19
+ strategy:
20
+ fail-fast: false
21
+ matrix:
22
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
23
+ env:
24
+ UV_PYTHON: ${{ matrix.python-version }}
25
+ steps:
26
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
27
+ - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b
28
+ with:
29
+ version: 0.11.12
30
+ - uses: dtolnay/rust-toolchain@1.95.0
31
+ - name: Sync dependencies
32
+ run: uv sync --locked --group dev
33
+ - name: Build editable extension
34
+ run: uv run --locked --group dev maturin develop
35
+ - name: Run public API tests
36
+ run: uv run --locked --group dev pytest tests/test_api.py -v -ra
@@ -0,0 +1,33 @@
1
+ name: ci
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ branches: [main]
7
+ tags:
8
+ - "v*"
9
+ pull_request:
10
+ branches: [main]
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ ci:
17
+ name: source ci
18
+ runs-on: ubuntu-latest
19
+ env:
20
+ UV_PYTHON: "3.13"
21
+ steps:
22
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
23
+ - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b
24
+ with:
25
+ version: 0.11.12
26
+ - uses: dtolnay/rust-toolchain@1.95.0
27
+ with:
28
+ components: clippy
29
+ - name: Install cargo-deny
30
+ uses: taiki-e/install-action@60ae4ce63c7aeb6e96d7f572c1ec7fafbb17ca80
31
+ with:
32
+ tool: cargo-deny@0.19.7
33
+ - run: make ci
@@ -0,0 +1,144 @@
1
+ name: dependency-health
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ schedule:
6
+ - cron: "31 10 * * 2"
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ prepare:
13
+ name: refresh and verify dependencies
14
+ runs-on: ubuntu-latest
15
+ outputs:
16
+ changed: ${{ steps.changes.outputs.changed }}
17
+ changed-paths: ${{ steps.changes.outputs.paths }}
18
+ release-needed: ${{ steps.classification.outputs.release-needed }}
19
+ release-label: ${{ steps.classification.outputs.label }}
20
+ release-reason: ${{ steps.classification.outputs.reason }}
21
+ env:
22
+ UV_PYTHON: "3.13"
23
+ steps:
24
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
25
+ - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b
26
+ with:
27
+ version: 0.11.12
28
+ - uses: dtolnay/rust-toolchain@1.95.0
29
+ with:
30
+ components: clippy
31
+ - name: Install cargo-deny
32
+ uses: taiki-e/install-action@60ae4ce63c7aeb6e96d7f572c1ec7fafbb17ca80
33
+ with:
34
+ tool: cargo-deny@0.19.7
35
+ - name: Refresh lockfiles
36
+ run: |
37
+ uv lock --upgrade
38
+ cargo update
39
+ - name: Sync refreshed dependencies
40
+ run: uv sync --locked --group dev
41
+ - name: Refresh pre-commit hooks
42
+ run: uv run --locked --group dev pre-commit autoupdate
43
+ - name: Refresh GitHub Actions
44
+ run: uv run --locked --group dev python scripts/update_github_actions.py
45
+ - name: Apply lint and generated-file fixes
46
+ run: make lint-fix
47
+ - name: Generate third-party notices
48
+ run: make third-party-notices
49
+ - name: Run dependency audits
50
+ run: make dependency-audit
51
+ - name: Run CI
52
+ run: make ci
53
+ - name: Check for changes
54
+ id: changes
55
+ run: |
56
+ paths="$({
57
+ git diff --name-only
58
+ git ls-files --others --exclude-standard
59
+ } | sort -u)"
60
+ if [ -z "$paths" ]; then
61
+ echo "changed=false" >> "$GITHUB_OUTPUT"
62
+ else
63
+ echo "changed=true" >> "$GITHUB_OUTPUT"
64
+ {
65
+ echo "paths<<EOF"
66
+ echo "$paths"
67
+ echo "EOF"
68
+ } >> "$GITHUB_OUTPUT"
69
+ fi
70
+ - name: Classify dependency refresh
71
+ id: classification
72
+ if: steps.changes.outputs.changed == 'true'
73
+ run: uv run --locked --group dev python scripts/classify_dependency_refresh.py --base-ref origin/main
74
+ - name: Upload dependency refresh workspace
75
+ if: steps.changes.outputs.changed == 'true'
76
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
77
+ with:
78
+ name: dependency-refresh
79
+ include-hidden-files: true
80
+ path: ${{ steps.changes.outputs.paths }}
81
+
82
+ publish:
83
+ name: open dependency refresh PR
84
+ needs: prepare
85
+ if: needs.prepare.outputs.changed == 'true'
86
+ runs-on: ubuntu-latest
87
+ permissions:
88
+ contents: write
89
+ pull-requests: write
90
+ steps:
91
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
92
+ with:
93
+ persist-credentials: false
94
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
95
+ with:
96
+ name: dependency-refresh
97
+ path: .
98
+ - name: Require dependency refresh token
99
+ env:
100
+ DEPENDENCY_REFRESH_TOKEN: ${{ secrets.DEPENDENCY_REFRESH_TOKEN }}
101
+ run: |
102
+ if [ -z "$DEPENDENCY_REFRESH_TOKEN" ]; then
103
+ echo "DEPENDENCY_REFRESH_TOKEN is required so refresh PRs trigger normal CI." >&2
104
+ exit 1
105
+ fi
106
+ - name: Create pull request
107
+ id: cpr
108
+ uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1
109
+ with:
110
+ token: ${{ secrets.DEPENDENCY_REFRESH_TOKEN }}
111
+ commit-message: "chore: refresh dependency lockfiles"
112
+ title: "chore: refresh dependency lockfiles"
113
+ body: |
114
+ Automated dependency refresh.
115
+
116
+ Verification run in the prepare job:
117
+
118
+ - `uv run --locked --group dev pre-commit autoupdate`
119
+ - `uv run --locked --group dev python scripts/update_github_actions.py`
120
+ - `make lint-fix`
121
+ - `make dependency-audit`
122
+ - `make ci`
123
+
124
+ Release classification:
125
+
126
+ - `${{ needs.prepare.outputs.release-label }}`
127
+ - `${{ needs.prepare.outputs.release-reason }}`
128
+
129
+ `no-release-needed` PRs auto-merge after required checks pass.
130
+ `release-needed` PRs stay open for an explicit wrapper version bump
131
+ before merge.
132
+ branch: automation/dependency-refresh
133
+ delete-branch: true
134
+ labels: dependencies, automated, ${{ needs.prepare.outputs.release-label }}
135
+ add-paths: ${{ needs.prepare.outputs.changed-paths }}
136
+ - name: Enable auto-merge
137
+ if: >-
138
+ needs.prepare.outputs.release-needed == 'false' &&
139
+ steps.cpr.outputs.pull-request-number != '' &&
140
+ contains(fromJSON('["created", "updated"]'), steps.cpr.outputs.pull-request-operation)
141
+ env:
142
+ GH_TOKEN: ${{ secrets.DEPENDENCY_REFRESH_TOKEN }}
143
+ run: |
144
+ gh pr merge "${{ steps.cpr.outputs.pull-request-number }}" --auto --rebase --delete-branch
@@ -0,0 +1,134 @@
1
+ name: release-tag
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ workflow_run:
6
+ workflows: ["ci"]
7
+ types: ["completed"]
8
+ branches: ["main"]
9
+
10
+ permissions:
11
+ contents: read
12
+ actions: read
13
+
14
+ jobs:
15
+ create-release-tag:
16
+ name: create release tag
17
+ runs-on: ubuntu-latest
18
+ if: >-
19
+ github.event_name == 'workflow_dispatch' ||
20
+ github.event.workflow_run.conclusion == 'success'
21
+ permissions:
22
+ contents: write
23
+ actions: read
24
+ steps:
25
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
26
+ with:
27
+ fetch-depth: 0
28
+ persist-credentials: false
29
+ - name: Check automated release eligibility
30
+ id: eligibility
31
+ shell: bash
32
+ run: |
33
+ git fetch --quiet origin main --tags
34
+ git checkout --quiet origin/main
35
+ main_sha="$(git rev-parse HEAD)"
36
+ if [ "${{ github.event_name }}" = "workflow_run" ] &&
37
+ [ "$main_sha" != "${{ github.event.workflow_run.head_sha }}" ]; then
38
+ echo "eligible=false" >> "$GITHUB_OUTPUT"
39
+ echo "latest main commit $main_sha differs from ci head ${{ github.event.workflow_run.head_sha }}"
40
+ exit 0
41
+ fi
42
+ subject="$(git log -1 --pretty=%s)"
43
+ if [ "$subject" != "chore: bump upstream oxipng" ]; then
44
+ echo "eligible=false" >> "$GITHUB_OUTPUT"
45
+ echo "latest main commit is not an automated upstream bump: $subject"
46
+ exit 0
47
+ fi
48
+ before_version="$(
49
+ git show HEAD^:pyproject.toml |
50
+ python -c 'import sys,tomllib; print(tomllib.loads(sys.stdin.read())["project"]["version"])'
51
+ )"
52
+ version="$(
53
+ python -c 'import pathlib,tomllib; print(tomllib.loads(pathlib.Path("pyproject.toml").read_text())["project"]["version"])'
54
+ )"
55
+ if [ "$before_version" = "$version" ]; then
56
+ echo "eligible=false" >> "$GITHUB_OUTPUT"
57
+ echo "project.version did not change"
58
+ exit 0
59
+ fi
60
+ tag="v$version"
61
+ python scripts/validate_release_tag.py --tag "$tag" --skip-main-check --skip-pypi-check
62
+ if git rev-parse "$tag" >/dev/null 2>&1; then
63
+ echo "eligible=false" >> "$GITHUB_OUTPUT"
64
+ echo "tag already exists: $tag"
65
+ exit 0
66
+ fi
67
+ echo "eligible=true" >> "$GITHUB_OUTPUT"
68
+ echo "version=$version" >> "$GITHUB_OUTPUT"
69
+ echo "tag=$tag" >> "$GITHUB_OUTPUT"
70
+ - name: Wait for CI on main commit
71
+ if: steps.eligibility.outputs.eligible == 'true'
72
+ env:
73
+ GH_TOKEN: ${{ github.token }}
74
+ run: |
75
+ sha="$(git rev-parse HEAD)"
76
+ for attempt in $(seq 1 60); do
77
+ conclusion="$(
78
+ gh run list --workflow ci.yml --commit "$sha" \
79
+ --json status,conclusion \
80
+ --jq '.[0] | "\(.status) \(.conclusion)"'
81
+ )"
82
+ case "$conclusion" in
83
+ "completed success") exit 0 ;;
84
+ "completed failure"|"completed cancelled"|"completed timed_out")
85
+ echo "ci failed: $conclusion"
86
+ exit 1
87
+ ;;
88
+ esac
89
+ sleep 30
90
+ done
91
+ echo "timed out waiting for ci"
92
+ exit 1
93
+ - name: Wait for API matrix on main commit
94
+ if: steps.eligibility.outputs.eligible == 'true'
95
+ env:
96
+ GH_TOKEN: ${{ github.token }}
97
+ run: |
98
+ sha="$(git rev-parse HEAD)"
99
+ for attempt in $(seq 1 60); do
100
+ conclusion="$(
101
+ gh run list --workflow api-matrix.yml --commit "$sha" \
102
+ --json status,conclusion \
103
+ --jq '.[0] | "\(.status) \(.conclusion)"'
104
+ )"
105
+ case "$conclusion" in
106
+ "completed success") exit 0 ;;
107
+ "completed failure"|"completed cancelled"|"completed timed_out")
108
+ echo "api-matrix failed: $conclusion"
109
+ exit 1
110
+ ;;
111
+ esac
112
+ sleep 30
113
+ done
114
+ echo "timed out waiting for api-matrix"
115
+ exit 1
116
+ - name: Check PyPI version does not exist
117
+ if: steps.eligibility.outputs.eligible == 'true'
118
+ run: |
119
+ python scripts/validate_release_tag.py \
120
+ --tag "${{ steps.eligibility.outputs.tag }}" \
121
+ --project "oxipng-pybind" \
122
+ --pypi-url "https://pypi.org" \
123
+ --skip-main-check
124
+ - name: Create and push release tag
125
+ if: steps.eligibility.outputs.eligible == 'true'
126
+ env:
127
+ RELEASE_TAG_TOKEN: ${{ secrets.RELEASE_TAG_TOKEN }}
128
+ run: |
129
+ tag="${{ steps.eligibility.outputs.tag }}"
130
+ version="${{ steps.eligibility.outputs.version }}"
131
+ git config user.name "oxipng-pybind release automation"
132
+ git config user.email "github-actions[bot]@users.noreply.github.com"
133
+ git tag -a "$tag" -m "Release oxipng-pybind $version"
134
+ git push "https://x-access-token:${RELEASE_TAG_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" "$tag"
@@ -0,0 +1,32 @@
1
+ name: retry-failed-checks
2
+
3
+ on:
4
+ workflow_run:
5
+ workflows:
6
+ - ci
7
+ - api-matrix
8
+ - wheels
9
+ types:
10
+ - completed
11
+
12
+ permissions:
13
+ actions: write
14
+ contents: read
15
+
16
+ jobs:
17
+ retry:
18
+ name: retry failed jobs once
19
+ if: >-
20
+ github.event.workflow_run.conclusion == 'failure' &&
21
+ github.event.workflow_run.run_attempt == 1
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - name: Wait before retry
25
+ run: sleep 600
26
+ - name: Rerun failed jobs
27
+ env:
28
+ GH_TOKEN: ${{ github.token }}
29
+ RUN_ID: ${{ github.event.workflow_run.id }}
30
+ REPOSITORY: ${{ github.event.repository.full_name }}
31
+ run: |
32
+ gh run rerun "$RUN_ID" --repo "$REPOSITORY" --failed
@@ -0,0 +1,173 @@
1
+ name: upstream-bump
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ schedule:
6
+ - cron: "17 9 * * 1"
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ prepare:
13
+ name: prepare oxipng bump
14
+ runs-on: ubuntu-latest
15
+ outputs:
16
+ changed: ${{ steps.changes.outputs.changed }}
17
+ target-version: ${{ steps.bump.outputs.target-version }}
18
+ upstream-crate-available: ${{ steps.bump.outputs.upstream-crate-available }}
19
+ env:
20
+ UV_PYTHON: "3.13"
21
+ steps:
22
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
23
+ - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b
24
+ with:
25
+ version: 0.11.12
26
+ - uses: dtolnay/rust-toolchain@1.95.0
27
+ with:
28
+ components: clippy
29
+ - name: Install nightly rustdoc JSON toolchain
30
+ run: rustup toolchain install nightly --profile minimal
31
+ - name: Install cargo-deny
32
+ uses: taiki-e/install-action@60ae4ce63c7aeb6e96d7f572c1ec7fafbb17ca80
33
+ with:
34
+ tool: cargo-deny@0.19.7
35
+ - name: Sync dependencies
36
+ run: uv sync --locked --group dev
37
+ - name: Bump upstream
38
+ id: bump
39
+ run: uv run --locked --group dev python scripts/bump_upstream.py
40
+ - name: Generate third-party notices
41
+ run: make third-party-notices
42
+ - name: Fetch upstream source
43
+ if: steps.bump.outputs.upstream-crate-available != 'false'
44
+ run: |
45
+ version="${{ steps.bump.outputs.target-version }}"
46
+ git clone --depth 1 --branch "v$version" https://github.com/oxipng/oxipng .cache/upstream/oxipng
47
+ - name: Prepare API surface manifest
48
+ if: steps.bump.outputs.upstream-crate-available != 'false'
49
+ run: |
50
+ version="${{ steps.bump.outputs.target-version }}"
51
+ mkdir -p docs/api-surface
52
+ if [ ! -f "docs/api-surface/oxipng-$version.toml" ]; then
53
+ previous="$(ls docs/api-surface/oxipng-*.toml | sort -V | tail -n 1)"
54
+ cp "$previous" "docs/api-surface/oxipng-$version.toml"
55
+ sed -i "s/^upstream_version = .*/upstream_version = \"$version\"/" "docs/api-surface/oxipng-$version.toml"
56
+ fi
57
+ - name: Scan upstream surface
58
+ if: steps.bump.outputs.upstream-crate-available != 'false'
59
+ run: uv run --locked --group dev python scripts/scan_upstream_surface.py --update-docs
60
+ - name: Check for changes
61
+ id: changes
62
+ run: |
63
+ if git diff --quiet; then
64
+ echo "changed=false" >> "$GITHUB_OUTPUT"
65
+ else
66
+ echo "changed=true" >> "$GITHUB_OUTPUT"
67
+ fi
68
+ - name: Run CI before opening PR
69
+ if: steps.changes.outputs.changed == 'true'
70
+ run: make ci
71
+ - name: Upload bump workspace
72
+ if: steps.changes.outputs.changed == 'true'
73
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
74
+ with:
75
+ name: upstream-bump-workspace
76
+ include-hidden-files: true
77
+ path: |
78
+ Cargo.toml
79
+ Cargo.lock
80
+ pyproject.toml
81
+ uv.lock
82
+ THIRD_PARTY_NOTICES.md
83
+ CHANGELOG.md
84
+ docs/api-surface/*.toml
85
+ docs/architecture/api-compatibility.md
86
+ docs/architecture/options-surface.md
87
+ .cache/upstream-bump/target-version.txt
88
+ .cache/upstream-surface/pr-body-section.md
89
+
90
+ publish:
91
+ name: publish oxipng bump PR
92
+ needs: prepare
93
+ if: needs.prepare.outputs.changed == 'true'
94
+ runs-on: ubuntu-latest
95
+ permissions:
96
+ contents: write
97
+ issues: write
98
+ pull-requests: write
99
+ steps:
100
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
101
+ with:
102
+ persist-credentials: false
103
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
104
+ with:
105
+ name: upstream-bump-workspace
106
+ path: .
107
+ - name: Check upstream bump token
108
+ env:
109
+ UPSTREAM_BUMP_TOKEN: ${{ secrets.UPSTREAM_BUMP_TOKEN }}
110
+ run: |
111
+ if [ -z "$UPSTREAM_BUMP_TOKEN" ]; then
112
+ echo "UPSTREAM_BUMP_TOKEN is required to create bump PRs with normal PR CI checks and auto-merge."
113
+ exit 1
114
+ fi
115
+ - name: Write pull request body
116
+ run: |
117
+ mkdir -p .cache/upstream-bump
118
+ {
119
+ echo "Automated upstream oxipng bump."
120
+ echo
121
+ cat .cache/upstream-surface/pr-body-section.md
122
+ echo
123
+ echo "Auto-merge is enabled only after required CI and wheel checks pass."
124
+ } > .cache/upstream-bump/pr-body.md
125
+ - name: Create pull request
126
+ id: cpr
127
+ uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1
128
+ with:
129
+ token: ${{ secrets.UPSTREAM_BUMP_TOKEN }}
130
+ commit-message: "chore: bump upstream oxipng"
131
+ title: "chore: bump upstream oxipng"
132
+ body-path: .cache/upstream-bump/pr-body.md
133
+ branch: automation/bump-oxipng
134
+ delete-branch: true
135
+ labels: dependencies, automated
136
+ - name: Create or update upstream surface issue
137
+ env:
138
+ GH_TOKEN: ${{ secrets.UPSTREAM_BUMP_TOKEN }}
139
+ run: |
140
+ python - <<'PY'
141
+ from pathlib import Path
142
+ from scripts.bump_upstream import upsert_surface_issue
143
+
144
+ version = Path(".cache/upstream-bump/target-version.txt").read_text(encoding="utf-8").strip()
145
+ upsert_surface_issue(version, Path(".cache/upstream-surface/pr-body-section.md"))
146
+ PY
147
+ - name: Wait for wheel workflow
148
+ if: >-
149
+ steps.cpr.outputs.pull-request-number != '' &&
150
+ contains(fromJSON('["created", "updated"]'), steps.cpr.outputs.pull-request-operation)
151
+ env:
152
+ GH_TOKEN: ${{ secrets.UPSTREAM_BUMP_TOKEN }}
153
+ run: |
154
+ pr="${{ steps.cpr.outputs.pull-request-number }}"
155
+ sha="$(gh pr view "$pr" --json headRefOid --jq .headRefOid)"
156
+ for attempt in $(seq 1 60); do
157
+ conclusion="$(gh run list --workflow wheels.yml --commit "$sha" --json status,conclusion --jq '.[0] | "\(.status) \(.conclusion)"')"
158
+ case "$conclusion" in
159
+ "completed success") exit 0 ;;
160
+ "completed failure"|"completed cancelled"|"completed timed_out") echo "wheels workflow failed: $conclusion"; exit 1 ;;
161
+ esac
162
+ sleep 30
163
+ done
164
+ echo "timed out waiting for wheels workflow"
165
+ exit 1
166
+ - name: Enable auto-merge
167
+ if: >-
168
+ steps.cpr.outputs.pull-request-number != '' &&
169
+ contains(fromJSON('["created", "updated"]'), steps.cpr.outputs.pull-request-operation)
170
+ env:
171
+ GH_TOKEN: ${{ secrets.UPSTREAM_BUMP_TOKEN }}
172
+ run: |
173
+ gh pr merge "${{ steps.cpr.outputs.pull-request-number }}" --auto --rebase --delete-branch