Files
aego/.github/workflows/github-native.yml

349 lines
15 KiB
YAML

name: github-native
on:
push:
branches: [master]
tags: ['v*']
pull_request:
workflow_dispatch:
inputs:
stage_commit:
description: 'Optional full commit SHA for isolated Stage remote-store tests'
required: false
type: string
stage_art_checks:
description: 'Also test real Aseprite fixtures and editor import on native OS (headless)'
required: false
default: false
type: boolean
stage_web_checks:
description: 'Also run isolated Stage Asset Studio build and protocol checks (no GUI)'
required: false
default: false
type: boolean
permissions:
contents: read
jobs:
gitea-pending:
if: github.server_url == 'https://github.com'
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- name: Test status reporter
run: python3 -m unittest discover -s tools/ci -p gitea_status_test.py
- name: Report queued native jobs to Gitea
if: github.repository == 'Alexander-D-Karpov/aego' && github.ref == 'refs/heads/master' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
continue-on-error: true
env:
GITEA_STATUS_TOKEN: ${{ secrets.GITEA_STATUS_TOKEN }}
run: python3 tools/ci/gitea_status.py pending
native:
needs: gitea-pending
if: github.server_url == 'https://github.com' && !(github.event_name == 'workflow_dispatch' && inputs.stage_commit != '')
name: ${{ matrix.goos }} ${{ matrix.goarch }} native
# Gitea may assign a runner before evaluating job-level `if`. Route its
# skipped matrix entries to the available Linux runner instead of leaving
# Windows/macOS entries queued forever.
runs-on: ${{ github.server_url == 'https://github.com' && matrix.runner || 'ubuntu-24.04' }}
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
include:
- { runner: windows-2025, goos: windows, goarch: amd64 }
- { runner: macos-15, goos: darwin, goarch: arm64 }
- { runner: macos-15-intel, goos: darwin, goarch: amd64 }
- { runner: ubuntu-24.04, goos: linux, goarch: amd64 }
defaults:
run:
shell: bash
env:
CGO_ENABLED: '1'
AEGO_LANG: en
EXPECT_GOOS: ${{ matrix.goos }}
EXPECT_GOARCH: ${{ matrix.goarch }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
# Run the fast, isolated registry checks before unrelated build/tests so
# their result is still visible when an earlier native test fails.
- name: Test PATH editing rules with Windows PowerShell
if: runner.os == 'Windows'
shell: powershell
run: ./tools/ci/windows-user-path-test.ps1
- name: Test PATH editing rules with PowerShell 7
if: runner.os == 'Windows'
shell: pwsh
run: ./tools/ci/windows-user-path-test.ps1
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go.mod
cache: false
- name: Windows native toolchain
if: runner.os == 'Windows'
id: msys2
uses: msys2/setup-msys2@ec48f7c5447b3140e2b088413ae3a55687bccb6e # v2
with:
msystem: UCRT64
update: false
install: >-
mingw-w64-ucrt-x86_64-gcc
mingw-w64-ucrt-x86_64-cmake
mingw-w64-ucrt-x86_64-ninja
mingw-w64-ucrt-x86_64-nsis
- name: Windows toolchain path
if: runner.os == 'Windows'
env:
MSYS2_LOCATION: ${{ steps.msys2.outputs.msys2-location }}
run: echo "${MSYS2_LOCATION}\\ucrt64\\bin" >> "$GITHUB_PATH"
- name: macOS tools
if: runner.os == 'macOS'
run: brew list ninja >/dev/null 2>&1 || brew install ninja
- name: Linux dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake ninja-build pkg-config openssl \
libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev \
libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev libxkbcommon-dev \
libwayland-dev wayland-protocols libdecor-0-dev \
libasound2-dev libpulse-dev libdrm-dev libgbm-dev libudev-dev libdbus-1-dev libibus-1.0-dev \
glslang-tools=15.1.0-2~ubuntu0.24.04.2
bash tools/check-glslang.sh
- name: Build pinned shader validator
if: runner.os != 'Linux'
run: bash tools/ci/github-glslang.sh
- name: Record environment and check architecture
run: |
mkdir -p .cache/github-ci/logs
{
echo "commit=$(git rev-parse HEAD)"
echo "event_sha=$GITHUB_SHA"
echo "runner=$RUNNER_OS/$RUNNER_ARCH"
uname -a
go version
go env GOOS GOARCH CGO_ENABLED CC
cmake --version
gcc --version
} > .cache/github-ci/logs/environment.txt 2>&1
cat .cache/github-ci/logs/environment.txt
test "$(git rev-parse HEAD)" = "$GITHUB_SHA"
test "$(go env GOOS)" = "$EXPECT_GOOS"
test "$(go env GOARCH)" = "$EXPECT_GOARCH"
test "$(go env CGO_ENABLED)" = 1
- name: Build pinned SDL
id: native_sdl
run: bash tools/bootstrap-native.sh 2>&1 | tee .cache/github-ci/logs/bootstrap.txt
- name: Build all packages
id: native_build
run: go build ./... 2>&1 | tee .cache/github-ci/logs/build.txt
- name: Native platform tests
if: runner.os != 'Linux'
run: |
if [ "$RUNNER_OS" = Windows ]; then py=python; else py=python3; fi
"$py" -m unittest discover -s tools/ci -p native_test_groups_test.py
"$py" tools/ci/native_test_groups.py 2>&1 | tee .cache/github-ci/logs/tests.txt
- name: Linux compatibility tests
if: runner.os == 'Linux'
run: go test -count=1 ./asset/... ./engine/... ./runtime/... ./update/... 2>&1 | tee .cache/github-ci/logs/tests.txt
- name: Strict headless smoke
run: go run ./cmd/sandbox --demo headless --frames 600 --strict-allocs
- name: CLI and headless runtime smoke
run: bash tools/ci/github-cli-smoke.sh 2>&1 | tee .cache/github-ci/logs/cli-smoke.txt
- name: Build Windows portable and installer
# Collect installer diagnostics even if an unrelated test failed. A
# failed test still fails the job and prevents all artifact uploads.
if: ${{ runner.os == 'Windows' && (success() || failure()) && steps.native_sdl.conclusion == 'success' && steps.native_build.conclusion == 'success' }}
id: windows_package
run: bash tools/ci/github-windows-package.sh 2>&1 | tee .cache/github-ci/logs/windows-package.txt
- name: Native silent installer and uninstaller
if: ${{ runner.os == 'Windows' && (success() || failure()) && steps.windows_package.conclusion == 'success' }}
shell: pwsh
run: ./tools/ci/github-windows-installer-smoke.ps1
- name: Build macOS app bundle
if: runner.os == 'macOS'
run: bash tools/ci/github-macos-package.sh 2>&1 | tee .cache/github-ci/logs/macos-package.txt
- name: Package Linux CLI
if: runner.os == 'Linux'
run: |
mkdir -p .cache/github-ci/dist/linux
cp .cache/github-ci/bin/aego .cache/github-ci/dist/linux/aego-linux-amd64
cd .cache/github-ci/dist/linux
sha256sum aego-linux-amd64 > SHA256SUMS.txt
- name: Upload diagnostic logs
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: native-logs-${{ matrix.goos }}-${{ matrix.goarch }}
path: .cache/github-ci/logs/
include-hidden-files: true
if-no-files-found: ignore
- name: Upload Windows portable
if: runner.os == 'Windows' && success()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: windows-amd64-portable-unsigned
path: .cache/github-ci/dist/portable/
include-hidden-files: true
if-no-files-found: error
- name: Upload Windows installer
if: runner.os == 'Windows' && success()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: windows-amd64-installer-unsigned
path: .cache/github-ci/dist/installer/
include-hidden-files: true
if-no-files-found: error
- name: Upload macOS app
if: runner.os == 'macOS' && success()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: macos-${{ matrix.goarch }}-app-not-notarized
path: .cache/github-ci/dist/macos/
include-hidden-files: true
if-no-files-found: error
- name: Upload Linux CLI
if: runner.os == 'Linux' && success()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: linux-amd64-cli
path: .cache/github-ci/dist/linux/
include-hidden-files: true
if-no-files-found: error
stage-remote-store:
if: github.server_url == 'https://github.com' && github.event_name == 'workflow_dispatch' && inputs.stage_commit != ''
name: stage remote store ${{ matrix.goos }} ${{ matrix.goarch }}
runs-on: ${{ matrix.runner }}
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
include:
- { runner: windows-2025, goos: windows, goarch: amd64 }
- { runner: macos-15, goos: darwin, goarch: arm64 }
- { runner: macos-15-intel, goos: darwin, goarch: amd64 }
env:
CGO_ENABLED: '0'
GOFLAGS: '-mod=readonly'
STAGE_COMMIT: ${{ inputs.stage_commit }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
ref: ${{ inputs.stage_commit }}
persist-credentials: false
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go.mod
cache: false
- name: Record Windows temporary directory ACL
if: runner.os == 'Windows'
shell: pwsh
run: |
$dir = Get-Item -LiteralPath $env:TEMP
while ($null -ne $dir) {
Write-Host "ACL $($dir.FullName)"
Get-Acl -LiteralPath $dir.FullName | Format-List Owner,AccessToString
$dir = $dir.Parent
}
- name: Test exact Stage commit on native host
shell: bash
run: |
set -o pipefail
[[ "$STAGE_COMMIT" =~ ^[0-9a-f]{40}$ ]]
test "$(git rev-parse HEAD)" = "$STAGE_COMMIT"
test "$(go env GOOS)" = '${{ matrix.goos }}'
test "$(go env GOARCH)" = '${{ matrix.goarch }}'
go version
go test -count=1 -v ./project/remoteexample
- name: Test Stage Aseprite import without a GUI
if: ${{ inputs.stage_art_checks }}
shell: bash
run: |
set -o pipefail
# Check inventory explicitly: a missing test must not be reported as PASS.
go test -tags aego_nonative -list '^TestRealAsepriteFilesMatchLibreSpriteAndRoundTrip$' ./art | grep -Fx TestRealAsepriteFilesMatchLibreSpriteAndRoundTrip
go test -tags aego_nonative -list '^TestAsepriteImportCommandOpensEditableDocumentAndPreservesSource$' ./modules/render2d/editor | grep -Fx TestAsepriteImportCommandOpensEditableDocumentAndPreservesSource
go test -tags aego_nonative -list '^TestReadExternalFileIsBoundedAndRegular$' ./asset/pipeline | grep -Fx TestReadExternalFileIsBoundedAndRegular
go test -tags aego_nonative -count=1 -run '^TestRealAseprite' -v ./art
go test -tags aego_nonative -count=1 -run '^TestAsepriteImport' -v ./modules/render2d/editor
go test -tags aego_nonative -count=1 -run '^TestReadExternalFile' -v ./asset/pipeline
- name: Build Stage Asset Studio release tool
if: ${{ inputs.stage_web_checks }}
shell: bash
run: |
set -euo pipefail
go build -tags aego_nonative -o "$RUNNER_TEMP/aego-artstudio-release" ./tools/artstudio/release
stage-web:
if: github.server_url == 'https://github.com' && github.event_name == 'workflow_dispatch' && inputs.stage_commit != '' && inputs.stage_web_checks
name: stage Asset Studio web checks (headless)
runs-on: ubuntu-24.04
timeout-minutes: 25
env:
GOFLAGS: '-mod=readonly'
STAGE_COMMIT: ${{ inputs.stage_commit }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
ref: ${{ inputs.stage_commit }}
persist-credentials: false
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go.mod
cache: false
- name: Check exact Stage tree and scoped tests
shell: bash
run: |
set -euo pipefail
[[ "$STAGE_COMMIT" =~ ^[0-9a-f]{40}$ ]]
test "$(git rev-parse HEAD)" = "$STAGE_COMMIT"
go version
node --version
go test -race -count=1 ./art ./tools/artstudio/host ./tools/artstudio/release
go vet ./art ./tools/artstudio/host ./tools/artstudio/release
node --test tools/artstudio/release/tests/*.test.cjs
(cd tools/gendocs && CGO_ENABLED=0 go test -tags aego_nonative -count=1 ./...)
- name: Build one snapshot and integrate real gendocs
shell: bash
run: |
set -euo pipefail
out="$RUNNER_TEMP/aego-artstudio-stage"
site="$RUNNER_TEMP/aego-artstudio-docs"
test ! -e "$out"
test ! -e "$site"
go run ./tools/artstudio/release build -id github-stage -out "$out" \
-app-origin http://127.0.0.1:8097 -docs-origin http://127.0.0.1:8098 > "$RUNNER_TEMP/aego-artstudio-build.json"
go run ./tools/artstudio/release verify -dir "$out"
go run ./tools/artstudio/release check-source -dir "$out" -root "$GITHUB_WORKSPACE"
CGO_ENABLED=0 ARTSTUDIO_ARTIFACT="$out" go run -tags aego_nonative ./cmd/aego docs build \
--out "$site" --engine "$GITHUB_WORKSPACE" --playground=false
test -f "$site/asset-studio/ru/first-sprite/index.html"
test -f "$site/asset-studio/en/first-sprite/index.html"
test ! -e "$site/studio/artstudio.wasm"
gitea-result:
if: ${{ always() && github.server_url == 'https://github.com' && github.repository == 'Alexander-D-Karpov/aego' && github.ref == 'refs/heads/master' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
needs: native
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions:
contents: read
actions: read
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- name: Report actual native results to Gitea
env:
GITEA_STATUS_TOKEN: ${{ secrets.GITEA_STATUS_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: python3 tools/ci/gitea_status.py finished