feat: add interactive PTY terminal with launch cwd and clud access (#… #89
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Auto Release | |
| on: | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| actions: read | |
| jobs: | |
| detect-version: | |
| runs-on: ubuntu-24.04 | |
| outputs: | |
| version: ${{ steps.version_check.outputs.current }} | |
| should_release: ${{ steps.version_check.outputs.should_release }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Check if version needs release | |
| id: version_check | |
| run: | | |
| VERSION=$(python -c 'import tomllib; from pathlib import Path; manifest = tomllib.loads(Path("Cargo.toml").read_text(encoding="utf-8")); print(manifest["workspace"]["package"]["version"])') | |
| echo "current=$VERSION" >> $GITHUB_OUTPUT | |
| STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://pypi.org/pypi/fastled/$VERSION/json") | |
| if [ "$STATUS" = "200" ]; then | |
| echo "should_release=false" >> $GITHUB_OUTPUT | |
| echo "Version $VERSION already on PyPI, skipping release" | |
| else | |
| echo "should_release=true" >> $GITHUB_OUTPUT | |
| echo "Version $VERSION not on PyPI, will release" | |
| fi | |
| # The per-platform CI build workflows already produce release-identical | |
| # wheel/binary artifacts for this same SHA (same rust targets, plat-name | |
| # tags, and soldr cache keys — see the build wrappers). Wait for those runs | |
| # and reuse their artifacts instead of rebuilding all 6 platforms (#170). | |
| # Any platform whose CI run is missing, failed, or timed out falls back to | |
| # a build-* job below. Runs only on push: a workflow_dispatch SHA may have | |
| # no CI runs, so dispatch always builds. | |
| collect-artifacts: | |
| needs: [detect-version] | |
| if: needs.detect-version.outputs.should_release == 'true' && github.event_name == 'push' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 45 | |
| outputs: | |
| reused_linux_x86: ${{ steps.collect.outputs.reused_linux_x86 }} | |
| reused_linux_arm: ${{ steps.collect.outputs.reused_linux_arm }} | |
| reused_windows_x86: ${{ steps.collect.outputs.reused_windows_x86 }} | |
| reused_windows_arm: ${{ steps.collect.outputs.reused_windows_arm }} | |
| reused_macos_x86: ${{ steps.collect.outputs.reused_macos_x86 }} | |
| reused_macos_arm: ${{ steps.collect.outputs.reused_macos_arm }} | |
| steps: | |
| - name: Wait for CI build runs and download artifacts | |
| id: collect | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| REPO: ${{ github.repository }} | |
| SHA: ${{ github.sha }} | |
| run: | | |
| set -uo pipefail | |
| mkdir -p artifacts | |
| declare -A WF_SUFFIX=( | |
| ["linux-x86-build.yml"]="ubuntu-24.04-x86_64-unknown-linux-gnu" | |
| ["linux-arm-build.yml"]="ubuntu-24.04-arm-aarch64-unknown-linux-gnu" | |
| ["windows-x86-build.yml"]="windows-2025-x86_64-pc-windows-msvc" | |
| ["windows-arm-build.yml"]="windows-2025-aarch64-pc-windows-msvc" | |
| ["macos-x86-build.yml"]="macos-14-x86_64-apple-darwin" | |
| ["macos-arm-build.yml"]="macos-15-aarch64-apple-darwin" | |
| ) | |
| deadline=$(( $(date +%s) + 2100 )) | |
| for wf in linux-x86-build.yml linux-arm-build.yml windows-x86-build.yml windows-arm-build.yml macos-x86-build.yml macos-arm-build.yml; do | |
| suffix="${WF_SUFFIX[$wf]}" | |
| key="reused_$(echo "$wf" | sed 's/-build\.yml$//; s/-/_/g')" | |
| reused=false | |
| while :; do | |
| run_json=$(gh api "repos/$REPO/actions/workflows/$wf/runs?head_sha=$SHA&per_page=1" --jq '.workflow_runs[0] // empty' 2>/dev/null || true) | |
| if [ -n "$run_json" ]; then | |
| status=$(jq -r .status <<<"$run_json") | |
| if [ "$status" = "completed" ]; then | |
| conclusion=$(jq -r .conclusion <<<"$run_json") | |
| run_id=$(jq -r .id <<<"$run_json") | |
| if [ "$conclusion" = "success" ] && \ | |
| gh run download "$run_id" -R "$REPO" --dir artifacts -n "wheel-$suffix" -n "binary-$suffix"; then | |
| reused=true | |
| else | |
| echo "$wf run $run_id concluded '$conclusion' or artifact download failed; falling back to build." | |
| fi | |
| break | |
| fi | |
| fi | |
| if [ "$(date +%s)" -ge "$deadline" ]; then | |
| echo "Timed out waiting for $wf; falling back to build." | |
| break | |
| fi | |
| sleep 30 | |
| done | |
| echo "$wf -> $key=$reused" | |
| echo "$key=$reused" >> "$GITHUB_OUTPUT" | |
| done | |
| - uses: actions/upload-artifact@v4 | |
| if: steps.collect.outputs.reused_linux_x86 == 'true' | |
| with: | |
| name: wheel-ubuntu-24.04-x86_64-unknown-linux-gnu | |
| path: artifacts/wheel-ubuntu-24.04-x86_64-unknown-linux-gnu/* | |
| - uses: actions/upload-artifact@v4 | |
| if: steps.collect.outputs.reused_linux_x86 == 'true' | |
| with: | |
| name: binary-ubuntu-24.04-x86_64-unknown-linux-gnu | |
| path: artifacts/binary-ubuntu-24.04-x86_64-unknown-linux-gnu/* | |
| - uses: actions/upload-artifact@v4 | |
| if: steps.collect.outputs.reused_linux_arm == 'true' | |
| with: | |
| name: wheel-ubuntu-24.04-arm-aarch64-unknown-linux-gnu | |
| path: artifacts/wheel-ubuntu-24.04-arm-aarch64-unknown-linux-gnu/* | |
| - uses: actions/upload-artifact@v4 | |
| if: steps.collect.outputs.reused_linux_arm == 'true' | |
| with: | |
| name: binary-ubuntu-24.04-arm-aarch64-unknown-linux-gnu | |
| path: artifacts/binary-ubuntu-24.04-arm-aarch64-unknown-linux-gnu/* | |
| - uses: actions/upload-artifact@v4 | |
| if: steps.collect.outputs.reused_windows_x86 == 'true' | |
| with: | |
| name: wheel-windows-2025-x86_64-pc-windows-msvc | |
| path: artifacts/wheel-windows-2025-x86_64-pc-windows-msvc/* | |
| - uses: actions/upload-artifact@v4 | |
| if: steps.collect.outputs.reused_windows_x86 == 'true' | |
| with: | |
| name: binary-windows-2025-x86_64-pc-windows-msvc | |
| path: artifacts/binary-windows-2025-x86_64-pc-windows-msvc/* | |
| - uses: actions/upload-artifact@v4 | |
| if: steps.collect.outputs.reused_windows_arm == 'true' | |
| with: | |
| name: wheel-windows-2025-aarch64-pc-windows-msvc | |
| path: artifacts/wheel-windows-2025-aarch64-pc-windows-msvc/* | |
| - uses: actions/upload-artifact@v4 | |
| if: steps.collect.outputs.reused_windows_arm == 'true' | |
| with: | |
| name: binary-windows-2025-aarch64-pc-windows-msvc | |
| path: artifacts/binary-windows-2025-aarch64-pc-windows-msvc/* | |
| - uses: actions/upload-artifact@v4 | |
| if: steps.collect.outputs.reused_macos_x86 == 'true' | |
| with: | |
| name: wheel-macos-14-x86_64-apple-darwin | |
| path: artifacts/wheel-macos-14-x86_64-apple-darwin/* | |
| - uses: actions/upload-artifact@v4 | |
| if: steps.collect.outputs.reused_macos_x86 == 'true' | |
| with: | |
| name: binary-macos-14-x86_64-apple-darwin | |
| path: artifacts/binary-macos-14-x86_64-apple-darwin/* | |
| - uses: actions/upload-artifact@v4 | |
| if: steps.collect.outputs.reused_macos_arm == 'true' | |
| with: | |
| name: wheel-macos-15-aarch64-apple-darwin | |
| path: artifacts/wheel-macos-15-aarch64-apple-darwin/* | |
| - uses: actions/upload-artifact@v4 | |
| if: steps.collect.outputs.reused_macos_arm == 'true' | |
| with: | |
| name: binary-macos-15-aarch64-apple-darwin | |
| path: artifacts/binary-macos-15-aarch64-apple-darwin/* | |
| # Fallback builds: each runs only when the matching CI artifact could not | |
| # be reused (collect skipped on workflow_dispatch, CI run failed/missing, | |
| # or download failed). | |
| build-linux-x86: | |
| needs: [detect-version, collect-artifacts] | |
| if: >- | |
| !cancelled() && | |
| needs.detect-version.outputs.should_release == 'true' && | |
| !(needs.collect-artifacts.result == 'success' && needs.collect-artifacts.outputs.reused_linux_x86 == 'true') | |
| uses: ./.github/workflows/_build.yml | |
| with: | |
| runs-on: ubuntu-24.04 | |
| rust-target: x86_64-unknown-linux-gnu | |
| build-linux-arm: | |
| needs: [detect-version, collect-artifacts] | |
| if: >- | |
| !cancelled() && | |
| needs.detect-version.outputs.should_release == 'true' && | |
| !(needs.collect-artifacts.result == 'success' && needs.collect-artifacts.outputs.reused_linux_arm == 'true') | |
| uses: ./.github/workflows/_build.yml | |
| with: | |
| runs-on: ubuntu-24.04-arm | |
| rust-target: aarch64-unknown-linux-gnu | |
| build-windows-x86: | |
| needs: [detect-version, collect-artifacts] | |
| if: >- | |
| !cancelled() && | |
| needs.detect-version.outputs.should_release == 'true' && | |
| !(needs.collect-artifacts.result == 'success' && needs.collect-artifacts.outputs.reused_windows_x86 == 'true') | |
| uses: ./.github/workflows/_build.yml | |
| with: | |
| runs-on: windows-2025 | |
| rust-target: x86_64-pc-windows-msvc | |
| build-windows-arm: | |
| needs: [detect-version, collect-artifacts] | |
| if: >- | |
| !cancelled() && | |
| needs.detect-version.outputs.should_release == 'true' && | |
| !(needs.collect-artifacts.result == 'success' && needs.collect-artifacts.outputs.reused_windows_arm == 'true') | |
| uses: ./.github/workflows/_build.yml | |
| with: | |
| runs-on: windows-2025 | |
| rust-target: aarch64-pc-windows-msvc | |
| build-macos-x86: | |
| needs: [detect-version, collect-artifacts] | |
| if: >- | |
| !cancelled() && | |
| needs.detect-version.outputs.should_release == 'true' && | |
| !(needs.collect-artifacts.result == 'success' && needs.collect-artifacts.outputs.reused_macos_x86 == 'true') | |
| uses: ./.github/workflows/_build.yml | |
| with: | |
| runs-on: macos-14 | |
| rust-target: x86_64-apple-darwin | |
| build-macos-arm: | |
| needs: [detect-version, collect-artifacts] | |
| if: >- | |
| !cancelled() && | |
| needs.detect-version.outputs.should_release == 'true' && | |
| !(needs.collect-artifacts.result == 'success' && needs.collect-artifacts.outputs.reused_macos_arm == 'true') | |
| uses: ./.github/workflows/_build.yml | |
| with: | |
| runs-on: macos-15 | |
| rust-target: aarch64-apple-darwin | |
| create-tag: | |
| needs: | |
| - detect-version | |
| - build-linux-x86 | |
| - build-linux-arm | |
| - build-windows-x86 | |
| - build-windows-arm | |
| - build-macos-x86 | |
| - build-macos-arm | |
| # A skipped build means its artifact was reused from CI by | |
| # collect-artifacts; any failed or cancelled build blocks the release. | |
| if: >- | |
| !cancelled() && | |
| needs.detect-version.outputs.should_release == 'true' && | |
| contains(fromJSON('["success", "skipped"]'), needs.build-linux-x86.result) && | |
| contains(fromJSON('["success", "skipped"]'), needs.build-linux-arm.result) && | |
| contains(fromJSON('["success", "skipped"]'), needs.build-windows-x86.result) && | |
| contains(fromJSON('["success", "skipped"]'), needs.build-windows-arm.result) && | |
| contains(fromJSON('["success", "skipped"]'), needs.build-macos-x86.result) && | |
| contains(fromJSON('["success", "skipped"]'), needs.build-macos-arm.result) | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Create tag if not present | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| git config --local user.email "action@github.com" | |
| git config --local user.name "GitHub Action" | |
| TAG="v${{ needs.detect-version.outputs.version }}" | |
| if git ls-remote --exit-code --tags origin "refs/tags/${TAG}" >/dev/null 2>&1; then | |
| echo "Tag ${TAG} already exists; continuing release workflow." | |
| else | |
| git tag -a "${TAG}" -m "Release ${{ needs.detect-version.outputs.version }}" | |
| git push origin "${TAG}" | |
| fi | |
| publish-pypi: | |
| needs: [detect-version, create-tag] | |
| # Job-level success() (implied by a plain `if`) evaluates false when any | |
| # transitive ancestor was skipped — and the build-* jobs are skipped | |
| # whenever collect-artifacts reused CI artifacts, which silently skipped | |
| # publishing on the v2.0.12 release. Gate explicitly on create-tag instead. | |
| if: >- | |
| !cancelled() && | |
| needs.detect-version.outputs.should_release == 'true' && | |
| needs.create-tag.result == 'success' | |
| runs-on: ubuntu-24.04 | |
| environment: | |
| name: release | |
| url: https://pypi.org/p/fastled | |
| permissions: | |
| id-token: write | |
| steps: | |
| - name: Download all wheels | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: wheel-* | |
| path: dist | |
| merge-multiple: true | |
| - name: List artifacts | |
| run: ls -la dist/ | |
| - name: Publish to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| create-release: | |
| needs: [detect-version, create-tag] | |
| # Same skipped-ancestor gotcha as publish-pypi above. | |
| if: >- | |
| !cancelled() && | |
| needs.detect-version.outputs.should_release == 'true' && | |
| needs.create-tag.result == 'success' | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: write | |
| id-token: write | |
| steps: | |
| # With merge-multiple unset, each artifact lands in its own | |
| # binaries/<artifact-name>/ directory, so the case match below on the | |
| # target-suffixed artifact name works for both reused and rebuilt | |
| # artifacts. | |
| - name: Download all binaries | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: binary-* | |
| path: binaries | |
| - name: Prepare release files | |
| shell: bash | |
| run: | | |
| mkdir release | |
| cd binaries | |
| for d in binary-*; do | |
| case "$d" in | |
| *x86_64-unknown-linux-gnu) zip -j "../release/fastled-linux-x86_64.zip" "$d"/fastled ;; | |
| *aarch64-unknown-linux-gnu) zip -j "../release/fastled-linux-aarch64.zip" "$d"/fastled ;; | |
| *x86_64-pc-windows-msvc) zip -j "../release/fastled-windows-x86_64.zip" "$d"/fastled.exe ;; | |
| *aarch64-pc-windows-msvc) zip -j "../release/fastled-windows-aarch64.zip" "$d"/fastled.exe ;; | |
| *x86_64-apple-darwin) zip -j "../release/fastled-macos-x86_64.zip" "$d"/fastled ;; | |
| *aarch64-apple-darwin) zip -j "../release/fastled-macos-aarch64.zip" "$d"/fastled ;; | |
| esac | |
| done | |
| cd .. | |
| ls -la release/ | |
| - name: Sign release artifacts with sigstore | |
| uses: sigstore/gh-action-sigstore-python@v3.3.0 | |
| with: | |
| inputs: ./release/*.zip | |
| release-signing-artifacts: true | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: v${{ needs.detect-version.outputs.version }} | |
| files: | | |
| release/*.zip | |
| release/*.sigstore | |
| draft: false | |
| prerelease: false |