|
| 1 | +name: Pamplejuce |
| 2 | + |
| 3 | +on: |
| 4 | + workflow_dispatch: # lets you run a build from the UI |
| 5 | + push: |
| 6 | + pull_request: |
| 7 | + |
| 8 | +# When pushing new commits, cancel any running builds on that branch |
| 9 | +concurrency: |
| 10 | + group: ${{ github.ref }} |
| 11 | + cancel-in-progress: true |
| 12 | + |
| 13 | +env: |
| 14 | + BUILD_TYPE: Release |
| 15 | + BUILD_DIR: Builds |
| 16 | + DISPLAY: :0 # linux pluginval needs this |
| 17 | + HOMEBREW_NO_INSTALL_CLEANUP: 1 |
| 18 | + SCCACHE_GHA_ENABLED: true |
| 19 | + SCCACHE_CACHE_MULTIARCH: 1 |
| 20 | + SCCACHE_IDLE_TIMEOUT: 0 |
| 21 | + |
| 22 | +defaults: |
| 23 | + run: |
| 24 | + shell: bash |
| 25 | + |
| 26 | +# jobs are run in parallel on different machines |
| 27 | +# all steps run in series |
| 28 | +jobs: |
| 29 | + build_and_test: |
| 30 | + # don't double run on PRs |
| 31 | + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name |
| 32 | + name: ${{ matrix.name }} |
| 33 | + runs-on: ${{ matrix.os }} |
| 34 | + strategy: |
| 35 | + fail-fast: false # show all errors for each platform (vs. cancel jobs on error) |
| 36 | + matrix: |
| 37 | + include: |
| 38 | + - name: Linux |
| 39 | + os: ubuntu-22.04 |
| 40 | + pluginval-binary: ./pluginval |
| 41 | + extra-flags: -G Ninja |
| 42 | + - name: macOS |
| 43 | + os: macos-14 |
| 44 | + pluginval-binary: pluginval.app/Contents/MacOS/pluginval |
| 45 | + extra-flags: -G Ninja -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" |
| 46 | + - name: Windows |
| 47 | + os: windows-latest |
| 48 | + pluginval-binary: ./pluginval.exe |
| 49 | + |
| 50 | + steps: |
| 51 | + # Setup MSVC toolchain and developer command prompt (Windows) |
| 52 | + - uses: ilammy/msvc-dev-cmd@v1 |
| 53 | + |
| 54 | + # Use clang on Linux so we don't introduce a 3rd compiler (Windows and macOS use MSVC and Clang) |
| 55 | + - name: Set up Clang |
| 56 | + if: runner.os == 'Linux' |
| 57 | + uses: egor-tensin/setup-clang@v1 |
| 58 | + |
| 59 | + # This also starts up our "fake" display (Xvfb), needed for pluginval |
| 60 | + - name: Install JUCE's Linux Deps |
| 61 | + if: runner.os == 'Linux' |
| 62 | + # Thanks to McMartin & co https://forum.juce.com/t/list-of-juce-dependencies-under-linux/15121/44 |
| 63 | + run: | |
| 64 | + # IPP stuff |
| 65 | + wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | gpg --dearmor | sudo tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null |
| 66 | + echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list |
| 67 | + |
| 68 | + sudo apt-get update && sudo apt install libasound2-dev libx11-dev libxinerama-dev libxext-dev libfreetype6-dev libwebkit2gtk-4.1-dev libglu1-mesa-dev xvfb ninja-build intel-oneapi-ipp-devel |
| 69 | + sudo /usr/bin/Xvfb $DISPLAY & |
| 70 | +
|
| 71 | + - name: Install IPP (Windows) |
| 72 | + if: (runner.os == 'Windows') |
| 73 | + run: | |
| 74 | + nuget install intelipp.static.win-x64 -Version 2022.3.0.387 |
| 75 | +
|
| 76 | + - name: Install Ninja (Windows) |
| 77 | + if: runner.os == 'Windows' |
| 78 | + run: choco install ninja |
| 79 | + |
| 80 | + - name: Install macOS Deps |
| 81 | + if: ${{ runner.os == 'macOS' }} |
| 82 | + run: brew install ninja osxutils |
| 83 | + |
| 84 | + - name: Checkout code |
| 85 | + uses: actions/checkout@v6 |
| 86 | + with: |
| 87 | + submodules: recursive |
| 88 | + |
| 89 | + - name: Cache the build |
| 90 | + uses: mozilla-actions/sccache-action@v0.0.9 |
| 91 | + |
| 92 | + - name: Configure |
| 93 | + run: cmake -B ${{ env.BUILD_DIR }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE}} -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache ${{ matrix.extra-flags }} . |
| 94 | + |
| 95 | + - name: Build |
| 96 | + run: cmake --build ${{ env.BUILD_DIR }} --config ${{ env.BUILD_TYPE }} |
| 97 | + |
| 98 | + - name: Test & Benchmarks |
| 99 | + working-directory: ${{ env.BUILD_DIR }} |
| 100 | + run: ctest --verbose --output-on-failure |
| 101 | + |
| 102 | + - name: Read in .env from CMake # see GitHubENV.cmake |
| 103 | + run: | |
| 104 | + cat .env # show us the config |
| 105 | + cat .env >> $GITHUB_ENV # pull in our PRODUCT_NAME, etc |
| 106 | +
|
| 107 | + - name: Set additional env vars for next steps |
| 108 | + run: | |
| 109 | + ARTIFACTS_PATH=${{ env.BUILD_DIR }}/${{ env.PROJECT_NAME }}_artefacts/${{ env.BUILD_TYPE }} |
| 110 | + echo "ARTIFACTS_PATH=$ARTIFACTS_PATH" >> $GITHUB_ENV |
| 111 | + echo "VST3_PATH=$ARTIFACTS_PATH/VST3/${{ env.PRODUCT_NAME }}.vst3" >> $GITHUB_ENV |
| 112 | + echo "AU_PATH=$ARTIFACTS_PATH/AU/${{ env.PRODUCT_NAME }}.component" >> $GITHUB_ENV |
| 113 | + echo "AUV3_PATH=$ARTIFACTS_PATH/AUv3/${{ env.PRODUCT_NAME }}.appex" >> $GITHUB_ENV |
| 114 | + echo "CLAP_PATH=$ARTIFACTS_PATH/CLAP/${{ env.PRODUCT_NAME }}.clap" >> $GITHUB_ENV |
| 115 | + echo "STANDALONE_PATH=$ARTIFACTS_PATH/Standalone/${{ env.PRODUCT_NAME }}.app" >> $GITHUB_ENV |
| 116 | + echo "ARTIFACT_NAME=${{ env.PRODUCT_NAME }}-${{ env.VERSION }}-${{ runner.os }}" >> $GITHUB_ENV |
| 117 | +
|
| 118 | + - name: Pluginval |
| 119 | + run: | |
| 120 | + curl -LO "https://github.com/Tracktion/pluginval/releases/download/v1.0.3/pluginval_${{ runner.os }}.zip" |
| 121 | + 7z x pluginval_${{ runner.os }}.zip |
| 122 | + ${{ matrix.pluginval-binary }} --strictness-level 10 --verbose --validate "${{ env.VST3_PATH }}" |
| 123 | +
|
| 124 | + - name: Import Certificates (macOS) |
| 125 | + uses: sudara/basic-macos-keychain-action@v1 |
| 126 | + id: keychain |
| 127 | + if: ${{ runner.os == 'macOS'}} |
| 128 | + with: |
| 129 | + dev-id-app-cert: ${{ secrets.DEV_ID_APP_CERT }} |
| 130 | + dev-id-app-password: ${{ secrets.DEV_ID_APP_PASSWORD }} |
| 131 | + dev-id-installer-cert: ${{ secrets.DEV_ID_INSTALLER_CERT }} |
| 132 | + dev-id-installer-password: ${{ secrets.DEV_ID_INSTALLER_PASSWORD }} |
| 133 | + |
| 134 | + - name: Codesign (macOS) |
| 135 | + if: ${{ runner.os == 'macOS' }} |
| 136 | + timeout-minutes: 5 |
| 137 | + run: | |
| 138 | + # Each plugin must be code signed |
| 139 | + codesign --force --keychain ${{ steps.keychain.outputs.keychain-path }} -s "${{ secrets.DEVELOPER_ID_APPLICATION}}" -v "${{ env.VST3_PATH }}" --deep --strict --options=runtime --timestamp |
| 140 | + codesign --force --keychain ${{ steps.keychain.outputs.keychain-path }} -s "${{ secrets.DEVELOPER_ID_APPLICATION}}" -v "${{ env.AU_PATH }}" --deep --strict --options=runtime --timestamp |
| 141 | + codesign --force --keychain ${{ steps.keychain.outputs.keychain-path }} -s "${{ secrets.DEVELOPER_ID_APPLICATION}}" -v "${{ env.CLAP_PATH }}" --deep --strict --options=runtime --timestamp |
| 142 | + codesign --force --keychain ${{ steps.keychain.outputs.keychain-path }} -s "${{ secrets.DEVELOPER_ID_APPLICATION}}" -v "${{ env.STANDALONE_PATH }}" --deep --strict --options=runtime --timestamp |
| 143 | +
|
| 144 | + - name: Add Custom Icons (macOS) |
| 145 | + if: ${{ runner.os == 'macOS' }} |
| 146 | + run: | |
| 147 | + # add the icns as its own icon resource (meta!) |
| 148 | + sips -i packaging/pamplejuce.icns |
| 149 | +
|
| 150 | + # Grab the resource, put in tempfile |
| 151 | + DeRez -only icns packaging/pamplejuce.icns > /tmp/icons |
| 152 | +
|
| 153 | + # Stuff the resource into the strange Icon? file's resource fork |
| 154 | + Rez -a /tmp/icons -o "${{ env.VST3_PATH }}/Icon"$'\r' |
| 155 | + Rez -a /tmp/icons -o "${{ env.AU_PATH }}/Icon"$'\r' |
| 156 | + Rez -a /tmp/icons -o "${{ env.CLAP_PATH }}/Icon"$'\r' |
| 157 | +
|
| 158 | + # Set custom icon attribute |
| 159 | + SetFile -a C "${{ env.VST3_PATH }}" |
| 160 | + SetFile -a C "${{ env.AU_PATH }}" |
| 161 | + SetFile -a C "${{ env.CLAP_PATH }}" |
| 162 | +
|
| 163 | + - name: pkgbuild, Productbuild and Notarize |
| 164 | + if: ${{ runner.os == 'macOS' }} |
| 165 | + timeout-minutes: 5 |
| 166 | + run: | |
| 167 | + pkgbuild --identifier "${{ env.BUNDLE_ID }}.au.pkg" --version $VERSION --component "${{ env.AU_PATH }}" --install-location "/Library/Audio/Plug-Ins/Components" "packaging/${{ env.PRODUCT_NAME }}.au.pkg" |
| 168 | + pkgbuild --identifier "${{ env.BUNDLE_ID }}.vst3.pkg" --version $VERSION --component "${{ env.VST3_PATH }}" --install-location "/Library/Audio/Plug-Ins/VST3" "packaging/${{ env.PRODUCT_NAME }}.vst3.pkg" |
| 169 | + pkgbuild --identifier "${{ env.BUNDLE_ID }}.clap.pkg" --version $VERSION --component "${{ env.CLAP_PATH }}" --install-location "/Library/Audio/Plug-Ins/CLAP" "packaging/${{ env.PRODUCT_NAME }}.clap.pkg" |
| 170 | +
|
| 171 | + # Standalone is special, needs a boolean to always install in /Applications |
| 172 | + pkgbuild --analyze --root "$(dirname "${{ env.STANDALONE_PATH }}")" standalone.plist |
| 173 | + plutil -replace BundleIsRelocatable -bool NO standalone.plist |
| 174 | + pkgbuild --identifier "${{ env.BUNDLE_ID }}.app.pkg" --version $VERSION --root "$(dirname "${{ env.STANDALONE_PATH }}")" --component-plist standalone.plist --install-location "/Applications" "packaging/${{ env.PRODUCT_NAME }}.app.pkg" |
| 175 | +
|
| 176 | + cd packaging |
| 177 | + envsubst < distribution.xml.template > distribution.xml |
| 178 | + productbuild --resources ./resources --distribution distribution.xml --sign "${{ secrets.DEVELOPER_ID_INSTALLER }}" --timestamp "${{ env.ARTIFACT_NAME }}.pkg" |
| 179 | +
|
| 180 | + xcrun notarytool submit "${{ env.ARTIFACT_NAME }}.pkg" --apple-id ${{ secrets.NOTARIZATION_USERNAME }} --password ${{ secrets.NOTARIZATION_PASSWORD }} --team-id ${{ secrets.TEAM_ID }} --wait |
| 181 | + xcrun stapler staple "${{ env.ARTIFACT_NAME }}.pkg" |
| 182 | +
|
| 183 | + - name: Zip |
| 184 | + if: ${{ runner.os == 'Linux' }} |
| 185 | + working-directory: ${{ env.ARTIFACTS_PATH }} |
| 186 | + run: 7z a -tzip "${{ env.ARTIFACT_NAME }}.zip" "-xr!lib${{ env.PRODUCT_NAME }}_SharedCode.a" . |
| 187 | + |
| 188 | + - name: Generate Installer |
| 189 | + if: ${{ runner.os == 'Windows' }} |
| 190 | + run: | |
| 191 | + iscc "packaging\installer.iss" |
| 192 | + mv "packaging/Output/${{ env.ARTIFACT_NAME }}.exe" "${{ env.ARTIFACTS_PATH }}/" |
| 193 | +
|
| 194 | + - name: Codesign with Azure Trusted Signing |
| 195 | + if: ${{ runner.os == 'Windows' }} |
| 196 | + uses: azure/trusted-signing-action@v0.5.11 |
| 197 | + with: |
| 198 | + # The Azure Active Directory tenant (directory) ID. |
| 199 | + azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} |
| 200 | + |
| 201 | + # The client (application) ID of an App Registration in the tenant. |
| 202 | + azure-client-id: ${{ secrets.AZURE_CLIENT_ID }} |
| 203 | + |
| 204 | + # A client secret that was generated for the App Registration. |
| 205 | + azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} |
| 206 | + |
| 207 | + # The Code Signing Account endpoint. The URI value must have a URI that aligns to the region your Code Signing Account and Certificate Profile you are specifying were created in during the setup of these resources. |
| 208 | + endpoint: ${{ secrets.AZURE_ENDPOINT }} |
| 209 | + |
| 210 | + # The Code Signing Account name. |
| 211 | + trusted-signing-account-name: ${{ secrets.AZURE_CODE_SIGNING_NAME }} |
| 212 | + |
| 213 | + # The Certificate Profile name. |
| 214 | + certificate-profile-name: ${{ secrets.AZURE_CERT_PROFILE_NAME }} |
| 215 | + |
| 216 | + # This signs all exes inside the folder |
| 217 | + files-folder: ${{ env.ARTIFACTS_PATH }} |
| 218 | + files-folder-filter: exe |
| 219 | + |
| 220 | + - name: Upload Exe (Windows) |
| 221 | + if: ${{ runner.os == 'Windows' }} |
| 222 | + uses: actions/upload-artifact@v6 |
| 223 | + with: |
| 224 | + name: ${{ env.ARTIFACT_NAME }}.exe |
| 225 | + path: "${{ env.ARTIFACTS_PATH }}/${{ env.ARTIFACT_NAME }}.exe" |
| 226 | + |
| 227 | + - name: Upload Zip (Linux) |
| 228 | + if: ${{ runner.os == 'Linux' }} |
| 229 | + uses: actions/upload-artifact@v6 |
| 230 | + with: |
| 231 | + name: ${{ env.ARTIFACT_NAME }}.zip |
| 232 | + path: "${{ env.ARTIFACTS_PATH }}/${{ env.ARTIFACT_NAME }}.zip" |
| 233 | + |
| 234 | + - name: Upload pkg (macOS) |
| 235 | + if: ${{ runner.os == 'macOS' }} |
| 236 | + uses: actions/upload-artifact@v6 |
| 237 | + with: |
| 238 | + name: ${{ env.ARTIFACT_NAME }}.pkg |
| 239 | + path: packaging/${{ env.ARTIFACT_NAME }}.pkg |
| 240 | + |
| 241 | + release: |
| 242 | + if: contains(github.ref, 'tags/v') |
| 243 | + runs-on: ubuntu-latest |
| 244 | + needs: build_and_test |
| 245 | + |
| 246 | + steps: |
| 247 | + - name: Get Artifacts |
| 248 | + uses: actions/download-artifact@v7 |
| 249 | + |
| 250 | + - name: Create Release |
| 251 | + uses: softprops/action-gh-release@v2 |
| 252 | + with: |
| 253 | + prerelease: true |
| 254 | + # download-artifact puts these files in their own dirs... |
| 255 | + # Using globs sidesteps having to pass the version around |
| 256 | + files: | |
| 257 | + */*.exe |
| 258 | + */*.zip |
| 259 | + */*.dmg |
0 commit comments