Revert "Fix memory leak" #402
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: Multi-platform build | |
| on: | |
| push: | |
| branches: [ "main", "development" ] | |
| pull_request: | |
| branches: [ "main" ] | |
| workflow_dispatch: | |
| jobs: | |
| config: | |
| name: Configure Workflow | |
| runs-on: ubuntu-latest | |
| outputs: | |
| enable_freebsd: ${{ steps.set_vars.outputs.enable_freebsd }} | |
| steps: | |
| - id: set_vars | |
| run: echo "enable_freebsd=true" >> "$GITHUB_OUTPUT" | |
| build: | |
| name: build (${{ matrix.asset_name }}) | |
| runs-on: ${{ matrix.runs_on }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - id: ubuntu-gcc | |
| runs_on: ubuntu-latest | |
| build_type: Release | |
| c_compiler: gcc | |
| cpp_compiler: g++ | |
| ocaml_version: "4.14.2" | |
| binary_path: bin/Release/chsl | |
| asset_name: "linux-x64-gcc" | |
| - id: ubuntu-clang | |
| runs_on: ubuntu-latest | |
| build_type: Release | |
| c_compiler: clang | |
| cpp_compiler: clang++ | |
| ocaml_version: "4.14.2" | |
| binary_path: bin/Release/chsl | |
| asset_name: "linux-x64-clang" | |
| - id: ubuntu-arm | |
| runs_on: ubuntu-24.04-arm | |
| build_type: Release | |
| c_compiler: gcc | |
| cpp_compiler: g++ | |
| ocaml_version: "4.14.2" | |
| binary_path: bin/Release/chsl | |
| asset_name: "linux-arm64" | |
| - id: macos-intel | |
| runs_on: macos-15-intel | |
| build_type: Release | |
| c_compiler: clang | |
| cpp_compiler: clang++ | |
| ocaml_version: "4.14.2" | |
| binary_path: bin/Release/chsl | |
| asset_name: "macos-x64" | |
| - id: macos-arm | |
| runs_on: macos-26 | |
| build_type: Release | |
| c_compiler: clang | |
| cpp_compiler: clang++ | |
| ocaml_version: "4.14.2" | |
| binary_path: bin/Release/chsl | |
| asset_name: "macos-arm64" | |
| - id: windows-x64 | |
| runs_on: windows-latest | |
| build_type: Release | |
| c_compiler: cl | |
| cpp_compiler: cl | |
| extra_cmake_args: -DENABLE_MP3PACKER=OFF -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static | |
| binary_path: bin/Release/chsl.exe | |
| asset_name: "windows-x64" | |
| - id: windows-arm | |
| runs_on: windows-11-arm | |
| build_type: Release | |
| c_compiler: cl | |
| cpp_compiler: cl | |
| extra_cmake_args: -DENABLE_MP3PACKER=OFF -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=arm64-windows-static | |
| binary_path: bin/Release/chsl.exe | |
| asset_name: "windows-arm64" | |
| steps: | |
| - name: Disable Git AutoCRLF | |
| if: runner.os == 'Windows' && (!contains(matrix.extra_cmake_args, 'ENABLE_MP3PACKER=OFF')) | |
| run: git config --global core.autocrlf false | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| submodules: recursive | |
| fetch-depth: 0 | |
| lfs: true | |
| - name: Setup Git LFS | |
| run: | | |
| git lfs install | |
| git lfs pull | |
| - name: Set up OCaml | |
| if: (!contains(matrix.extra_cmake_args, 'ENABLE_MP3PACKER=OFF')) | |
| uses: ocaml/setup-ocaml@v3 | |
| with: | |
| ocaml-compiler: ${{ matrix.ocaml_version }} | |
| dune-cache: true | |
| - name: Install OCaml Dependencies | |
| if: (!contains(matrix.extra_cmake_args, 'ENABLE_MP3PACKER=OFF')) | |
| run: | | |
| opam install dune dune-configurator --yes | |
| opam exec -- ocamlopt -version | |
| - name: Install build dependencies (Linux) | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y build-essential cmake ninja-build pkg-config \ | |
| autoconf automake libtool m4 nasm yasm curl unzip tar gzip python3-pip | |
| - name: Install build dependencies (macOS) | |
| if: runner.os == 'macOS' | |
| run: | | |
| brew update | |
| brew remove --force $(brew list --formula) | |
| brew remove --cask --force $(brew list) | |
| brew install autoconf automake libtool nasm yasm cmake ninja | |
| - name: Setup MSVC Developer Environment | |
| if: runner.os == 'Windows' | |
| uses: TheMrMilchmann/setup-msvc-dev@v4 | |
| with: | |
| arch: ${{ matrix.id == 'windows-arm' && 'arm64' || 'x64' }} | |
| - name: Install build dependencies (Windows) | |
| if: runner.os == 'Windows' | |
| run: choco install ninja | |
| - name: Set up Rust | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| toolchain: stable | |
| - name: Set build output directory | |
| id: strings | |
| shell: bash | |
| run: echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" | |
| - name: Configure CMake | |
| run: > | |
| cmake -B ${{ steps.strings.outputs.build-output-dir }} | |
| -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} | |
| -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} | |
| -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} | |
| ${{ matrix.extra_cmake_args }} | |
| -S ${{ github.workspace }} | |
| - name: Build | |
| run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} | |
| - name: Determine Version | |
| shell: bash | |
| run: | | |
| if [[ $GITHUB_REF == refs/tags/v* ]]; then | |
| echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV | |
| else | |
| echo "VERSION=dev" >> $GITHUB_ENV | |
| fi | |
| - name: Rename Binary | |
| shell: bash | |
| run: | | |
| EXT="" | |
| SRC="${{ matrix.binary_path }}" | |
| if [[ "${{ runner.os }}" == "Windows" ]]; then | |
| EXT=".exe" | |
| if [[ "$SRC" != *".exe" ]]; then SRC="$SRC.exe"; fi | |
| fi | |
| DEST="chsl-${{ matrix.asset_name }}-${{ env.VERSION }}$EXT" | |
| echo "Renaming $SRC to $DEST" | |
| mv "$SRC" "$DEST" | |
| echo "ARTIFACT_PATH=$DEST" >> $GITHUB_ENV | |
| - name: Upload binary artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: binary-${{ matrix.asset_name }} | |
| path: ${{ env.ARTIFACT_PATH }} | |
| if-no-files-found: error | |
| build-freebsd-x64: | |
| name: build (freebsd-x64) | |
| needs: config | |
| if: needs.config.outputs.enable_freebsd == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| submodules: recursive | |
| fetch-depth: 0 | |
| lfs: true | |
| - name: Setup Git LFS | |
| run: | | |
| git lfs install | |
| git lfs pull | |
| - name: Build on FreeBSD | |
| uses: vmactions/freebsd-vm@v1 | |
| with: | |
| arch: amd64 | |
| release: "15.0" | |
| usesh: true | |
| prepare: | | |
| pkg install -y cmake ninja pkgconf autoconf automake libtool m4 nasm yasm gmake git llvm20 rust | |
| run: | | |
| echo "--- Starting FreeBSD Build ---" | |
| export MAKE=gmake | |
| mkdir -p $HOME/bin | |
| ln -s /usr/local/bin/gmake $HOME/bin/make | |
| export PATH=$HOME/bin:$PATH | |
| # disable mp3packer as ocaml is not installed | |
| cmake -G Ninja -DCMAKE_CXX_STANDARD=20 \ | |
| -DCMAKE_C_COMPILER=/usr/local/bin/clang20 \ | |
| -DCMAKE_CXX_COMPILER=/usr/local/bin/clang++20 \ | |
| -DCMAKE_CXX_FLAGS="-stdlib=libc++ -fexperimental-library" \ | |
| -DCMAKE_EXE_LINKER_FLAGS="-stdlib=libc++ -fexperimental-library" \ | |
| -DENABLE_MP3PACKER=OFF \ | |
| -B build -DCMAKE_BUILD_TYPE=Release -S ${{ github.workspace }} | |
| cmake --build build --config Release | |
| echo "--- Build Complete ---" | |
| - name: Determine Version | |
| shell: bash | |
| run: | | |
| if [[ $GITHUB_REF == refs/tags/v* ]]; then | |
| echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV | |
| else | |
| echo "VERSION=dev" >> $GITHUB_ENV | |
| fi | |
| - name: Rename Binary | |
| shell: bash | |
| run: | | |
| SRC="bin/Release/chsl" | |
| DEST="chsl-freebsd-x64-${{ env.VERSION }}" | |
| echo "Renaming $SRC to $DEST" | |
| mv "$SRC" "$DEST" | |
| echo "ARTIFACT_PATH=$DEST" >> $GITHUB_ENV | |
| - name: Upload binary artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: binary-freebsd-x64 | |
| path: ${{ env.ARTIFACT_PATH }} | |
| if-no-files-found: error | |
| build-freebsd-arm64: | |
| name: build (freebsd-arm64) | |
| needs: config | |
| if: needs.config.outputs.enable_freebsd == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| submodules: recursive | |
| fetch-depth: 0 | |
| lfs: true | |
| - name: Setup Git LFS | |
| run: | | |
| git lfs install | |
| git lfs pull | |
| - name: Build on FreeBSD | |
| uses: vmactions/freebsd-vm@v1 | |
| with: | |
| arch: arm64 | |
| release: "15.0" | |
| usesh: true | |
| prepare: | | |
| pkg install -y cmake ninja pkgconf autoconf automake libtool m4 nasm yasm gmake git llvm20 rust | |
| run: | | |
| echo "--- Starting FreeBSD Build ---" | |
| export MAKE=gmake | |
| mkdir -p $HOME/bin | |
| ln -s /usr/local/bin/gmake $HOME/bin/make | |
| export PATH=$HOME/bin:$PATH | |
| # disable mp3packer as ocaml is not installed | |
| cmake -G Ninja -DCMAKE_CXX_STANDARD=20 \ | |
| -DCMAKE_C_COMPILER=/usr/local/bin/clang20 \ | |
| -DCMAKE_CXX_COMPILER=/usr/local/bin/clang++20 \ | |
| -DCMAKE_CXX_FLAGS="-stdlib=libc++ -fexperimental-library" \ | |
| -DCMAKE_EXE_LINKER_FLAGS="-stdlib=libc++ -fexperimental-library" \ | |
| -DENABLE_MP3PACKER=OFF \ | |
| -B build -DCMAKE_BUILD_TYPE=Release -S ${{ github.workspace }} | |
| cmake --build build --config Release | |
| echo "--- Build Complete ---" | |
| - name: Determine Version | |
| shell: bash | |
| run: | | |
| if [[ $GITHUB_REF == refs/tags/v* ]]; then | |
| echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV | |
| else | |
| echo "VERSION=dev" >> $GITHUB_ENV | |
| fi | |
| - name: Rename Binary | |
| shell: bash | |
| run: | | |
| SRC="bin/Release/chsl" | |
| DEST="chsl-freebsd-arm64-${{ env.VERSION }}" | |
| echo "Renaming $SRC to $DEST" | |
| mv "$SRC" "$DEST" | |
| echo "ARTIFACT_PATH=$DEST" >> $GITHUB_ENV | |
| - name: Upload binary artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: binary-freebsd-arm64 | |
| path: ${{ env.ARTIFACT_PATH }} | |
| if-no-files-found: error | |
| test: | |
| name: test (${{ matrix.asset_name }}) | |
| needs: build | |
| runs-on: ${{ matrix.runs_on }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - id: ubuntu-gcc | |
| runs_on: ubuntu-latest | |
| asset_name: "linux-x64-gcc" | |
| - id: ubuntu-clang | |
| runs_on: ubuntu-latest | |
| asset_name: "linux-x64-clang" | |
| - id: ubuntu-arm | |
| runs_on: ubuntu-24.04-arm | |
| asset_name: "linux-arm64" | |
| - id: macos-intel | |
| runs_on: macos-15-intel | |
| asset_name: "macos-x64" | |
| - id: macos-arm | |
| runs_on: macos-26 | |
| asset_name: "macos-arm64" | |
| - id: windows-x64 | |
| runs_on: windows-latest | |
| asset_name: "windows-x64" | |
| # disabled, takes longer than 6 hours | |
| #- id: windows-arm | |
| # runs_on: windows-11-arm | |
| # asset_name: "windows-arm64" | |
| env: | |
| TEST_ARCHIVE_NAME: chisel_samples.zip | |
| TEST_DIR: test-data | |
| BIN_DIR: bin | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Download binary artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: binary-${{ matrix.asset_name }} | |
| path: ${{ env.BIN_DIR }} | |
| - name: Restore Binary Name | |
| shell: bash | |
| run: | | |
| cd ${{ env.BIN_DIR }} | |
| find . -maxdepth 1 -type f -name "chsl-*" ! -name "chsl" ! -name "chsl.exe" -exec mv {} chsl \; || true | |
| if [[ "${{ runner.os }}" == "Windows" ]] && [ -f "chsl" ]; then | |
| mv chsl chsl.exe | |
| fi | |
| ls -la | |
| - name: Make binary executable | |
| if: runner.os != 'Windows' | |
| run: chmod +x ${{ env.BIN_DIR }}/chsl | |
| shell: bash | |
| - name: Install test dependencies (Linux) | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y python3-pip unzip | |
| pip3 install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib | |
| - name: Install test dependencies (macOS) | |
| if: runner.os == 'macOS' | |
| run: | | |
| brew install unzip | |
| python3 -m venv ${{ github.workspace }}/venv-gdrive | |
| ${{ github.workspace }}/venv-gdrive/bin/pip3 install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib | |
| - name: Install test dependencies (Windows) | |
| if: runner.os == 'Windows' | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib | |
| shell: bash | |
| - name: Cache test data archive | |
| id: cache-test-archive | |
| uses: actions/cache@v5 | |
| with: | |
| path: ${{ env.TEST_ARCHIVE_NAME }} | |
| key: ${{ runner.os }}-testarchive-v1-${{ secrets.GDRIVE_FILE_ID }} | |
| - name: Authenticate and Download Test Data from Google Drive | |
| if: steps.cache-test-archive.outputs.cache-hit != 'true' | |
| env: | |
| GDRIVE_CREDENTIALS_JSON: ${{ secrets.GDRIVE_CREDENTIALS_JSON }} | |
| GDRIVE_FILE_ID: ${{ secrets.GDRIVE_FILE_ID }} | |
| run: | | |
| PY_EXE="python3" | |
| if [[ "$RUNNER_OS" == "Windows" ]]; then | |
| PY_EXE="python" | |
| elif [[ "$RUNNER_OS" == "macOS" ]]; then | |
| # Point to the python inside the venv | |
| PY_EXE="${{ github.workspace }}/venv-gdrive/bin/python3" | |
| fi | |
| "$PY_EXE" -c " | |
| import os | |
| import io | |
| import json | |
| import sys | |
| from google.oauth2 import service_account | |
| from googleapiclient.discovery import build | |
| from googleapiclient.http import MediaIoBaseDownload | |
| creds_json_string = os.environ.get('GDRIVE_CREDENTIALS_JSON') | |
| if not creds_json_string: | |
| print('::error::Secret GDRIVE_CREDENTIALS_JSON is not set.', file=sys.stderr) | |
| sys.exit(1) | |
| try: | |
| creds_info = json.loads(creds_json_string) | |
| creds = service_account.Credentials.from_service_account_info(creds_info) | |
| except json.JSONDecodeError: | |
| print('::error::Could not decode credentials JSON. Check the secret.', file=sys.stderr) | |
| sys.exit(1) | |
| except Exception as e: | |
| print(f'::error::Failed to load service account credentials: {e}', file=sys.stderr) | |
| sys.exit(1) | |
| file_id = os.environ.get('GDRIVE_FILE_ID') | |
| output_filename = os.environ.get('TEST_ARCHIVE_NAME') | |
| if not file_id: | |
| print('::error::Secret GDRIVE_FILE_ID is not set.', file=sys.stderr) | |
| sys.exit(1) | |
| if not output_filename: | |
| print('::error::Environment variable TEST_ARCHIVE_NAME is not set.', file=sys.stderr) | |
| sys.exit(1) | |
| print(f'Authenticating and creating Google Drive service...') | |
| try: | |
| service = build('drive', 'v3', credentials=creds) | |
| except Exception as e: | |
| print(f'::error::Failed to build Drive service: {e}', file=sys.stderr) | |
| sys.exit(1) | |
| print(f'Requesting file ID: {file_id}...') | |
| try: | |
| request = service.files().get_media(fileId=file_id) | |
| except Exception as e: | |
| print(f'::error::Failed to create download request for file ID {file_id}: {e}', file=sys.stderr) | |
| sys.exit(1) | |
| try: | |
| print(f'Opening output file: {output_filename}...') | |
| fh = io.FileIO(output_filename, 'wb') | |
| except Exception as e: | |
| print(f'::error::Failed to open output file {output_filename} for writing: {e}', file=sys.stderr) | |
| sys.exit(1) | |
| downloader = MediaIoBaseDownload(fh, request) | |
| done = False | |
| print(f'Starting download -> {output_filename}...') | |
| try: | |
| while done is False: | |
| status, done = downloader.next_chunk() | |
| if status: | |
| print(f'Download {int(status.progress() * 100)}%.') | |
| except Exception as e: | |
| print(f'::error::Download failed: {e}', file=sys.stderr) | |
| # Ensure file handle is closed before attempting removal | |
| if not fh.closed: | |
| fh.close() | |
| # Attempt to remove partially downloaded file | |
| try: | |
| if os.path.exists(output_filename): | |
| os.remove(output_filename) | |
| print(f'Removed partially downloaded file: {output_filename}') | |
| except OSError as oe: | |
| print(f'Warning: Could not remove partial file {output_filename}: {oe}', file=sys.stderr) | |
| sys.exit(1) | |
| finally: | |
| # Ensure file handle is closed even if download finished successfully | |
| if not fh.closed: | |
| fh.close() | |
| print(f'Download complete: {output_filename}.') | |
| " | |
| shell: bash | |
| - name: Extract Test Data | |
| run: | | |
| echo "Extracting test data..." | |
| mkdir ${{ env.TEST_DIR }} | |
| unzip -q ${{ env.TEST_ARCHIVE_NAME }} -d ${{ env.TEST_DIR }} | |
| shell: bash | |
| - name: Run Chisel Tests | |
| run: | | |
| if [[ "$RUNNER_OS" == "Windows" ]]; then | |
| CHISEL_EXE="./${{ env.BIN_DIR }}/chsl.exe" | |
| else | |
| CHISEL_EXE="./${{ env.BIN_DIR }}/chsl" | |
| fi | |
| echo "Running chisel from: $CHISEL_EXE" | |
| echo "Processing files in: ${{ env.TEST_DIR }}" | |
| if [[ "$RUNNER_OS" == "Windows" ]]; then | |
| "$CHISEL_EXE" "${{ env.TEST_DIR }}" --recursive --threads 3 --log-level=ALL --log-file chisel.log --iterations 2 --iterations-large 2 | |
| else | |
| "$CHISEL_EXE" "${{ env.TEST_DIR }}" --recursive --threads 4 --log-level=ALL --log-file chisel.log --iterations 2 --iterations-large 2 | |
| fi | |
| shell: bash | |
| - name: Check for errors in Chisel Log | |
| if: always() | |
| run: | | |
| LOG_FILE="build/chisel.log" | |
| if [ ! -f "$LOG_FILE" ]; then | |
| if [ -f "${{ github.workspace }}/chisel.log" ]; then | |
| LOG_FILE="${{ github.workspace }}/chisel.log" | |
| elif [ -f "chisel.log" ]; then | |
| LOG_FILE="chisel.log" | |
| else | |
| echo "Log file not found at build/chisel.log, ${{ github.workspace }}/chisel.log, or current directory." | |
| exit 0 | |
| fi | |
| fi | |
| echo "Checking log file at: $LOG_FILE" | |
| if grep -q '\[ERROR\]' "$LOG_FILE"; then | |
| echo "::error::Errors detected in chisel.log!" | |
| grep '\[ERROR\]' "$LOG_FILE" | |
| exit 1 | |
| else | |
| echo "No [ERROR] lines found in chisel.log." | |
| exit 0 | |
| fi | |
| shell: bash | |
| - name: Upload Chisel Log File | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: chisel-log-${{ matrix.id }} | |
| path: | | |
| build/chisel.log | |
| ${{ github.workspace }}/chisel.log | |
| chisel.log | |
| if-no-files-found: warn | |
| retention-days: 7 | |
| test-freebsd: | |
| name: test (${{ matrix.asset_name }}) | |
| if: needs.config.outputs.enable_freebsd == 'true' | |
| needs: [config, build-freebsd-x64] | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - id: freebsd-x64 | |
| arch: amd64 | |
| asset_name: "freebsd-x64" | |
| # disabled, takes too long | |
| # - id: freebsd-arm | |
| # arch: arm64 | |
| # asset_name: "freebsd-arm64" | |
| env: | |
| TEST_ARCHIVE_NAME: chisel_samples.zip | |
| TEST_DIR: test-data | |
| BIN_DIR: bin | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Download binary artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: binary-${{ matrix.asset_name }} | |
| path: ${{ env.BIN_DIR }} | |
| - name: Restore Binary Name | |
| shell: bash | |
| run: | | |
| cd ${{ env.BIN_DIR }} | |
| find . -maxdepth 1 -type f -name "chsl-*" ! -name "chsl" -exec mv {} chsl \; || true | |
| ls -la | |
| - name: Make binary executable (Host) | |
| run: chmod +x ${{ env.BIN_DIR }}/chsl | |
| - name: Install test dependencies (Linux Host for GDrive) | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y python3-pip unzip | |
| pip3 install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib | |
| - name: Cache test data archive | |
| id: cache-test-archive | |
| uses: actions/cache@v5 | |
| with: | |
| path: ${{ env.TEST_ARCHIVE_NAME }} | |
| key: ${{ runner.os }}-testarchive-v1-${{ secrets.GDRIVE_FILE_ID }} | |
| - name: Authenticate and Download Test Data from Google Drive | |
| if: steps.cache-test-archive.outputs.cache-hit != 'true' | |
| env: | |
| GDRIVE_CREDENTIALS_JSON: ${{ secrets.GDRIVE_CREDENTIALS_JSON }} | |
| GDRIVE_FILE_ID: ${{ secrets.GDRIVE_FILE_ID }} | |
| run: | | |
| python3 -c " | |
| import os, io, json, sys | |
| from google.oauth2 import service_account | |
| from googleapiclient.discovery import build | |
| from googleapiclient.http import MediaIoBaseDownload | |
| creds_json_string = os.environ.get('GDRIVE_CREDENTIALS_JSON') | |
| if not creds_json_string: sys.exit(1) | |
| try: | |
| creds_info = json.loads(creds_json_string) | |
| creds = service_account.Credentials.from_service_account_info(creds_info) | |
| except: sys.exit(1) | |
| file_id = os.environ.get('GDRIVE_FILE_ID') | |
| output_filename = os.environ.get('TEST_ARCHIVE_NAME') | |
| if not file_id or not output_filename: sys.exit(1) | |
| try: service = build('drive', 'v3', credentials=creds) | |
| except: sys.exit(1) | |
| try: request = service.files().get_media(fileId=file_id) | |
| except: sys.exit(1) | |
| try: fh = io.FileIO(output_filename, 'wb') | |
| except: sys.exit(1) | |
| downloader = MediaIoBaseDownload(fh, request) | |
| done = False | |
| try: | |
| while done is False: status, done = downloader.next_chunk() | |
| except: | |
| if not fh.closed: fh.close() | |
| try: | |
| if os.path.exists(output_filename): os.remove(output_filename) | |
| except: pass | |
| sys.exit(1) | |
| finally: | |
| if not fh.closed: fh.close() | |
| " | |
| shell: bash | |
| - name: Extract Test Data | |
| run: | | |
| echo "Extracting test data..." | |
| mkdir ${{ env.TEST_DIR }} | |
| unzip -q ${{ env.TEST_ARCHIVE_NAME }} -d ${{ env.TEST_DIR }} | |
| shell: bash | |
| - name: Run Chisel Tests (in FreeBSD VM) | |
| uses: vmactions/freebsd-vm@v1 | |
| with: | |
| arch: ${{ matrix.arch }} | |
| release: "15.0" | |
| usesh: true | |
| run: | | |
| echo "--- Starting FreeBSD Test ---" | |
| CHISEL_EXE="./${{ env.BIN_DIR }}/chsl" | |
| echo "Running chisel from: $CHISEL_EXE" | |
| echo "Processing files in: ${{ env.TEST_DIR }}" | |
| $CHISEL_EXE "${{ env.TEST_DIR }}" --recursive --threads 4 --log-level=ALL --log-file chisel.log | |
| echo "--- Test Run Complete ---" | |
| - name: Check for errors in Chisel Log | |
| if: always() | |
| run: | | |
| LOG_FILE="chisel.log" | |
| if grep -q '\[ERROR\]' "$LOG_FILE"; then | |
| echo "::error::Errors detected in chisel.log!" | |
| grep '\[ERROR\]' "$LOG_FILE" | |
| exit 1 | |
| else | |
| echo "No [ERROR] lines found in chisel.log." | |
| exit 0 | |
| fi | |
| shell: bash | |
| - name: Upload Chisel Log File | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: chisel-log-${{ matrix.asset_name }} | |
| path: chisel.log | |
| if-no-files-found: warn | |
| retention-days: 7 | |
| combine-logs: | |
| name: combine-logs | |
| needs: [test, test-freebsd] | |
| runs-on: ubuntu-latest | |
| if: always() | |
| steps: | |
| - name: Download all log artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| pattern: chisel-log-* | |
| path: logs | |
| - name: Combine logs | |
| run: | | |
| mkdir -p combined | |
| find logs -type f -name "*.log" -exec cat {} + > combined/chisel-combined.log | |
| sort -u combined/chisel-combined.log > combined/chisel-combined-unique.log | |
| - name: Upload combined log | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: chisel-combined-logs | |
| path: combined/ | |
| retention-days: 14 | |
| publish_nightly: | |
| name: Publish Nightly Pre-Release | |
| runs-on: ubuntu-latest | |
| needs: [test, test-freebsd] | |
| if: | | |
| always() && | |
| needs.test.result == 'success' && | |
| (needs.test-freebsd.result == 'success' || needs.test-freebsd.result == 'skipped') && | |
| github.ref == 'refs/heads/development' | |
| permissions: | |
| actions: read | |
| contents: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Download all build and log artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: artifacts/ | |
| - name: Prepare assets for release | |
| run: | | |
| mkdir release_assets | |
| function package_unix { | |
| SRC_DIR="artifacts/$1" | |
| OUT_NAME="$2" | |
| # skip if freebsd artifact is missing | |
| if [ ! -d "$SRC_DIR" ]; then return; fi | |
| mv "$SRC_DIR"/* "release_assets/chsl" | |
| chmod +x "release_assets/chsl" | |
| tar -czf "release_assets/$OUT_NAME.tar.gz" -C release_assets "chsl" | |
| rm "release_assets/chsl" | |
| } | |
| function package_windows { | |
| SRC_DIR="artifacts/$1" | |
| OUT_NAME="$2" | |
| mv "$SRC_DIR"/*.exe "release_assets/chsl.exe" | |
| zip -j "release_assets/$OUT_NAME.zip" "release_assets/chsl.exe" | |
| rm "release_assets/chsl.exe" | |
| } | |
| # --- FreeBSD --- | |
| package_unix "binary-freebsd-x64" "chsl-freebsd-x64" | |
| package_unix "binary-freebsd-arm64" "chsl-freebsd-arm64" | |
| # --- Linux --- | |
| package_unix "binary-linux-x64-gcc" "chsl-linux-x64-gcc" | |
| package_unix "binary-linux-x64-clang" "chsl-linux-x64-clang" | |
| package_unix "binary-linux-arm64" "chsl-linux-arm64" | |
| # --- macOS --- | |
| package_unix "binary-macos-x64" "chsl-macos-x64" | |
| package_unix "binary-macos-arm64" "chsl-macos-arm64" | |
| # --- Windows --- | |
| package_windows "binary-windows-x64" "chsl-windows-x64" | |
| package_windows "binary-windows-arm64" "chsl-windows-arm64" | |
| # --- Logs --- | |
| find artifacts/ -type f -name '*.log' -exec cp {} release_assets/ \; | |
| - name: Delete and recreate 'development-latest' release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release delete development-latest -y || echo "No previous nightly release to delete." | |
| git push origin --delete development-latest || echo "No previous nightly tag to delete." | |
| gh release create development-latest \ | |
| --prerelease \ | |
| --title "Nightly Build" \ | |
| --notes "Latest successful build from 'development' branch. Not a stable release." \ | |
| release_assets/* | |
| publish_stable: | |
| name: Publish Stable Release | |
| runs-on: ubuntu-latest | |
| needs: [test, test-freebsd] | |
| if: | | |
| always() && | |
| needs.test.result == 'success' && | |
| (needs.test-freebsd.result == 'success' || needs.test-freebsd.result == 'skipped') && | |
| startsWith(github.ref, 'refs/tags/v') | |
| permissions: | |
| actions: read | |
| contents: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Download all build and log artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: artifacts/ | |
| - name: Prepare assets for release | |
| run: | | |
| mkdir release_assets | |
| function package_unix { | |
| SRC_DIR="artifacts/$1" | |
| OUT_NAME="$2" | |
| # skip if freebsd artifact is missing | |
| if [ ! -d "$SRC_DIR" ]; then return; fi | |
| mv "$SRC_DIR"/* "release_assets/$OUT_NAME" | |
| chmod +x "release_assets/$OUT_NAME" | |
| tar -czf "release_assets/$OUT_NAME.tar.gz" -C release_assets "$OUT_NAME" | |
| rm "release_assets/$OUT_NAME" | |
| } | |
| function package_windows { | |
| SRC_DIR="artifacts/$1" | |
| OUT_NAME="$2" | |
| mv "$SRC_DIR"/*.exe "release_assets/$OUT_NAME.exe" | |
| zip -j "release_assets/$OUT_NAME.zip" "release_assets/$OUT_NAME.exe" | |
| rm "release_assets/$OUT_NAME.exe" | |
| } | |
| # Packaging | |
| package_unix "binary-linux-x64-gcc" "chsl-linux-x64-gcc" | |
| package_unix "binary-linux-x64-clang" "chsl-linux-x64-clang" | |
| package_unix "binary-linux-arm64" "chsl-linux-arm64" | |
| package_unix "binary-macos-x64" "chsl-macos-x64" | |
| package_unix "binary-macos-arm64" "chsl-macos-arm64" | |
| package_unix "binary-freebsd-x64" "chsl-freebsd-x64" | |
| package_unix "binary-freebsd-arm64" "chsl-freebsd-arm64" | |
| package_windows "binary-windows-x64" "chsl-windows-x64" | |
| package_windows "binary-windows-arm64" "chsl-windows-arm64" | |
| # Logs | |
| find artifacts/ -type f -name '*.log' -exec cp {} release_assets/ \; | |
| - name: Create Release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release create ${{ github.ref_name }} \ | |
| --title "Chisel ${{ github.ref_name }}" \ | |
| --generate-notes \ | |
| release_assets/* | |
| verify-static-linking: | |
| name: verify-static-linking (${{ matrix.asset_name }}) | |
| needs: build | |
| runs-on: ${{ matrix.runs_on }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - id: ubuntu-gcc | |
| runs_on: ubuntu-latest | |
| asset_name: "linux-x64-gcc" | |
| - id: ubuntu-clang | |
| runs_on: ubuntu-latest | |
| asset_name: "linux-x64-clang" | |
| - id: ubuntu-arm | |
| runs_on: ubuntu-24.04-arm | |
| asset_name: "linux-arm64" | |
| - id: macos-intel | |
| runs_on: macos-15-intel | |
| asset_name: "macos-x64" | |
| - id: macos-arm | |
| runs_on: macos-15 | |
| asset_name: "macos-arm64" | |
| - id: windows-x64 | |
| runs_on: windows-latest | |
| asset_name: "windows-x64" | |
| - id: windows-arm | |
| runs_on: windows-11-arm | |
| asset_name: "windows-arm64" | |
| env: | |
| BIN_DIR: bin | |
| FORBIDDEN_LIBS: "jpeg|png|flac|archive|zlib|jxl|tiff|qpdf|webp|wavpack|sqlite|magic|mseed|ebml|matroska|mkclean|zopfli|ape|gif|mac|flexigif|tag" | |
| steps: | |
| - name: Setup MSVC Developer Environment | |
| if: runner.os == 'Windows' | |
| uses: TheMrMilchmann/setup-msvc-dev@v4 | |
| with: | |
| arch: ${{ matrix.id == 'windows-arm' && 'arm64' || 'x64' }} | |
| - name: Download binary artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: binary-${{ matrix.asset_name }} | |
| path: ${{ env.BIN_DIR }} | |
| - name: Restore Binary Name | |
| shell: bash | |
| run: | | |
| cd ${{ env.BIN_DIR }} | |
| find . -maxdepth 1 -type f -name "chsl-*" ! -name "chsl" ! -name "chsl.exe" -exec mv {} chsl \; || true | |
| if [[ "${{ runner.os }}" == "Windows" ]] && [ -f "chsl" ]; then | |
| mv chsl chsl.exe | |
| fi | |
| ls -la | |
| - name: Make binary executable | |
| if: runner.os != 'Windows' | |
| run: chmod +x ${{ env.BIN_DIR }}/chsl | |
| - name: Verify Linux (ldd) | |
| if: runner.os == 'Linux' | |
| run: | | |
| echo "Checking dependencies for Linux..." | |
| ldd ${{ env.BIN_DIR }}/chsl | |
| echo "---" | |
| matches=$(ldd ${{ env.BIN_DIR }}/chsl | grep -iE "(${FORBIDDEN_LIBS})" || true) | |
| if [ -n "$matches" ]; then | |
| echo "::error::Found forbidden dynamic libraries!" | |
| echo "$matches" | |
| exit 1 | |
| else | |
| echo "OK: No forbidden dynamic libraries found." | |
| fi | |
| - name: Verify macOS (otool) | |
| if: runner.os == 'macOS' | |
| run: | | |
| echo "Checking dependencies for macOS..." | |
| otool -L ${{ env.BIN_DIR }}/chsl | |
| echo "---" | |
| matches=$(otool -L ${{ env.BIN_DIR }}/chsl | grep -iE "(${FORBIDDEN_LIBS})" || true) | |
| if [ -n "$matches" ]; then | |
| echo "::error::Found forbidden dynamic libraries!" | |
| echo "$matches" | |
| exit 1 | |
| else | |
| echo "OK: No forbidden dynamic libraries found." | |
| fi | |
| - name: Verify Windows (dumpbin + PowerShell) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| Write-Output "Checking dependencies for Windows..." | |
| $deps = & dumpbin /dependents "${{ env.BIN_DIR }}\chsl.exe" | |
| $deps | Out-String | Write-Output | |
| Write-Output "---" | |
| $pattern = [regex]"(${env:FORBIDDEN_LIBS})\.dll" | |
| $matches = $deps | Select-String -Pattern $pattern -AllMatches | |
| if ($matches) { | |
| Write-Error "Found forbidden dynamic libraries!" | |
| $matches | ForEach-Object { $_.Matches.Value } | Sort-Object -Unique | ForEach-Object { Write-Output $_ } | |
| exit 1 | |
| } else { | |
| Write-Output "OK: No forbidden dynamic libraries found." | |
| } | |
| verify-static-linking-freebsd: | |
| name: verify-static-linking (${{ matrix.asset_name }}) | |
| if: needs.config.outputs.enable_freebsd == 'true' | |
| needs: [config, build-freebsd-x64, build-freebsd-arm64] | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - id: freebsd-x64 | |
| arch: amd64 | |
| asset_name: "freebsd-x64" | |
| - id: freebsd-arm | |
| arch: arm64 | |
| asset_name: "freebsd-arm64" | |
| env: | |
| BIN_DIR: bin | |
| FORBIDDEN_LIBS: "jpeg|png|flac|archive|zlib|jxl|tiff|qpdf|webp|wavpack|sqlite|magic|mseed|ebml|matroska|mkclean|zopfli|ape|gif|mac|flexigif|tag" | |
| steps: | |
| - name: Download binary artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: binary-${{ matrix.asset_name }} | |
| path: ${{ env.BIN_DIR }} | |
| - name: Restore Binary Name | |
| shell: bash | |
| run: | | |
| cd ${{ env.BIN_DIR }} | |
| find . -maxdepth 1 -type f -name "chsl-*" ! -name "chsl" -exec mv {} chsl \; || true | |
| - name: Make binary executable (Host) | |
| run: chmod +x ${{ env.BIN_DIR }}/chsl | |
| - name: Verify FreeBSD (ldd) | |
| uses: vmactions/freebsd-vm@v1 | |
| with: | |
| arch: ${{ matrix.arch }} | |
| release: "15.0" | |
| usesh: true | |
| run: | | |
| echo "Checking dependencies for FreeBSD..." | |
| ldd ${{ env.BIN_DIR }}/chsl | |
| echo "---" | |
| matches=$(ldd ${{ env.BIN_DIR }}/chsl | grep -iE "(${FORBIDDEN_LIBS})" || true) | |
| if [ -n "$matches" ]; then | |
| echo "::error::Found forbidden dynamic libraries!" | |
| echo "$matches" | |
| exit 1 | |
| else | |
| echo "OK: No forbidden dynamic libraries found." | |
| fi |