Build viewer #94
This file contains 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: Build viewer | |
on: | |
workflow_dispatch: | |
inputs: | |
include_tracy: | |
description: 'Include tracy profiling builds' | |
required: false | |
default: 'false' | |
push: | |
branches: | |
- "Firestorm*.*.*" | |
- "*alpha" | |
- "*nightly" | |
- "*preview" | |
schedule: | |
- cron: '00 03 * * *' # Run every day at 3am UTC | |
env: | |
AUTOBUILD_VARIABLES_FILE: ${{github.workspace}}/build-variables/variables | |
EXTRA_ARGS: -DUSE_FMODSTUDIO=ON -DUSE_KDU=ON --crashreporting | |
build_secrets_checkout: ${{github.workspace}}/signing | |
XZ_DEFAULTS: -T0 | |
FS_RELEASE_TYPE: Unknown | |
platform: Unknown | |
addrsize: 64 | |
fallback_platform: ${platform} | |
FS_RELEASE_CHAN: ${FS_RELEASE_TYPE}x64 | |
FS_GRID: "GRID FLAGS NOT SET" | |
PYTHON: | |
jobs: | |
build_matrix: | |
strategy: | |
matrix: | |
os: [macos-14,ubuntu-22.04,windows-2022] | |
grid: [sl,os] | |
variant: [regular, avx] | |
runs-on: ${{ matrix.os }} | |
outputs: | |
viewer_channel: ${{ steps.channel.outputs.viewer_channel }} | |
viewer_version: ${{ steps.version.outputs.viewer_version }} | |
viewer_variant: ${{ matrix.variant }} | |
viewer_build: ${{ steps.version.outputs.viewer_build }} | |
viewer_release_type: ${{ steps.version.outputs.viewer_release_type }} | |
steps: | |
- name: Install Bash 4 and GNU sed on Mac | |
if: runner.os == 'macOS' | |
run: | | |
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" | |
brew update | |
brew install bash | |
brew install gnu-sed | |
echo "/usr/local/bin" >> $GITHUB_PATH | |
echo "$(brew --prefix)/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH | |
- uses: actions/checkout@v4 | |
- uses: actions/setup-python@v5 | |
id: py311 | |
with: | |
python-version: '3.11' | |
- name: Set PYTHON environment for CMake | |
run: | | |
echo "PYTHON=${{ steps.py311.outputs.python-path }}" >> $GITHUB_ENV | |
shell: bash | |
- name: Install python requirements | |
run: | | |
python3 -m pip install -r requirements.txt | |
python -m pip install -r requirements.txt | |
# export the new python to the environment var $PYTHON | |
- name: Check python version | |
run: python -V | |
- name: Check python3 version | |
run: python3 -V | |
- name: Test python llsd | |
run: | | |
python - <<EOF | |
import llsd | |
print("Hello from inline Python script!") | |
EOF | |
shell: bash | |
- name: Test python3 llsd | |
run: | | |
python3 - <<EOF | |
import llsd | |
print("Hello from inline Python script!") | |
EOF | |
shell: bash | |
- name: Free Disk Space (Ubuntu) | |
if: runner.os == 'Linux' | |
uses: jlumbroso/free-disk-space@main | |
with: | |
swap-storage: false | |
# - name: Set gcc version on Linux | |
# if: runner.os == 'Linux' | |
# run: | | |
# echo "CC=gcc-10" >> $GITHUB_ENV | |
# echo "CXX=g++-10" >> $GITHUB_ENV | |
- name: Setup rclone and download the folder | |
uses: beqjanus/setup-rclone@main | |
with: | |
rclone_config: ${{ secrets.RCLONE_CONFIG }} | |
- name: Set OS/SL flags | |
run: echo "FS_GRID=-DOPENSIM:BOOL=$([ "${{ matrix.grid }}" == "os" ] && echo "ON" || echo "OFF") -DHAVOK_TPV:BOOL=$([ "${{ matrix.grid }}" == "sl" ] && echo "ON" || echo "OFF")" >> $GITHUB_ENV | |
shell: bash | |
- name: find channel from Branch name | |
id: channel | |
run: | | |
if [[ "${{ github.ref_name }}" == Firestorm* ]]; then | |
FS_RELEASE_TYPE=Release | |
elif [[ "${{ github.ref_name }}" == *review* ]]; then | |
FS_RELEASE_TYPE=Beta | |
elif [[ "${{ github.ref_name }}" == *alpha* ]]; then | |
FS_RELEASE_TYPE=Alpha | |
elif [[ "${{ github.ref_name }}" == *nightly* ]] || [[ "${{ github.event_name }}" == 'schedule' ]]; then | |
FS_RELEASE_TYPE=Nightly | |
elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
if [[ "${{ github.event.inputs.include_tracy }}" == "false" ]]; then | |
FS_RELEASE_TYPE=Manual | |
elif [[ "${{ github.event.inputs.include_tracy }}" == "true" ]]; then | |
FS_RELEASE_TYPE=Profiling | |
fi | |
fi | |
if [[ "${{ matrix.variant }}" == "avx" ]]; then | |
FS_RELEASE_CHAN="${FS_RELEASE_TYPE}x64" | |
else | |
FS_RELEASE_CHAN=${FS_RELEASE_TYPE} | |
fi | |
echo "FS_RELEASE_TYPE=${FS_RELEASE_TYPE}" >> $GITHUB_ENV | |
echo "FS_RELEASE_CHAN=${FS_RELEASE_CHAN}" >> $GITHUB_ENV | |
echo "Building for channel ${FS_RELEASE_CHAN}" | |
viewer_channel=${FS_RELEASE_CHAN} | |
shell: bash | |
- name: Get the code | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Checkout build vars (after the main code) | |
uses: actions/checkout@v4 | |
with: | |
repository: FirestormViewer/fs-build-variables | |
path: build-variables | |
- name: Define platform variable(s) | |
run: | | |
declare -A os_map | |
os_map=( ["Windows"]="windows" ["Linux"]="linux" ["macOS"]="darwin" ) | |
platform="${os_map[${{ runner.os}}]}" | |
echo "fallback_platform=${platform}" >> $GITHUB_ENV | |
platform+=${addrsize} | |
echo "platform=${platform}" >> $GITHUB_ENV | |
shell: bash | |
- name: rclone the private 3p packages for this platform (both 64 & 32) | |
run: 'rclone copy fs_bundles: --filter "- Alpha/*" --filter "+ *${{ env.fallback_platform }}*bz2" .' | |
- name: rclone any extra private 3p packages for Alpha (allows library updates not in the main repo) | |
if: env.FS_RELEASE_TYPE == 'Alpha' | |
run: 'rclone copy fs_bundles:Alpha --include "*${{ env.fallback_platform }}*bz2" .' | |
- name: set VSVER for Windows builds | |
if: runner.os == 'Windows' | |
run: echo "AUTOBUILD_VSVER=170" >> $GITHUB_ENV | |
shell: bash | |
- name: Install certificate | |
if: runner.os == 'macOS' | |
env: | |
FS_CERT: ${{ secrets.FS_CERT }} | |
FS_CERT_PASS: ${{ secrets.FS_CERT_PASS }} | |
FS_KEYCHAIN_PASS: ${{ secrets.FS_KEYCHAIN_PASS }} | |
NOTARIZE_CREDS: ${{ secrets.NOTARIZE_CREDS }} | |
run: | | |
mkdir -p ${build_secrets_checkout}/code-signing-osx | |
echo -n "$FS_CERT" | base64 --decode --output ${build_secrets_checkout}/code-signing-osx/fs-cert.p12 | |
echo -n "$FS_CERT_PASS" >${build_secrets_checkout}/code-signing-osx/password.txt | |
echo -n "$NOTARIZE_CREDS" | base64 --decode --output ${build_secrets_checkout}/code-signing-osx/notarize_creds.sh | |
security create-keychain -p "$FS_KEYCHAIN_PASS" ~/Library/Keychains/viewer.keychain | |
# notarize tool uses a specific database keychain by default we need to override this to ours. | |
security default-keychain -s viewer.keychain | |
security set-keychain-settings -lut 21600 ~/Library/Keychains/viewer.keychain | |
security unlock-keychain -p "$FS_KEYCHAIN_PASS" ~/Library/Keychains/viewer.keychain | |
security import ${build_secrets_checkout}/code-signing-osx/fs-cert.p12 -P "$FS_CERT_PASS" -A -t cert -f pkcs12 -k ~/Library/Keychains/viewer.keychain | |
security set-key-partition-list -S apple-tool:,apple:, -s -k "$FS_KEYCHAIN_PASS" -t private ~/Library/Keychains/viewer.keychain | |
security list-keychain -d user -s ~/Library/Keychains/viewer.keychain | |
- name: Install required Ubuntu packages and release some space. | |
if: runner.os == 'Linux' | |
run: | | |
dependencies=("python3-setuptools" "mesa-common-dev" "libgl1-mesa-dev" "libxinerama-dev" "libxrandr-dev" "libpulse-dev" "libglu1-mesa-dev" "libfreetype6-dev" "libfontconfig1") | |
sudo apt-get update | |
sudo apt-get install -y "${dependencies[@]}" | |
sudo apt-get install -y wget apt-transport-https software-properties-common | |
sudo apt-get autoremove --purge | |
sudo apt-get clean | |
- name: Install Microsoft repository GPG keys | |
if: runner.os == 'Linux' | |
run: | | |
wget -q "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" -O packages-microsoft-prod.deb | |
sudo dpkg -i packages-microsoft-prod.deb | |
rm packages-microsoft-prod.deb | |
sudo apt-get update | |
sudo apt-get install -y powershell | |
pwsh -c '$PSVersionTable' | |
- name: test macOS bundles are present | |
if: runner.os == 'MacOS' | |
run: | | |
dirlisting="$(ls -l ${{ github.workspace }}${path_sep}${pattern})" | |
echo "${dirlisting}" | |
shell: bash | |
- name: edit installables | |
run: | | |
path_sep="/" | |
if [[ "${{ runner.os }}" == "Windows" ]]; then | |
path_sep="\\" | |
fi | |
function find_most_recent_bundle() { | |
local pattern="$1-.*$2[-_]+.*" | |
local most_recent_file=$(ls -t "${{ github.workspace }}" | egrep "$pattern" | head -1) | |
if [ -z "$most_recent_file" ]; then | |
echo "" | |
else | |
echo "$most_recent_file" | |
fi | |
} | |
packages=("fmodstudio" "llphysicsextensions_tpv" "kdu") | |
for package in "${packages[@]}"; do | |
package_file=$(find_most_recent_bundle $package ${{ env.platform }}) | |
full_package_path="${{ github.workspace }}${path_sep}${package_file}" | |
if [ -n "$package_file" ]; then | |
echo "Installing ${package_file}" | |
autobuild installables remove ${package} | |
autobuild installables add ${package} platform=${{ env.platform }} url="file:///${full_package_path}" | |
else | |
echo "No bundle found for ${package} on ${{ env.platform }}" | |
package_file=$(find_most_recent_bundle $package ${{ env.fallback_platform }}) | |
full_package_path="${{ github.workspace }}${path_sep}${package_file}" | |
if [ -n "$package_file" ]; then | |
echo "Installing ${package_file}" | |
autobuild installables remove ${package} | |
autobuild installables add ${package} platform=${{ env.fallback_platform }} url="file:///${full_package_path}" | |
else | |
echo "No bundle found for ${package} on ${{ env.fallback_platform }}. Package will not be available for build." | |
fi | |
fi | |
done | |
shell: bash | |
- name: Set expiration days based on FS_RELEASE_TYPE | |
run: | | |
case "${{ env.FS_RELEASE_TYPE }}" in | |
"Nightly" | "Manual" | "Profiling") | |
EXPIRE_DAYS=14 | |
;; | |
"Alpha") | |
EXPIRE_DAYS=28 | |
;; | |
"Beta") | |
EXPIRE_DAYS=60 | |
;; | |
*) | |
EXPIRE_DAYS="" | |
;; | |
esac | |
if [ -n "$EXPIRE_DAYS" ]; then | |
echo "This ${{ env.FS_RELEASE_TYPE }} build will expire in $EXPIRE_DAYS" | |
echo "EXTRA_ARGS=${{ env.EXTRA_ARGS}} --testbuild=$EXPIRE_DAYS" >> $GITHUB_ENV | |
else | |
echo "This ${{ env.FS_RELEASE_TYPE }} has no built in expiry" | |
echo "EXTRA_ARGS=${{ env.EXTRA_ARGS}}" >> $GITHUB_ENV | |
fi | |
shell: bash | |
- name: Add tracy builds for dev use if selected (manual builds only). | |
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.include_tracy == 'true' }} | |
shell: bash | |
run: echo "EXTRA_ARGS=${{ env.EXTRA_ARGS }} --tracy" >> $GITHUB_ENV | |
- name: Add flags for AVX2 builds | |
if: ${{ matrix.variant == 'avx' }} | |
shell: bash | |
run: echo "EXTRA_ARGS=${{ env.EXTRA_ARGS }} --avx2" >> $GITHUB_ENV | |
- name: Clean up packages to give more space | |
run: rm *${{ env.fallback_platform }}*bz2 | |
shell: bash | |
- name: Configure | |
run: | | |
autobuild configure -c ReleaseFS -A${addrsize} -- --package --chan ${{env.FS_RELEASE_CHAN}} ${{env.EXTRA_ARGS}} ${{env.FS_GRID}} | |
echo "BUGSPLAT_DB=$BUGSPLAT_DB" >> $GITHUB_ENV | |
shell: bash | |
- name: build | |
id: build | |
run: autobuild build -c ReleaseFS -A${addrsize} --no-configure | |
shell: bash | |
- name: Extract version number | |
id: version | |
shell: bash | |
run: | | |
if [ -r "indra/newview/VIEWER_VERSION.txt" ] | |
then | |
viewer_version="$(<"indra/newview/VIEWER_VERSION.txt")" | |
echo "viewer_version=$viewer_version" >> "$GITHUB_OUTPUT" | |
fi | |
viewer_build=$(git rev-list --count HEAD) | |
echo "viewer_build=$viewer_build" >> "$GITHUB_OUTPUT" | |
echo "viewer_channel=${{ env.FS_RELEASE_CHAN }}" >> "$GITHUB_OUTPUT" | |
echo "viewer_release_type=${{ env.FS_RELEASE_TYPE }}" >> "$GITHUB_OUTPUT" | |
- name: Unzip xcarchive.zip files | |
if: runner.os == 'macOS' | |
run: | | |
find . -name '*.xcarchive.zip' -exec sh -c 'unzip -o "{}" -d "$(dirname "{}")"' \; | |
- name: Post Bugsplat Symbols | |
uses: BugSplat-Git/symbol-upload@main | |
with: | |
clientId: ${{ | |
steps.version.outputs.viewer_release_type == 'Release' && secrets.BUGSPLAT_RELEASE_ID || | |
steps.version.outputs.viewer_release_type == 'Nightly' && secrets.BUGSPLAT_NIGHTLY_ID || | |
steps.version.outputs.viewer_release_type == 'Manual' && secrets.BUGSPLAT_MANUAL_ID || | |
steps.version.outputs.viewer_release_type == 'Beta' && secrets.BUGSPLAT_PREVIEW_ID || | |
steps.version.outputs.viewer_release_type == 'Alpha' && secrets.BUGSPLAT_ALPHA_ID || | |
secrets.BUGSPLAT_DEFAULT_ID }} | |
clientSecret: ${{ | |
steps.version.outputs.viewer_release_type == 'Release' && secrets.BUGSPLAT_RELEASE_SECRET || | |
steps.version.outputs.viewer_release_type == 'Nightly' && secrets.BUGSPLAT_NIGHTLY_SECRET || | |
steps.version.outputs.viewer_release_type == 'Manual' && secrets.BUGSPLAT_MANUAL_SECRET || | |
steps.version.outputs.viewer_release_type == 'Beta' && secrets.BUGSPLAT_PREVIEW_SECRET || | |
steps.version.outputs.viewer_release_type == 'Alpha' && secrets.BUGSPLAT_ALPHA_SECRET || | |
secrets.BUGSPLAT_DEFAULT_SECRET }} | |
database: ${{ | |
steps.version.outputs.viewer_release_type == 'Release' && secrets.BUGSPLAT_RELEASE_DB || | |
steps.version.outputs.viewer_release_type == 'Nightly' && secrets.BUGSPLAT_NIGHTLY_DB || | |
steps.version.outputs.viewer_release_type == 'Manual' && secrets.BUGSPLAT_MANUAL_DB || | |
steps.version.outputs.viewer_release_type == 'Beta' && secrets.BUGSPLAT_PREVIEW_DB || | |
steps.version.outputs.viewer_release_type == 'Alpha' && secrets.BUGSPLAT_ALPHA_DB || | |
secrets.BUGSPLAT_DEFAULT_DB }} | |
application: "Firestorm-${{ steps.version.outputs.viewer_channel}}" | |
version: ${{ steps.version.outputs.viewer_version }}.${{ steps.version.outputs.viewer_build }} | |
files: ${{ runner.os == 'Windows' && '**/Release/*.{pdb,exe,dll}' || runner.os == 'macOS' && '**/Release/{Firestorm,*.dSYM}' || '**/{do-not-run-directly-firestorm-bin,*.sym}' }} | |
directory: "build-*" | |
node-version: "20" | |
dumpSyms: false | |
- name: Publish artifacts | |
if: runner.os == 'Windows' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ env.FS_RELEASE_TYPE }}-${{ matrix.os }}-${{ matrix.variant }}-${{ matrix.grid }}-artifacts.zip | |
path: | | |
build-*/newview/Release/*Setup.exe | |
build-*/newview/Release/*.xz | |
- name: publish Linux artifacts | |
if: runner.os == 'Linux' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ env.FS_RELEASE_TYPE }}-${{ matrix.os }}-${{ matrix.variant }}-${{matrix.grid}}-artifacts.zip | |
path: | | |
build-linux-*/newview/*.xz | |
build-linux-*/newview/*.bz2 | |
- name: publish MacOS artifacts | |
if: runner.os == 'macOS' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ env.FS_RELEASE_TYPE }}-${{ matrix.os }}-${{ matrix.variant }}-${{matrix.grid}}-artifacts.zip | |
path: | | |
build-darwin-*/newview/*.dmg | |
build-darwin-*/newview/*.bz2 | |
deploy: | |
runs-on: ubuntu-latest | |
needs: build_matrix | |
env: | |
FS_BUILD_WEBHOOK_URL: | |
FS_RELEASE_FOLDER: | |
if: always() | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
with: | |
sparse-checkout: | | |
fsutils/download_list.py | |
fsutils/build_config.json | |
fsutils/build_config.py | |
sparse-checkout-cone-mode: false | |
ref: ${{ github.head_ref || github.ref_name || 'master' }} | |
fetch-depth: 1 | |
- name: Install discord-webhook library | |
run: pip install discord-webhook | |
- name: Download artifacts | |
uses: actions/download-artifact@v4 | |
id: download | |
with: | |
path: to_deploy | |
- name: find channel and webhook from build_matrix outputs | |
run: | | |
viewer_release_type=${{ needs.build_matrix.outputs.viewer_release_type }} | |
if [[ "$viewer_release_type" == "Release" ]]; then | |
FS_RELEASE_FOLDER=release | |
FS_BUILD_WEBHOOK_URL=${{ secrets.RELEASE_WEBHOOK_URL }} | |
elif [[ "$viewer_release_type" == "Beta" ]]; then | |
FS_RELEASE_FOLDER=preview | |
FS_BUILD_WEBHOOK_URL=${{ secrets.BETA_WEBHOOK_URL }} | |
elif [[ "$viewer_release_type" == "Alpha" ]]; then | |
FS_RELEASE_FOLDER=test | |
FS_BUILD_WEBHOOK_URL=${{ secrets.BETA_WEBHOOK_URL }} | |
elif [[ "$viewer_release_type" == "Nightly" ]] || [[ "${{ github.event_name }}" == 'schedule' ]]; then | |
FS_RELEASE_FOLDER=nightly | |
FS_BUILD_WEBHOOK_URL=${{ secrets.NIGHTLY_WEBHOOK_URL }} | |
elif [[ "$viewer_release_type" == "Manual" ]]; then | |
FS_RELEASE_FOLDER=test | |
FS_BUILD_WEBHOOK_URL=${{ secrets.MANUAL_WEBHOOK_URL }} | |
else | |
FS_RELEASE_TYPE=Unknown | |
fi | |
echo "FS_RELEASE_FOLDER=${FS_RELEASE_FOLDER}" >> $GITHUB_ENV | |
echo "FS_BUILD_WEBHOOK_URL=${FS_BUILD_WEBHOOK_URL}" >> $GITHUB_ENV | |
- name: List artifacts download | |
run: ls -R | |
working-directory: ${{steps.download.outputs.download-path}} | |
- name: Create Build Info artifact | |
env: | |
FS_VIEWER_VERSION: | |
FS_VIEWER_BUILD: | |
FS_VIEWER_RELEASE_TYPE: | |
id: create_build_info | |
run: | | |
cat <<EOF > build_info.json | |
{ | |
"build_run_number": "${{ github.run_number }}", | |
"release_type": "${{ needs.build_matrix.outputs.viewer_release_type }}", | |
"viewer_version": "${{ needs.build_matrix.outputs.viewer_version }}", | |
"viewer_build": "${{ needs.build_matrix.outputs.viewer_build }}" | |
} | |
EOF | |
echo "Build info created: $(cat build_info.json)" | |
# Upload Build Info Artifact (note that this file is expected to be identical for each matrix run, so items like OS and VARIANT cannot be in this file.) | |
- name: Upload Tag Info | |
uses: actions/upload-artifact@v4 | |
with: | |
name: build_info | |
path: build_info.json | |
- name: Reorganise artifacts ready for server upload. | |
env: | |
FS_VIEWER_VERSION: ${{ needs.build_matrix.outputs.viewer_version }} | |
FS_VIEWER_BUILD: ${{ needs.build_matrix.outputs.viewer_build }} | |
FS_VIEWER_RELEASE_TYPE: ${{ needs.build_matrix.outputs.viewer_release_type }} | |
FS_VERSION_MGR_KEY: ${{ secrets.FS_VERSION_MGR_KEY }} | |
run: python ./fsutils/download_list.py ${{steps.download.outputs.download-path}} -w ${{ env.FS_BUILD_WEBHOOK_URL }} | |
- name: Setup rclone and download the folder | |
uses: beqjanus/setup-rclone@main | |
with: | |
rclone_config: ${{ secrets.RCLONE_CONFIG }} | |
- name: Copy files to remote host | |
run: rclone copy ${{steps.download.outputs.download-path}}/${{ env.FS_RELEASE_FOLDER }} fs_r2_deploy:viewerdownloads/${{ env.FS_RELEASE_FOLDER }} | |