From 3f2661084c8d8fa50bb6aae9dafcd503f4fc7975 Mon Sep 17 00:00:00 2001 From: Abdo Date: Fri, 8 May 2026 05:45:43 +0300 Subject: [PATCH 1/5] Add a workflow to publish anki-audio package --- .github/workflows/publish-audio-package.yml | 116 ++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 .github/workflows/publish-audio-package.yml diff --git a/.github/workflows/publish-audio-package.yml b/.github/workflows/publish-audio-package.yml new file mode 100644 index 00000000000..c4322e1f3fb --- /dev/null +++ b/.github/workflows/publish-audio-package.yml @@ -0,0 +1,116 @@ +name: Publish anki-audio to PyPI + +on: + workflow_dispatch: + inputs: + publish: + description: "Publishing target" + default: "testpypi" + required: true + type: choice + options: + - testpypi + - release + +env: + RELEASE: 2 + +jobs: + build: + strategy: + matrix: + include: + - runner: macos-14 + artifact: wheel-macos-arm + build_cmd: ./qt/audio/build.sh + needs_signing: true + - runner: macos-15-intel + artifact: wheel-macos-intel + build_cmd: ./qt/audio/build.sh + needs_signing: true + - runner: windows-latest + artifact: wheel-windows-x64 + build_cmd: ./ninja audio_wheel + needs_signing: false + - runner: windows-11-arm + artifact: wheel-windows-arm + build_cmd: ./ninja audio_wheel + needs_signing: false + runs-on: ${{ matrix.runner }} + environment: ${{ matrix.needs_signing && inputs.publish == 'release' && 'release' || '' }} + steps: + - uses: actions/checkout@v4 + + - name: Setup build environment + uses: ./.github/actions/setup-anki + + - name: Set up Apple code signing + if: matrix.needs_signing && inputs.publish == 'release' + run: .github/scripts/setup_apple_signing.sh + env: + APPLE_CERTIFICATE_P12: ${{ secrets.APPLE_CERTIFICATE_P12 }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + APPLE_NOTARY_KEY: ${{ secrets.APPLE_NOTARY_KEY }} + APPLE_NOTARY_KEY_ID: ${{ secrets.APPLE_NOTARY_KEY_ID }} + APPLE_NOTARY_ISSUER_ID: ${{ secrets.APPLE_NOTARY_ISSUER_ID }} + + - name: Build wheel + run: ${{ matrix.build_cmd }} + env: + SIGN_IDENTITY: ${{ matrix.needs_signing && inputs.publish == 'release' && secrets.APPLE_SIGNING_IDENTITY || '' }} + + - name: Clean up signing credentials + if: always() && matrix.needs_signing && inputs.publish == 'release' + run: | + KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db" + security delete-keychain "$KEYCHAIN_PATH" 2>/dev/null || true + rm -f "$RUNNER_TEMP/certificate.p12" "$RUNNER_TEMP/AuthKey.p8" + + - name: Upload wheel + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact }} + path: out/wheels/anki_audio-*.whl + + publish-testpypi: + needs: build + runs-on: ubuntu-latest + environment: release + permissions: + id-token: write + steps: + - name: Download all wheels + uses: actions/download-artifact@v4 + with: + pattern: wheel-* + path: dist + merge-multiple: true + + - name: Publish to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist/ + repository-url: https://test.pypi.org/legacy/ + skip-existing: true + + publish-pypi: + needs: publish-testpypi + if: inputs.publish == 'release' + runs-on: ubuntu-latest + environment: release + permissions: + id-token: write + steps: + - name: Download all wheels + uses: actions/download-artifact@v4 + with: + pattern: wheel-* + path: dist + merge-multiple: true + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist/ From 67a6d229bf672461f3f71f3688fb672d535870ac Mon Sep 17 00:00:00 2001 From: Abdo Date: Fri, 8 May 2026 05:47:56 +0300 Subject: [PATCH 2/5] Sign macOS binaries --- qt/audio/build.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/qt/audio/build.sh b/qt/audio/build.sh index 29c4b3b87c9..6679d67f7ef 100755 --- a/qt/audio/build.sh +++ b/qt/audio/build.sh @@ -31,4 +31,11 @@ rm -rf "$OUTPUT_DIR/lame" mkdir -p "$OUTPUT_DIR/lame" cp /opt/homebrew/bin/lame "$OUTPUT_DIR/lame/" && chmod u+w "$OUTPUT_DIR/lame/lame" +if [ -n "${SIGN_IDENTITY:-}" ]; then + find "$OUTPUT_DIR/mpv/libs" -name "*.dylib" -exec \ + codesign --sign "$SIGN_IDENTITY" --force --options runtime --timestamp {} \; + codesign --sign "$SIGN_IDENTITY" --force --options runtime --timestamp "$OUTPUT_DIR/mpv/mpv" + codesign --sign "$SIGN_IDENTITY" --force --options runtime --timestamp "$OUTPUT_DIR/lame/lame" +fi + ./ninja audio_wheel From 96d32477749c88e4bd118d8ef0ad957d4f1eb42c Mon Sep 17 00:00:00 2001 From: Abdo Date: Fri, 8 May 2026 05:48:35 +0300 Subject: [PATCH 3/5] Fix package version Last release was 0.1.0 --- qt/audio/.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qt/audio/.version b/qt/audio/.version index 4e379d2bfea..0ea3a944b39 100644 --- a/qt/audio/.version +++ b/qt/audio/.version @@ -1 +1 @@ -0.0.2 +0.2.0 From 130176b0604a1e08690a8d03347383f6bd936a25 Mon Sep 17 00:00:00 2001 From: Abdo Date: Fri, 8 May 2026 07:51:01 +0300 Subject: [PATCH 4/5] Refactor inputs to match release action --- .github/workflows/publish-audio-package.yml | 60 ++++++++++++++++----- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/.github/workflows/publish-audio-package.yml b/.github/workflows/publish-audio-package.yml index c4322e1f3fb..a75c957ff24 100644 --- a/.github/workflows/publish-audio-package.yml +++ b/.github/workflows/publish-audio-package.yml @@ -1,22 +1,44 @@ name: Publish anki-audio to PyPI +run-name: "Publish anki-audio (sign=${{ inputs.sign }}, testpypi=${{ inputs['publish-testpypi'] }}, pypi=${{ inputs['publish-pypi'] }})" on: workflow_dispatch: inputs: - publish: - description: "Publishing target" - default: "testpypi" - required: true - type: choice - options: - - testpypi - - release + sign: + description: "Sign macOS artifacts (requires release environment)" + default: false + required: false + type: boolean + publish-testpypi: + description: "Publish wheels to TestPyPI" + default: false + required: false + type: boolean + publish-pypi: + description: "Publish wheels to PyPI after TestPyPI" + default: false + required: false + type: boolean env: RELEASE: 2 jobs: + prepare: + runs-on: ubuntu-latest + steps: + - name: Reject incompatible inputs + run: | + if [ "$PUBLISH_PYPI" = "true" ] && [ "$SIGN" != "true" ]; then + echo "::error::PyPI releases must be signed" + exit 1 + fi + env: + PUBLISH_PYPI: ${{ inputs['publish-pypi'] }} + SIGN: ${{ inputs.sign }} + build: + needs: prepare strategy: matrix: include: @@ -37,7 +59,7 @@ jobs: build_cmd: ./ninja audio_wheel needs_signing: false runs-on: ${{ matrix.runner }} - environment: ${{ matrix.needs_signing && inputs.publish == 'release' && 'release' || '' }} + environment: ${{ matrix.needs_signing && inputs.sign == true && 'release' || '' }} steps: - uses: actions/checkout@v4 @@ -45,7 +67,7 @@ jobs: uses: ./.github/actions/setup-anki - name: Set up Apple code signing - if: matrix.needs_signing && inputs.publish == 'release' + if: matrix.needs_signing && inputs.sign == true run: .github/scripts/setup_apple_signing.sh env: APPLE_CERTIFICATE_P12: ${{ secrets.APPLE_CERTIFICATE_P12 }} @@ -59,10 +81,10 @@ jobs: - name: Build wheel run: ${{ matrix.build_cmd }} env: - SIGN_IDENTITY: ${{ matrix.needs_signing && inputs.publish == 'release' && secrets.APPLE_SIGNING_IDENTITY || '' }} + SIGN_IDENTITY: ${{ matrix.needs_signing && inputs.sign == true && secrets.APPLE_SIGNING_IDENTITY || '' }} - name: Clean up signing credentials - if: always() && matrix.needs_signing && inputs.publish == 'release' + if: always() && matrix.needs_signing && inputs.sign == true run: | KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db" security delete-keychain "$KEYCHAIN_PATH" 2>/dev/null || true @@ -75,7 +97,13 @@ jobs: path: out/wheels/anki_audio-*.whl publish-testpypi: - needs: build + needs: [prepare, build] + if: >- + ${{ always() + && (inputs['publish-testpypi'] == true || inputs['publish-pypi'] == true) + && needs.prepare.result == 'success' + && needs.build.result == 'success' + }} runs-on: ubuntu-latest environment: release permissions: @@ -97,7 +125,11 @@ jobs: publish-pypi: needs: publish-testpypi - if: inputs.publish == 'release' + if: >- + ${{ always() + && inputs['publish-pypi'] == true + && needs.publish-testpypi.result == 'success' + }} runs-on: ubuntu-latest environment: release permissions: From 62542b2f95105daf961afceacff9332d5716db29 Mon Sep 17 00:00:00 2001 From: Abdo Date: Fri, 8 May 2026 17:08:57 +0300 Subject: [PATCH 5/5] Rename sign input --- .github/workflows/publish-audio-package.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/publish-audio-package.yml b/.github/workflows/publish-audio-package.yml index a75c957ff24..5389498207f 100644 --- a/.github/workflows/publish-audio-package.yml +++ b/.github/workflows/publish-audio-package.yml @@ -1,10 +1,10 @@ name: Publish anki-audio to PyPI -run-name: "Publish anki-audio (sign=${{ inputs.sign }}, testpypi=${{ inputs['publish-testpypi'] }}, pypi=${{ inputs['publish-pypi'] }})" +run-name: "Publish anki-audio (sign-macos=${{ inputs.sign-macos }}, testpypi=${{ inputs['publish-testpypi'] }}, pypi=${{ inputs['publish-pypi'] }})" on: workflow_dispatch: inputs: - sign: + sign-macos: description: "Sign macOS artifacts (requires release environment)" default: false required: false @@ -30,12 +30,12 @@ jobs: - name: Reject incompatible inputs run: | if [ "$PUBLISH_PYPI" = "true" ] && [ "$SIGN" != "true" ]; then - echo "::error::PyPI releases must be signed" + echo "::error::macOS binaries must be signed" exit 1 fi env: PUBLISH_PYPI: ${{ inputs['publish-pypi'] }} - SIGN: ${{ inputs.sign }} + SIGN: ${{ inputs.sign-macos }} build: needs: prepare @@ -59,7 +59,7 @@ jobs: build_cmd: ./ninja audio_wheel needs_signing: false runs-on: ${{ matrix.runner }} - environment: ${{ matrix.needs_signing && inputs.sign == true && 'release' || '' }} + environment: ${{ matrix.needs_signing && inputs.sign-macos == true && 'release' || '' }} steps: - uses: actions/checkout@v4 @@ -67,7 +67,7 @@ jobs: uses: ./.github/actions/setup-anki - name: Set up Apple code signing - if: matrix.needs_signing && inputs.sign == true + if: matrix.needs_signing && inputs.sign-macos == true run: .github/scripts/setup_apple_signing.sh env: APPLE_CERTIFICATE_P12: ${{ secrets.APPLE_CERTIFICATE_P12 }} @@ -81,10 +81,10 @@ jobs: - name: Build wheel run: ${{ matrix.build_cmd }} env: - SIGN_IDENTITY: ${{ matrix.needs_signing && inputs.sign == true && secrets.APPLE_SIGNING_IDENTITY || '' }} + SIGN_IDENTITY: ${{ matrix.needs_signing && inputs.sign-macos == true && secrets.APPLE_SIGNING_IDENTITY || '' }} - name: Clean up signing credentials - if: always() && matrix.needs_signing && inputs.sign == true + if: always() && matrix.needs_signing && inputs.sign-macos == true run: | KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db" security delete-keychain "$KEYCHAIN_PATH" 2>/dev/null || true