Repository navigation
chore(deps): update dependency dotnet-sdk to v10 #213
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: Build and package SyntaxLauncher | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ["v*"] | |
| pull_request: | |
| workflow_dispatch: | |
| inputs: | |
| preview_channel: | |
| description: Preview channel to publish from main | |
| type: choice | |
| options: [snapshot, dev] | |
| default: snapshot | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: syntaxlauncher-ci-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} | |
| jobs: | |
| verify: | |
| name: Verify core and desktop compilation | |
| runs-on: ubuntu-26.04 | |
| timeout-minutes: 35 | |
| outputs: | |
| launcher_version: ${{ steps.release.outputs.launcher_version }} | |
| publish_release: ${{ steps.release.outputs.publish_release }} | |
| preview_channel: ${{ steps.channel.outputs.preview_channel }} | |
| build_channel: ${{ steps.channel.outputs.build_channel }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-java@v6 | |
| with: | |
| distribution: temurin | |
| java-version: "25" | |
| - uses: gradle/actions/setup-gradle@v6 | |
| with: | |
| gradle-version: "9.8.1" | |
| - name: Verify canonical product version and release tag | |
| run: python3 scripts/launcher_version.py --github-ref "$GITHUB_REF" | |
| - name: Detect eligible stable version increment | |
| id: release | |
| shell: bash | |
| env: | |
| BEFORE_SHA: ${{ github.event.before }} | |
| GH_TOKEN: ${{ github.token }} | |
| GH_REPO: ${{ github.repository }} | |
| run: | | |
| set -euo pipefail | |
| args=() | |
| if [[ "$GITHUB_EVENT_NAME" == push && "$GITHUB_REF" == refs/heads/main ]]; then | |
| args+=(--before "$BEFORE_SHA") | |
| fi | |
| python3 scripts/auto_release.py "${args[@]}" --github-output "$GITHUB_OUTPUT" | |
| # Never backfill a failed historical version from a newer main commit: | |
| # the code may already belong to the next milestone. Recover the | |
| # historical commit with the pinned recovery workflow instead. | |
| if [[ "$GITHUB_REF" == refs/heads/main && "$GITHUB_EVENT_NAME" == push ]]; then | |
| version="$(python3 scripts/launcher_version.py)" | |
| if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && ! gh release view "v$version" >/dev/null 2>&1; then | |
| echo "::warning::Stable v$version is missing. Only a version-increment commit can publish automatically. For earlier versions, use a release recovery pinned to the original verified commit." | |
| fi | |
| fi | |
| - name: Select publication channel | |
| id: channel | |
| shell: bash | |
| env: | |
| STABLE_RELEASE: ${{ steps.release.outputs.publish_release }} | |
| REQUESTED_PREVIEW: ${{ inputs.preview_channel }} | |
| run: | | |
| set -euo pipefail | |
| preview_channel="" | |
| build_channel=stable | |
| if [[ "$GITHUB_REF" == refs/heads/main && "$GITHUB_EVENT_NAME" == push ]]; then | |
| preview_channel=dev | |
| if [[ "$STABLE_RELEASE" != true ]]; then build_channel=dev; fi | |
| elif [[ "$GITHUB_REF" == refs/heads/main && "$GITHUB_EVENT_NAME" == workflow_dispatch ]]; then | |
| preview_channel="$REQUESTED_PREVIEW" | |
| [[ "$preview_channel" == snapshot || "$preview_channel" == dev ]] | |
| build_channel="$preview_channel" | |
| fi | |
| echo "preview_channel=$preview_channel" >> "$GITHUB_OUTPUT" | |
| echo "build_channel=$build_channel" >> "$GITHUB_OUTPUT" | |
| - name: Validate packaging shell scripts before building | |
| run: | | |
| bash -n packaging/smoke-linux.sh | |
| bash -n packaging/smoke-macos.sh | |
| - name: Compile and run tests | |
| run: gradle --no-daemon --stacktrace "-PlauncherBuildNumber=$GITHUB_RUN_NUMBER" "-PlauncherCommit=$GITHUB_SHA" "-PlauncherUpdateChannel=${{ steps.channel.outputs.build_channel }}" test build | |
| - name: Verify official NeoForge installer processors | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| timeout-minutes: 22 | |
| env: | |
| SYNTAXLAUNCHER_NEOFORGE_LIVE_SMOKE: "1" | |
| run: gradle --no-daemon --stacktrace :launcher-core:test --tests 'pl.syntaxdevteam.syntaxlauncher.core.loader.NeoForgeOfficialSmokeTest' --rerun-tasks | |
| - name: Smoke-test official Forge V2 processor installation | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| timeout-minutes: 22 | |
| env: | |
| SYNTAXLAUNCHER_FORGE_LIVE_SMOKE: "1" | |
| run: gradle --no-daemon --stacktrace :launcher-core:test --tests 'pl.syntaxdevteam.syntaxlauncher.core.loader.ForgeOfficialSmokeTest' --rerun-tasks | |
| - name: Test update packaging protocol | |
| run: python3 -m unittest discover -s scripts -p "test_*.py" | |
| - name: Test Build Explorer publisher | |
| run: python3 -m unittest discover -s tests -p 'test_*.py' | |
| - name: Summarize remaining release-readiness gates | |
| shell: bash | |
| run: python3 scripts/release_readiness.py --format markdown >> "$GITHUB_STEP_SUMMARY" | |
| - name: Enforce final acceptance before Stable 1.0 and later | |
| run: python3 scripts/release_readiness.py --enforce-production | |
| - name: Upload test evidence | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: syntaxlauncher-test-results | |
| path: | | |
| launcher-core/build/test-results/** | |
| launcher-core/build/reports/tests/** | |
| launcher-desktop/build/reports/** | |
| launcher-desktop/build/test-results/** | |
| if-no-files-found: ignore | |
| retention-days: 14 | |
| distributables: | |
| name: Application and installers (${{ matrix.os }}) | |
| needs: verify | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 50 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-24.04 | |
| artifact: linux-x64 | |
| - os: windows-2022 | |
| artifact: windows-x64 | |
| - os: macos-15 | |
| artifact: macos-arm64 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-java@v6 | |
| with: | |
| distribution: temurin | |
| java-version: "25" | |
| - uses: gradle/actions/setup-gradle@v6 | |
| with: | |
| gradle-version: "9.8.1" | |
| - uses: actions/setup-python@v7 | |
| with: | |
| python-version: "3.12" | |
| - name: Verify official managed Java on this platform | |
| shell: bash | |
| timeout-minutes: 15 | |
| env: | |
| SYNTAXLAUNCHER_JAVA_LIVE_SMOKE: "1" | |
| run: gradle --no-daemon --stacktrace :launcher-core:test --tests '*ManagedJavaOfficialSmokeTest' --rerun-tasks | |
| - name: Upload managed Java acceptance | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: managed-java-${{ matrix.artifact }} | |
| path: launcher-core/build/test-results/test | |
| if-no-files-found: warn | |
| - name: Build runnable native app directory | |
| shell: bash | |
| run: | | |
| version="$(python3 scripts/launcher_version.py --github-ref "$GITHUB_REF")" | |
| gradle --no-daemon --stacktrace "-PlauncherBuildNumber=$GITHUB_RUN_NUMBER" "-PlauncherCommit=$GITHUB_SHA" "-PlauncherUpdateChannel=${{ needs.verify.outputs.build_channel }}" :launcher-desktop:createDistributable | |
| python scripts/package_update.py --source launcher-desktop/build/compose/binaries/main/app --platform "${{ matrix.artifact }}" --version "$version" --output "launcher-desktop/build/updates/syntaxlauncher-update-${{ matrix.artifact }}.zip" | |
| gradle --no-daemon --stacktrace "-PlauncherBuildNumber=$GITHUB_RUN_NUMBER" "-PlauncherCommit=$GITHUB_SHA" "-PlauncherUpdateChannel=${{ needs.verify.outputs.build_channel }}" "-PupdateBundle=build/updates/syntaxlauncher-update-${{ matrix.artifact }}.zip" :launcher-desktop:verifyUpdateBundle | |
| - name: Verify portable Windows executable branding | |
| if: runner.os == 'Windows' | |
| shell: bash | |
| run: python scripts/verify_windows_icon.py --exe launcher-desktop/build/compose/binaries/main/app/SyntaxLauncher/SyntaxLauncher.exe | |
| - name: Verify Mojang HTTPS with the packaged runtime | |
| shell: bash | |
| run: | | |
| image=launcher-desktop/build/compose/binaries/main/app/SyntaxLauncher | |
| if [[ "$RUNNER_OS" == macOS ]]; then image="$image.app"; fi | |
| python scripts/verify_native_network.py --image "$image" --platform "${{ matrix.artifact }}" | |
| - name: Install Linux packaging tools | |
| if: runner.os == 'Linux' | |
| run: sudo apt-get update && sudo apt-get install -y rpm fakeroot desktop-file-utils xvfb appstream | |
| - uses: actions/setup-dotnet@v5 | |
| if: runner.os == 'Windows' | |
| with: | |
| dotnet-version: '10.0.x' | |
| - name: Install pinned WiX v7 | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| dotnet tool install --tool-path "$env:RUNNER_TEMP/wix7" wix --version 7.0.0 | |
| if ($LASTEXITCODE -ne 0) { throw 'WiX v7 installation failed' } | |
| "$env:RUNNER_TEMP/wix7" | Out-File -FilePath $env:GITHUB_PATH -Append | |
| # Maintainer explicitly accepted the WiX v7 OSMF EULA and confirmed eligibility on 2026-10-23. | |
| & "$env:RUNNER_TEMP/wix7/wix.exe" eula accept wix7 | |
| if ($LASTEXITCODE -ne 0) { throw 'WiX v7 EULA acceptance failed' } | |
| & "$env:RUNNER_TEMP/wix7/wix.exe" extension add --global WixToolset.UI.wixext/7.0.0 | |
| if ($LASTEXITCODE -ne 0) { throw 'WiX v7 UI extension installation failed' } | |
| - name: Build native installers from the verified application image | |
| shell: bash | |
| run: | | |
| image=launcher-desktop/build/compose/binaries/main/app/SyntaxLauncher | |
| if [[ "$RUNNER_OS" == macOS ]]; then image="$image.app"; fi | |
| python scripts/package_installers.py --image "$image" --platform "${{ matrix.artifact }}" --output launcher-desktop/build/installers | |
| - name: Test Debian, Fedora RPM and AppImage lifecycle | |
| if: runner.os == 'Linux' | |
| run: bash packaging/smoke-linux.sh | |
| - name: Test WiX v7 install, payload, repair and uninstall | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: ./packaging/smoke-windows.ps1 | |
| - name: Test DMG mount and application copy | |
| if: runner.os == 'macOS' | |
| run: bash packaging/smoke-macos.sh | |
| - name: Upload tested installers | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: native-installers-${{ matrix.artifact }}-${{ github.sha }} | |
| path: launcher-desktop/build/installers/* | |
| if-no-files-found: error | |
| retention-days: 14 | |
| - name: Upload installer evidence | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: native-installer-evidence-${{ matrix.artifact }}-${{ github.sha }} | |
| path: launcher-desktop/build/installer-evidence/ | |
| if-no-files-found: ignore | |
| retention-days: 14 | |
| - name: Show jpackage diagnostics on failure | |
| if: failure() | |
| shell: bash | |
| run: | | |
| if [ -d launcher-desktop/build/compose/logs ]; then | |
| find launcher-desktop/build/compose/logs -type f -name "*.txt" -print -exec tail -n 100 {} \; | |
| else | |
| echo "No Compose packaging logs found" | |
| fi | |
| - name: Upload jpackage diagnostic logs | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: syntaxlauncher-packaging-logs-${{ matrix.artifact }}-${{ github.sha }} | |
| path: launcher-desktop/build/compose/logs/ | |
| if-no-files-found: warn | |
| retention-days: 14 | |
| - name: Archive portable application preserving POSIX permissions | |
| shell: bash | |
| run: | | |
| test -d launcher-desktop/build/compose/binaries/main/app | |
| tar -czf syntaxlauncher-${{ matrix.artifact }}.tar.gz -C launcher-desktop/build/compose/binaries/main/app . | |
| - name: Upload portable app | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: syntaxlauncher-${{ matrix.artifact }}-${{ github.sha }} | |
| path: syntaxlauncher-${{ matrix.artifact }}.tar.gz | |
| if-no-files-found: error | |
| retention-days: 14 | |
| - name: Upload verified update bundle | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: syntaxlauncher-update-${{ matrix.artifact }} | |
| path: launcher-desktop/build/updates/*.zip | |
| if-no-files-found: error | |
| retention-days: 14 | |
| publish-release: | |
| name: Publish complete verified stable version | |
| if: (startsWith(github.ref, 'refs/tags/v') && !contains(github.ref_name, '-')) || needs.verify.outputs.publish_release == 'true' | |
| needs: [verify, distributables] | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: syntaxlauncher-update-* | |
| path: release-assets | |
| merge-multiple: true | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: syntaxlauncher-*-${{ github.sha }} | |
| path: release-assets | |
| merge-multiple: true | |
| - uses: actions/checkout@v7 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: native-installers-*-${{ github.sha }} | |
| path: release-assets | |
| merge-multiple: true | |
| - name: Verify complete installer set and write checksums | |
| run: python3 scripts/verify_installers.py --directory release-assets --write | |
| - name: Publish all platform updates together | |
| env: | |
| # A fine-grained PAT with repository Contents: write can be used | |
| # when the workflow GITHUB_TOKEN is denied by repository policy. | |
| GH_TOKEN: ${{ secrets.SYNTAXLAUNCHER_RELEASE_TOKEN || github.token }} | |
| GH_REPO: ${{ github.repository }} | |
| RELEASE_TAG: v${{ needs.verify.outputs.launcher_version }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| test -s release-assets/syntaxlauncher-update-linux-x64.zip | |
| test -s release-assets/syntaxlauncher-update-windows-x64.zip | |
| test -s release-assets/syntaxlauncher-update-macos-arm64.zip | |
| test -s release-assets/syntaxlauncher-linux-x64.tar.gz | |
| test -s release-assets/syntaxlauncher-windows-x64.tar.gz | |
| test -s release-assets/syntaxlauncher-macos-arm64.tar.gz | |
| # Refuse to publish this version from a commit different from its tag. | |
| if gh api "repos/$GH_REPO/git/ref/tags/$RELEASE_TAG" > existing-tag.json 2>/dev/null; then | |
| tag_type="$(python3 -c 'import json; print(json.load(open("existing-tag.json"))["object"]["type"])')" | |
| tag_sha="$(python3 -c 'import json; print(json.load(open("existing-tag.json"))["object"]["sha"])')" | |
| if [[ "$tag_type" == tag ]]; then | |
| tag_sha="$(gh api "repos/$GH_REPO/git/tags/$tag_sha" --jq '.object.sha')" | |
| elif [[ "$tag_type" != commit ]]; then | |
| echo "Unsupported git tag object type: $tag_type" >&2 | |
| exit 1 | |
| fi | |
| if [[ "$tag_sha" != "$GITHUB_SHA" ]]; then | |
| echo "Tag $RELEASE_TAG does not reference verified commit $GITHUB_SHA" >&2 | |
| exit 1 | |
| fi | |
| tag_exists=true | |
| else | |
| tag_exists=false | |
| if [[ "$GITHUB_REF" == refs/tags/v* ]]; then | |
| echo "Expected pushed tag $RELEASE_TAG is missing" >&2 | |
| exit 1 | |
| fi | |
| fi | |
| publish_release() { | |
| if ! gh release create "$@"; then | |
| echo "::error::Unable to create GitHub Release. If HTTP 403, authorize SYNTAXLAUNCHER_RELEASE_TOKEN for SyntaxDevTeam/SyntaxLauncher with Contents: Read and write and confirm organization approval. GITHUB_TOKEN may also be restricted by organization policy." | |
| exit 1 | |
| fi | |
| } | |
| if gh release view "$RELEASE_TAG" --json isDraft > existing-release.json 2>/dev/null; then | |
| python3 -c 'import json; assert json.load(open("existing-release.json"))["isDraft"], "Refusing to replace a published release"' | |
| elif [[ "$tag_exists" == true ]]; then | |
| publish_release "$RELEASE_TAG" --verify-tag --draft --generate-notes --notes "<!-- syntaxlauncher-build:$GITHUB_RUN_NUMBER.$GITHUB_RUN_ATTEMPT -->" --title "SyntaxLauncher $RELEASE_TAG" | |
| else | |
| # GITHUB_TOKEN-created tags do not invoke another workflow; publish from this verified run. | |
| publish_release "$RELEASE_TAG" --target "$GITHUB_SHA" --draft --generate-notes --notes "<!-- syntaxlauncher-build:$GITHUB_RUN_NUMBER.$GITHUB_RUN_ATTEMPT -->" --title "SyntaxLauncher $RELEASE_TAG" | |
| fi | |
| gh release upload "$RELEASE_TAG" release-assets/*.zip release-assets/*.tar.gz release-assets/*.msi release-assets/*.dmg release-assets/*.deb release-assets/*.rpm release-assets/*.AppImage release-assets/SHA256SUMS-installers.txt --clobber | |
| # Preview releases are published separately and never become latest stable. | |
| gh release edit "$RELEASE_TAG" --draft=false --latest | |
| publish-preview: | |
| name: Publish verified DEV or SNAPSHOT channel | |
| needs: [verify, distributables] | |
| if: needs.verify.outputs.preview_channel != '' | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: syntaxlauncher-update-* | |
| path: release-assets | |
| merge-multiple: true | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: syntaxlauncher-*-${{ github.sha }} | |
| path: release-assets | |
| merge-multiple: true | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: native-installers-*-${{ github.sha }} | |
| path: release-assets | |
| merge-multiple: true | |
| - name: Verify complete installer set and write checksums | |
| run: python3 scripts/verify_installers.py --directory release-assets --write | |
| - name: Publish complete applications and installers as an immutable preview | |
| env: | |
| GH_TOKEN: ${{ secrets.SYNTAXLAUNCHER_RELEASE_TOKEN || github.token }} | |
| GH_REPO: ${{ github.repository }} | |
| PREVIEW_CHANNEL: ${{ needs.verify.outputs.preview_channel }} | |
| run: >- | |
| python3 scripts/publish_preview.py --channel "$PREVIEW_CHANNEL" | |
| --run "$GITHUB_RUN_NUMBER" --attempt "$GITHUB_RUN_ATTEMPT" | |
| --commit "$GITHUB_SHA" --assets release-assets --installers | |
| publish-build-explorer: | |
| name: Publish all platforms to Build Explorer | |
| needs: [verify, distributables] | |
| if: github.event_name != 'pull_request' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 35 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: syntaxlauncher-*-${{ github.sha }} | |
| path: dist | |
| merge-multiple: true | |
| - name: Publish complete portable build set | |
| env: | |
| BUILD_EXPLORER_TOKEN: ${{ secrets.BUILD_EXPLORER_TOKEN }} | |
| run: python3 scripts/publish_build_explorer.py |