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.
- oxipng_pybind-10.1.1/.github/workflows/api-matrix.yml +36 -0
- oxipng_pybind-10.1.1/.github/workflows/ci.yml +33 -0
- oxipng_pybind-10.1.1/.github/workflows/dependency-health.yml +144 -0
- oxipng_pybind-10.1.1/.github/workflows/release-tag.yml +134 -0
- oxipng_pybind-10.1.1/.github/workflows/retry-failed-checks.yml +32 -0
- oxipng_pybind-10.1.1/.github/workflows/upstream-bump.yml +173 -0
- oxipng_pybind-10.1.1/.github/workflows/wheels.yml +316 -0
- oxipng_pybind-10.1.1/.gitignore +15 -0
- oxipng_pybind-10.1.1/.gitlint +9 -0
- oxipng_pybind-10.1.1/.markdownlint-cli2.jsonc +7 -0
- oxipng_pybind-10.1.1/.pre-commit-config.yaml +66 -0
- oxipng_pybind-10.1.1/AGENTS.md +12 -0
- oxipng_pybind-10.1.1/CLAUDE.md +124 -0
- oxipng_pybind-10.1.1/CONTRIBUTING.md +82 -0
- oxipng_pybind-10.1.1/CONVENTIONS.md +89 -0
- oxipng_pybind-10.1.1/Cargo.lock +410 -0
- oxipng_pybind-10.1.1/Cargo.toml +22 -0
- oxipng_pybind-10.1.1/LICENSE +22 -0
- oxipng_pybind-10.1.1/Makefile +164 -0
- oxipng_pybind-10.1.1/PKG-INFO +67 -0
- oxipng_pybind-10.1.1/PYPI-DESCRIPTION.md +39 -0
- oxipng_pybind-10.1.1/README.md +84 -0
- oxipng_pybind-10.1.1/THIRD_PARTY_NOTICES.md +188 -0
- oxipng_pybind-10.1.1/deny.toml +26 -0
- oxipng_pybind-10.1.1/docs/README.md +44 -0
- oxipng_pybind-10.1.1/docs/api-surface/oxipng-10.1.1.toml +116 -0
- oxipng_pybind-10.1.1/docs/architecture/api-compatibility.md +75 -0
- oxipng_pybind-10.1.1/docs/architecture/options-surface.md +86 -0
- oxipng_pybind-10.1.1/docs/architecture/overview.md +105 -0
- oxipng_pybind-10.1.1/docs/plans/unfinished-work.md +57 -0
- oxipng_pybind-10.1.1/docs/process/dependency-health.md +101 -0
- oxipng_pybind-10.1.1/docs/process/github-settings.md +44 -0
- oxipng_pybind-10.1.1/docs/process/lint-deviations.md +82 -0
- oxipng_pybind-10.1.1/docs/process/local-development.md +51 -0
- oxipng_pybind-10.1.1/docs/process/release-artifacts.md +105 -0
- oxipng_pybind-10.1.1/docs/process/upstream-bumps.md +113 -0
- oxipng_pybind-10.1.1/docs/process/writing-style.md +47 -0
- oxipng_pybind-10.1.1/docs/usage/build-from-source.md +90 -0
- oxipng_pybind-10.1.1/docs/usage/file-optimization.md +91 -0
- oxipng_pybind-10.1.1/docs/usage/memory-optimization.md +83 -0
- oxipng_pybind-10.1.1/docs/usage/pyoxipng-migration.md +227 -0
- oxipng_pybind-10.1.1/docs/usage/raw-image.md +209 -0
- oxipng_pybind-10.1.1/docs/usage/untrusted-input.md +70 -0
- oxipng_pybind-10.1.1/oxipng/__init__.py +627 -0
- oxipng_pybind-10.1.1/oxipng/__init__.pyi +286 -0
- oxipng_pybind-10.1.1/oxipng/_pyoxipng_compat.py +94 -0
- oxipng_pybind-10.1.1/oxipng/py.typed +0 -0
- oxipng_pybind-10.1.1/pyproject.toml +148 -0
- oxipng_pybind-10.1.1/scripts/__init__.py +1 -0
- oxipng_pybind-10.1.1/scripts/ai_filter_log.py +59 -0
- oxipng_pybind-10.1.1/scripts/audit_github_settings.py +217 -0
- oxipng_pybind-10.1.1/scripts/bump_upstream.py +278 -0
- oxipng_pybind-10.1.1/scripts/check_wheel_tags.py +105 -0
- oxipng_pybind-10.1.1/scripts/classify_dependency_refresh.py +292 -0
- oxipng_pybind-10.1.1/scripts/generate_third_party_notices.py +175 -0
- oxipng_pybind-10.1.1/scripts/scan_upstream_surface.py +351 -0
- oxipng_pybind-10.1.1/scripts/smoke_wheel.py +113 -0
- oxipng_pybind-10.1.1/scripts/update_github_actions.py +152 -0
- oxipng_pybind-10.1.1/scripts/validate_release_tag.py +151 -0
- oxipng_pybind-10.1.1/scripts/verify_release_artifacts.py +194 -0
- oxipng_pybind-10.1.1/scripts/verify_release_checks.py +137 -0
- oxipng_pybind-10.1.1/scripts/verify_release_version.py +63 -0
- oxipng_pybind-10.1.1/src/lib.rs +1254 -0
- oxipng_pybind-10.1.1/tests/conftest.py +39 -0
- oxipng_pybind-10.1.1/tests/test_api.py +1448 -0
- oxipng_pybind-10.1.1/tests/test_bump_upstream.py +523 -0
- oxipng_pybind-10.1.1/tests/test_dependency_refresh_classification.py +287 -0
- oxipng_pybind-10.1.1/tests/test_docs_examples.py +384 -0
- oxipng_pybind-10.1.1/tests/test_github_settings_audit.py +84 -0
- oxipng_pybind-10.1.1/tests/test_makefile.py +75 -0
- oxipng_pybind-10.1.1/tests/test_real_pngs.py +139 -0
- oxipng_pybind-10.1.1/tests/test_release_artifacts.py +175 -0
- oxipng_pybind-10.1.1/tests/test_release_checks.py +157 -0
- oxipng_pybind-10.1.1/tests/test_release_version.py +38 -0
- oxipng_pybind-10.1.1/tests/test_scan_upstream_surface.py +356 -0
- oxipng_pybind-10.1.1/tests/test_scripts.py +261 -0
- oxipng_pybind-10.1.1/tests/test_third_party_notices.py +167 -0
- oxipng_pybind-10.1.1/tests/test_update_github_actions.py +82 -0
- oxipng_pybind-10.1.1/tests/test_validate_release_tag.py +225 -0
- oxipng_pybind-10.1.1/tests/test_wheel_tags.py +91 -0
- oxipng_pybind-10.1.1/tests/test_workflows.py +663 -0
- oxipng_pybind-10.1.1/tests/typing_filter_options.py +28 -0
- 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
|