feat(spratpack): add --scale-filter; fix Zip Slip, frame bounds, and … #149
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: CI | |
| on: | |
| pull_request: | |
| push: | |
| branches: | |
| - release | |
| permissions: | |
| contents: read | |
| jobs: | |
| pr-build-and-test: | |
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install dependencies (Linux) | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libarchive-dev gettext python3-pillow imagemagick | |
| - name: Configure | |
| run: | | |
| cmake \ | |
| -S . \ | |
| -B build \ | |
| -DSPRAT_DOWNLOAD_STB=ON \ | |
| -DSPRAT_REQUIRE_GETTEXT=ON \ | |
| -DBUILD_TESTING=ON \ | |
| -DCMAKE_BUILD_TYPE=Release | |
| - name: Build | |
| run: cmake --build build --parallel --config Release | |
| - name: Test | |
| run: ctest --test-dir build --output-on-failure -C Release --output-junit build/test-results.xml | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-${{ runner.os }} | |
| path: build/test-results.xml | |
| retention-days: 7 | |
| release-build-package: | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/release' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, windows-latest, macos-latest] | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Cache apt packages | |
| if: runner.os == 'Linux' | |
| uses: actions/cache@v4 | |
| with: | |
| path: /var/cache/apt/archives | |
| key: apt-${{ runner.os }}-libarchive-gettext-pillow-imagemagick | |
| - name: Install dependencies (Linux) | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-upgrade libarchive-dev gettext python3-pillow imagemagick | |
| - name: Cache vcpkg (Windows) | |
| if: runner.os == 'Windows' | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ${{ github.workspace }}/vcpkg_installed | |
| ${{ github.workspace }}/vcpkg/downloads | |
| key: ${{ runner.os }}-vcpkg-${{ hashFiles('vcpkg.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-vcpkg- | |
| - name: Setup vcpkg (Windows) | |
| if: runner.os == 'Windows' | |
| uses: lukka/run-vcpkg@v11 | |
| - name: Install Python dependencies (Windows) | |
| if: runner.os == 'Windows' | |
| run: pip install Pillow | |
| - name: Cache Homebrew packages | |
| if: runner.os == 'macOS' | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/Library/Caches/Homebrew | |
| key: brew-${{ runner.os }}-libarchive-gettext-imagemagick | |
| - name: Install dependencies (macOS) | |
| if: runner.os == 'macOS' | |
| run: | | |
| # Use brew list to check if already installed and avoid warnings | |
| brew list pkg-config > /dev/null 2>&1 || brew install pkg-config | |
| brew list libarchive > /dev/null 2>&1 || brew install libarchive | |
| brew list gettext > /dev/null 2>&1 || brew install gettext | |
| brew list imagemagick > /dev/null 2>&1 || brew install imagemagick | |
| pip3 install Pillow --break-system-packages | |
| echo "PKG_CONFIG_PATH=$(brew --prefix libarchive)/lib/pkgconfig:$(brew --prefix gettext)/lib/pkgconfig" >> "$GITHUB_ENV" | |
| echo "CMAKE_PREFIX_PATH=$(brew --prefix libarchive):$(brew --prefix gettext)" >> "$GITHUB_ENV" | |
| - name: Configure | |
| shell: bash | |
| run: | | |
| CMAKE_OPTIONS=( | |
| -S . | |
| -B build | |
| -DSPRAT_DOWNLOAD_STB=ON | |
| -DBUILD_TESTING=ON | |
| -DCMAKE_BUILD_TYPE=Release | |
| ) | |
| if [ "${{ runner.os }}" == "Windows" ]; then | |
| VCPKG_TOOLCHAIN="${VCPKG_ROOT//\\//}/scripts/buildsystems/vcpkg.cmake" | |
| CMAKE_OPTIONS+=( | |
| "-DCMAKE_TOOLCHAIN_FILE=$VCPKG_TOOLCHAIN" | |
| "-DX_VCPKG_APPLOCAL_DEPS=ON" | |
| ) | |
| else | |
| CMAKE_OPTIONS+=("-DSPRAT_REQUIRE_GETTEXT=ON") | |
| fi | |
| cmake "${CMAKE_OPTIONS[@]}" | |
| - name: Build | |
| run: cmake --build build --parallel --config Release | |
| - name: Prepare test environment (Windows) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| Copy-Item -Path spratprofiles.cfg -Destination build/spratprofiles.cfg -Force | |
| New-Item -ItemType Directory -Force -Path "$env:RUNNER_TEMP\sprat-home\.config\sprat" | Out-Null | |
| New-Item -ItemType Directory -Force -Path "$env:RUNNER_TEMP\sprat-appdata\sprat" | Out-Null | |
| Copy-Item -Path spratprofiles.cfg -Destination "$env:RUNNER_TEMP\sprat-home\.config\sprat\spratprofiles.cfg" -Force | |
| Copy-Item -Path spratprofiles.cfg -Destination "$env:RUNNER_TEMP\sprat-appdata\sprat\spratprofiles.cfg" -Force | |
| - name: Test (Windows) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| env: | |
| HOME: ${{ runner.temp }}\sprat-home | |
| USERPROFILE: ${{ runner.temp }}\sprat-home | |
| APPDATA: ${{ runner.temp }}\sprat-appdata | |
| run: ctest --test-dir build --output-on-failure -C Release --output-junit build/test-results.xml | |
| - name: Test (Non-Windows) | |
| if: runner.os != 'Windows' | |
| run: ctest --test-dir build --output-on-failure -C Release --output-junit build/test-results.xml | |
| - name: Upload test results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-${{ runner.os }} | |
| path: build/test-results.xml | |
| retention-days: 7 | |
| - name: Package Linux (.tar.gz) | |
| if: runner.os == 'Linux' | |
| shell: bash | |
| run: | | |
| out_dir="dist/sprat-cli-linux-x64" | |
| mkdir -p "$out_dir" | |
| cp build/spratlayout "$out_dir/" | |
| cp build/spratpack "$out_dir/" | |
| cp build/spratconvert "$out_dir/" | |
| cp build/spratframes "$out_dir/" | |
| cp build/spratunpack "$out_dir/" | |
| cp spratprofiles.cfg "$out_dir/" | |
| cp -r transforms/ "$out_dir/" | |
| cp -r man/ "$out_dir/" | |
| tar -C dist -czf dist/sprat-cli-linux-x64.tar.gz sprat-cli-linux-x64 | |
| - name: Package macOS (.dmg) | |
| if: runner.os == 'macOS' | |
| shell: bash | |
| run: | | |
| out_dir="dist/sprat-cli-macos-x64" | |
| mkdir -p "$out_dir" | |
| cp build/spratlayout "$out_dir/" | |
| cp build/spratpack "$out_dir/" | |
| cp build/spratconvert "$out_dir/" | |
| cp build/spratframes "$out_dir/" | |
| cp build/spratunpack "$out_dir/" | |
| cp spratprofiles.cfg "$out_dir/" | |
| cp -r transforms/ "$out_dir/" | |
| cp -r man/ "$out_dir/" | |
| hdiutil create \ | |
| -volname "sprat-cli" \ | |
| -srcfolder "$out_dir" \ | |
| -ov \ | |
| -format UDZO \ | |
| dist/sprat-cli-macos-x64.dmg | |
| - name: Package Windows (.zip) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| $outDir = "dist/sprat-cli-windows-x64" | |
| New-Item -ItemType Directory -Force -Path $outDir | Out-Null | |
| Copy-Item -Path build/Release/*.exe -Destination $outDir -Force | |
| Copy-Item -Path build/Release/*.dll -Destination $outDir -Force -ErrorAction SilentlyContinue | |
| Copy-Item -Path spratprofiles.cfg -Destination $outDir -Force | |
| Copy-Item -Path transforms -Destination $outDir -Recurse -Force | |
| Copy-Item -Path LICENSE -Destination $outDir -Force | |
| Copy-Item -Path README.md -Destination $outDir -Force | |
| Compress-Archive -Path "$outDir/*" -DestinationPath "dist/sprat-cli-windows-x64.zip" -Force | |
| - name: Upload packaged artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: sprat-cli-${{ runner.os }} | |
| path: | | |
| dist/*.tar.gz | |
| dist/*.dmg | |
| dist/*.zip | |
| retention-days: 30 | |
| release: | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/release' | |
| runs-on: ubuntu-latest | |
| needs: release-build-package | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: dist | |
| merge-multiple: true | |
| - name: Create release tag | |
| id: release_tag | |
| run: echo "tag=$(cat VERSION)" >> "$GITHUB_OUTPUT" | |
| - name: Publish GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.release_tag.outputs.tag }} | |
| name: Release ${{ steps.release_tag.outputs.tag }} | |
| # Do not specify target_commitish if the release already exists to avoid "immutable" error | |
| # Or ensure we are using the existing tag's commit | |
| # Removing it is usually safer for existing tags | |
| generate_release_notes: true | |
| files: | | |
| dist/*.tar.gz | |
| dist/*.dmg | |
| dist/*.zip | |
| token: ${{ secrets.GITHUB_TOKEN }} |