Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions .github/workflows/linux_build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
name: Linux build

# This workflow can be triggered manually OR called by another workflow
# (e.g. linux_tests.yml) via `workflow_call`. It does NOT trigger on push or
# pull_request directly — the test workflow is the push/PR entry point, so
# the build does not run twice.
on:
workflow_dispatch:
workflow_call:
inputs:
preset:
description: "CMake preset to build"
required: false
type: string
default: "default"
artifact-name:
description: "Name of the uploaded build artifact"
required: false
type: string
default: "linux-build-tree"
artifact-retention-days:
description: "How long to keep the build artifact"
required: false
type: number
default: 3
outputs:
artifact-name:
description: "Name of the uploaded build artifact"
value: ${{ inputs.artifact-name }}

# Avoid stacking redundant standalone runs on the same ref.
concurrency:
group: linux-build-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
name: Build (${{ inputs.preset || 'default' }})
runs-on: ubuntu-latest
timeout-minutes: 180

env:
# vcpkg *tool* clone (separate from external/vcpkg, which only holds the
# seahowl manifest + overlay ports).
VCPKG_ROOT: ${{ github.workspace }}/.vcpkg
# Cache built vcpkg packages in the GH Actions cache.
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
VCPKG_DISABLE_METRICS: "1"
# Keep memory/CPU usage modest on the standard GH runner.
VCPKG_MAX_CONCURRENCY: "2"
CMAKE_BUILD_PARALLEL_LEVEL: "2"

steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 1

- name: Read pinned vcpkg baseline
id: vcpkg
run: |
set -euo pipefail
baseline=$(python3 -c \
"import json; \
print(json.load(open('external/vcpkg/vcpkg-configuration.json'))['default-registry']['baseline'])")
echo "baseline=$baseline" >> "$GITHUB_OUTPUT"
echo "Pinned vcpkg baseline: $baseline"

- name: Install system build prerequisites
run: |
set -euxo pipefail
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential cmake ninja-build pkg-config \
gfortran \
curl zip unzip tar ca-certificates git \
autoconf automake autoconf-archive libtool \
bison flex \
python3 python3-pip

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Cache vcpkg tool clone
id: cache-vcpkg-tool
uses: actions/cache@v4
with:
path: ${{ env.VCPKG_ROOT }}
key: vcpkg-tool-${{ runner.os }}-${{ steps.vcpkg.outputs.baseline }}

- name: Clone vcpkg at pinned baseline
if: steps.cache-vcpkg-tool.outputs.cache-hit != 'true'
run: |
set -euxo pipefail
rm -rf "$VCPKG_ROOT"
git clone https://github.com/microsoft/vcpkg.git "$VCPKG_ROOT"
git -C "$VCPKG_ROOT" checkout "${{ steps.vcpkg.outputs.baseline }}"

- name: Bootstrap vcpkg if needed
run: |
set -euxo pipefail
if [ ! -x "$VCPKG_ROOT/vcpkg" ]; then
"$VCPKG_ROOT/bootstrap-vcpkg.sh" -disableMetrics
fi
"$VCPKG_ROOT/vcpkg" version

# Required for VCPKG_BINARY_SOURCES=x-gha
- name: Export GitHub Actions cache env for vcpkg
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');

- name: Configure
run: cmake --preset ${{ inputs.preset || 'default' }}

- name: Build
run: cmake --build build

# Tar the build tree so file permissions (executable bit on test
# binaries, symlinks on .so versions) survive the artifact round-trip.
- name: Package build tree
if: success()
run: |
set -euxo pipefail
tar --exclude='build/vcpkg_installed/vcpkg/buildtrees' \
--exclude='build/vcpkg_installed/vcpkg/downloads' \
--exclude='build/vcpkg_installed/vcpkg/packages' \
--exclude='build/_deps' \
-czf build-tree.tar.gz build

- name: Upload build artifact
if: success()
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.artifact-name || 'linux-build-tree' }}
path: build-tree.tar.gz
if-no-files-found: error
retention-days: ${{ inputs.artifact-retention-days || 3 }}

# --- Diagnostics on failure ---------------------------------------------

- name: Collect failure logs
if: failure()
run: |
set +e
mkdir -p ci-logs
if [ -d build/vcpkg_installed/vcpkg ]; then
find build/vcpkg_installed/vcpkg -maxdepth 4 \
\( -name 'install-*.log' \
-o -name 'config-*.log' \
-o -name 'build-*.log' \
-o -name 'issue_body.md' \) \
-exec cp --parents {} ci-logs/ \;
fi
for f in build/CMakeFiles/CMakeOutput.log \
build/CMakeFiles/CMakeError.log \
build/CMakeCache.txt; do
[ -f "$f" ] && cp --parents "$f" ci-logs/
done
ls -R ci-logs || true

- name: Upload failure logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: linux-build-failure-logs
path: ci-logs
if-no-files-found: ignore
retention-days: 7
70 changes: 70 additions & 0 deletions .github/workflows/linux_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Linux tests

on:
push:
branches: [main, dev]
pull_request:
branches: [main, dev]
workflow_dispatch:

concurrency:
group: linux-tests-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
# Call the reusable build workflow. Tests cannot run unless this succeeds.
name: Build
uses: ./.github/workflows/linux_build.yml
with:
preset: default
artifact-name: linux-build-tree
artifact-retention-days: 1

test_components:
name: Run test_components
needs: build
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
# The test_components binary embeds SEAHOWL_DATADIR pointing at the
# source tree at configure time (see CMakeLists.txt). Re-checkout at the
# same workspace path so those paths resolve.
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 1

- name: Install runtime prerequisites
run: |
set -euxo pipefail
sudo apt-get update
sudo apt-get install -y --no-install-recommends cmake ninja-build

- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: ${{ needs.build.outputs.artifact-name }}
path: .

- name: Unpack build tree
run: |
set -euxo pipefail
tar -xzf build-tree.tar.gz
rm -f build-tree.tar.gz
ls build/tests || true

- name: Run test_components
working-directory: build
run: ctest --output-on-failure -R '^test_components$' --no-tests=error

- name: Upload ctest logs on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: test_components-logs
path: build/Testing
if-no-files-found: ignore
retention-days: 7
Loading