[Feature] Support for shared Minecraft folders (God Folders), Minecra… #328
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: CI Build, Channels, and Release Drafts | |
| on: | |
| push: | |
| branches: [main, release/**] | |
| pull_request: | |
| types: [opened, synchronize, reopened, edited] | |
| branches: [main, release/**] | |
| workflow_dispatch: | |
| inputs: | |
| channel: | |
| description: Release channel | |
| type: choice | |
| required: true | |
| default: nightly | |
| options: | |
| - nightly | |
| - pre-release | |
| - release | |
| version_prefix: | |
| description: Semver prefix for pre-release/release (for example 1.4.0) | |
| type: string | |
| required: false | |
| default: "" | |
| run_windows: | |
| description: Build Windows artifact | |
| type: boolean | |
| required: true | |
| default: true | |
| run_macos: | |
| description: Build macOS artifact | |
| type: boolean | |
| required: true | |
| default: true | |
| run_linux: | |
| description: Build Linux artifact | |
| type: boolean | |
| required: true | |
| default: true | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| ci-filter: | |
| name: Resolve CI Channel and Platform Filter | |
| runs-on: ubuntu-latest | |
| outputs: | |
| run_windows: ${{ steps.filter.outputs.run_windows }} | |
| run_macos: ${{ steps.filter.outputs.run_macos }} | |
| run_linux: ${{ steps.filter.outputs.run_linux }} | |
| release_channel: ${{ steps.filter.outputs.release_channel }} | |
| is_release_flow: ${{ steps.filter.outputs.is_release_flow }} | |
| release_is_prerelease: ${{ steps.filter.outputs.release_is_prerelease }} | |
| public_version: ${{ steps.filter.outputs.public_version }} | |
| package_version: ${{ steps.filter.outputs.package_version }} | |
| package_revision: ${{ steps.filter.outputs.package_revision }} | |
| release_tag: ${{ steps.filter.outputs.release_tag }} | |
| build_timestamp_utc: ${{ steps.filter.outputs.build_timestamp_utc }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Resolve commit/PR tags and build channel | |
| id: filter | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| event_name="${{ github.event_name }}" | |
| event_action="${{ github.event.action }}" | |
| resolve_flags() { | |
| local source_text="$1" | |
| local source_text_lc | |
| source_text_lc="$(printf '%s' "$source_text" | tr '[:upper:]' '[:lower:]')" | |
| local run_windows=true | |
| local run_macos=true | |
| local run_linux=true | |
| local has_ci_windows=false | |
| local has_ci_macos=false | |
| local has_ci_linux=false | |
| if [[ "$source_text_lc" == *"[ci-windows]"* ]]; then | |
| has_ci_windows=true | |
| fi | |
| if [[ "$source_text_lc" == *"[ci-macos]"* ]]; then | |
| has_ci_macos=true | |
| fi | |
| if [[ "$source_text_lc" == *"[ci-linux]"* ]]; then | |
| has_ci_linux=true | |
| fi | |
| if [[ "$source_text_lc" == *"[no-ci]"* ]]; then | |
| run_windows=false | |
| run_macos=false | |
| run_linux=false | |
| elif $has_ci_windows || $has_ci_macos || $has_ci_linux; then | |
| run_windows=$has_ci_windows | |
| run_macos=$has_ci_macos | |
| run_linux=$has_ci_linux | |
| fi | |
| printf '%s %s %s\n' "$run_windows" "$run_macos" "$run_linux" | |
| } | |
| resolve_channel() { | |
| local source_text="$1" | |
| local source_text_lc | |
| source_text_lc="$(printf '%s' "$source_text" | tr '[:upper:]' '[:lower:]')" | |
| local has_rel=false | |
| local has_pre=false | |
| local has_nightly=false | |
| if [[ "$source_text_lc" == *"[ci-rel]"* ]]; then | |
| has_rel=true | |
| fi | |
| if [[ "$source_text_lc" == *"[ci-pre]"* ]]; then | |
| has_pre=true | |
| fi | |
| if [[ "$source_text_lc" == *"[ci-nightly]"* ]]; then | |
| has_nightly=true | |
| fi | |
| local count=0 | |
| $has_rel && count=$((count + 1)) | |
| $has_pre && count=$((count + 1)) | |
| $has_nightly && count=$((count + 1)) | |
| if [ "$count" -gt 1 ]; then | |
| echo "Conflicting CI channel tags found in source text." | |
| exit 1 | |
| fi | |
| if $has_rel; then | |
| printf '%s\n' "release" | |
| elif $has_pre; then | |
| printf '%s\n' "pre-release" | |
| elif $has_nightly; then | |
| printf '%s\n' "nightly" | |
| else | |
| printf '%s\n' "nightly" | |
| fi | |
| } | |
| normalize_msix_component() { | |
| local raw_value="$1" | |
| local label="$2" | |
| if ! [[ "$raw_value" =~ ^[0-9]+$ ]]; then | |
| echo "$label must be numeric for MSIX package versions. Found: $raw_value" | |
| exit 1 | |
| fi | |
| local normalized_value=$((10#$raw_value)) | |
| if [ "$normalized_value" -gt 65535 ]; then | |
| echo "$label must be between 0 and 65535 for MSIX package versions. Found: $normalized_value" | |
| exit 1 | |
| fi | |
| printf '%s\n' "$normalized_value" | |
| } | |
| if [ "$event_name" = "workflow_dispatch" ]; then | |
| run_windows="$(jq -r '.inputs.run_windows // "true"' "$GITHUB_EVENT_PATH")" | |
| run_macos="$(jq -r '.inputs.run_macos // "true"' "$GITHUB_EVENT_PATH")" | |
| run_linux="$(jq -r '.inputs.run_linux // "true"' "$GITHUB_EVENT_PATH")" | |
| release_channel="$(jq -r '.inputs.channel // "nightly"' "$GITHUB_EVENT_PATH")" | |
| version_prefix_input="$(jq -r '.inputs.version_prefix // ""' "$GITHUB_EVENT_PATH")" | |
| source_used="workflow_dispatch.inputs" | |
| elif [ "$event_name" = "pull_request" ]; then | |
| pr_description="$(jq -r '.pull_request.body // ""' "$GITHUB_EVENT_PATH")" | |
| read -r run_windows run_macos run_linux <<< "$(resolve_flags "$pr_description")" | |
| release_channel="$(resolve_channel "$pr_description")" | |
| source_used="pull_request.body" | |
| version_prefix_input="" | |
| if [ "$event_action" = "synchronize" ]; then | |
| head_repo_api="$(jq -r '.pull_request.head.repo.url // ""' "$GITHUB_EVENT_PATH")" | |
| head_sha="$(jq -r '.pull_request.head.sha // ""' "$GITHUB_EVENT_PATH")" | |
| commit_text="" | |
| if [ -n "$head_repo_api" ] && [ -n "$head_sha" ]; then | |
| commit_payload="$(curl -fsSL \ | |
| -H 'Accept: application/vnd.github+json' \ | |
| -H 'Authorization: Bearer ${{ github.token }}' \ | |
| "$head_repo_api/commits/$head_sha" || true)" | |
| if [ -n "$commit_payload" ]; then | |
| commit_text="$(printf '%s' "$commit_payload" | jq -r '.commit.message // ""')" | |
| fi | |
| fi | |
| if [ -n "$commit_text" ]; then | |
| read -r run_windows run_macos run_linux <<< "$(resolve_flags "$commit_text")" | |
| release_channel="$(resolve_channel "$commit_text")" | |
| source_used="pull_request.head_commit.message" | |
| fi | |
| fi | |
| else | |
| push_message="$(jq -r '.head_commit.message // ""' "$GITHUB_EVENT_PATH")" | |
| read -r run_windows run_macos run_linux <<< "$(resolve_flags "$push_message")" | |
| release_channel="$(resolve_channel "$push_message")" | |
| source_used="head_commit.message" | |
| version_prefix_input="" | |
| fi | |
| if [ -z "$version_prefix_input" ]; then | |
| version_prefix_input="$(sed -n 's#.*<VersionPrefix>\(.*\)</VersionPrefix>.*#\1#p' Emerald/Emerald.csproj | head -n 1)" | |
| fi | |
| if [ -z "$version_prefix_input" ]; then | |
| version_prefix_input="0.1.0" | |
| fi | |
| if [[ "$release_channel" != "nightly" ]]; then | |
| run_windows=true | |
| run_macos=true | |
| run_linux=true | |
| fi | |
| if ! [[ "$version_prefix_input" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then | |
| echo "version_prefix must use semantic format MAJOR.MINOR.PATCH. Found: $version_prefix_input" | |
| exit 1 | |
| fi | |
| major="${BASH_REMATCH[1]}" | |
| minor="${BASH_REMATCH[2]}" | |
| patch="${BASH_REMATCH[3]}" | |
| short_sha="${GITHUB_SHA:0:7}" | |
| build_timestamp_utc="$(date -u +%Y-%m-%dT%H:%M:%SZ)" | |
| run_number="${GITHUB_RUN_NUMBER:-1}" | |
| run_attempt="${GITHUB_RUN_ATTEMPT:-1}" | |
| if [ "$release_channel" = "nightly" ]; then | |
| timestamp_slug="$(date -u +%Y%m%d.%H%M)" | |
| package_major="$(normalize_msix_component "$(date -u +%y)" "nightly package major")" | |
| package_minor="$(normalize_msix_component "$(date -u +%j)" "nightly package minor")" | |
| package_build="$(normalize_msix_component "$(date -u +%H%M)" "nightly package build")" | |
| package_revision="$(normalize_msix_component "$run_attempt" "nightly package revision")" | |
| public_version="nightly-${timestamp_slug}+sha.${short_sha}" | |
| package_version="${package_major}.${package_minor}.${package_build}.${package_revision}" | |
| release_tag="nightly-${timestamp_slug}+pkg.${package_version}" | |
| release_is_prerelease=true | |
| is_release_flow=false | |
| else | |
| package_major="$(normalize_msix_component "$major" "release package major")" | |
| package_minor="$(normalize_msix_component "$minor" "release package minor")" | |
| package_build="$(normalize_msix_component "$patch" "release package build")" | |
| package_revision="$(normalize_msix_component "$(( (run_number % 65534) + 1 ))" "release package revision")" | |
| package_version="${package_major}.${package_minor}.${package_build}.${package_revision}" | |
| if [ "$release_channel" = "pre-release" ]; then | |
| public_version="${version_prefix_input}-pre.${package_revision}" | |
| release_is_prerelease=true | |
| else | |
| public_version="${version_prefix_input}" | |
| release_is_prerelease=false | |
| fi | |
| release_tag="v${public_version}+pkg.${package_version}" | |
| is_release_flow=true | |
| fi | |
| echo "Resolved flags from $source_used:" | |
| echo " channel=$release_channel" | |
| echo " windows=$run_windows macos=$run_macos linux=$run_linux" | |
| echo " public_version=$public_version" | |
| echo " package_version=$package_version" | |
| echo " release_tag=$release_tag" | |
| { | |
| echo "run_windows=$run_windows" | |
| echo "run_macos=$run_macos" | |
| echo "run_linux=$run_linux" | |
| echo "release_channel=$release_channel" | |
| echo "is_release_flow=$is_release_flow" | |
| echo "release_is_prerelease=$release_is_prerelease" | |
| echo "public_version=$public_version" | |
| echo "package_version=$package_version" | |
| echo "package_revision=$package_revision" | |
| echo "release_tag=$release_tag" | |
| echo "build_timestamp_utc=$build_timestamp_utc" | |
| } >> "$GITHUB_OUTPUT" | |
| publish-windows: | |
| name: Windows Signed Bundle and MSIX | |
| needs: ci-filter | |
| if: ${{ needs.ci-filter.outputs.run_windows == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false) }} | |
| runs-on: windows-latest | |
| timeout-minutes: 35 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Dependencies | |
| uses: ./.github/steps/install_dependencies | |
| with: | |
| job-platform: windows | |
| - name: Materialize signing certificate | |
| shell: pwsh | |
| env: | |
| WINDOWS_SIGNING_CERT_BASE64: ${{ secrets.WINDOWS_SIGNING_CERT_BASE64 }} | |
| run: | | |
| if ([string]::IsNullOrWhiteSpace($env:WINDOWS_SIGNING_CERT_BASE64)) { | |
| throw "WINDOWS_SIGNING_CERT_BASE64 secret is missing." | |
| } | |
| $certPath = Join-Path $env:RUNNER_TEMP "emerald-signing.pfx" | |
| [IO.File]::WriteAllBytes($certPath, [Convert]::FromBase64String($env:WINDOWS_SIGNING_CERT_BASE64)) | |
| "EMERALD_SIGNING_CERT_PATH=$certPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| - name: Publish signed Windows packages | |
| shell: pwsh | |
| env: | |
| WINDOWS_SIGNING_CERT_PASSWORD: ${{ secrets.WINDOWS_SIGNING_CERT_PASSWORD }} | |
| run: | | |
| if ([string]::IsNullOrWhiteSpace($env:WINDOWS_SIGNING_CERT_PASSWORD)) { | |
| throw "WINDOWS_SIGNING_CERT_PASSWORD secret is missing." | |
| } | |
| & .\scripts\windows\publish-windows-msix.ps1 ` | |
| -ProjectPath ".\Emerald\Emerald.csproj" ` | |
| -OutputRoot (Join-Path $env:GITHUB_WORKSPACE "artifacts\windows") ` | |
| -Version "${{ needs.ci-filter.outputs.package_version }}" ` | |
| -FileVersion "${{ needs.ci-filter.outputs.package_version }}" ` | |
| -AssemblyVersion "${{ needs.ci-filter.outputs.package_version }}" ` | |
| -InformationalVersion "${{ needs.ci-filter.outputs.public_version }}" ` | |
| -UpdateChannel "${{ needs.ci-filter.outputs.release_channel }}" ` | |
| -PublicVersion "${{ needs.ci-filter.outputs.public_version }}" ` | |
| -ReleaseTag "${{ needs.ci-filter.outputs.release_tag }}" ` | |
| -CommitSha "${{ github.sha }}" ` | |
| -BuildTimestampUtc "${{ needs.ci-filter.outputs.build_timestamp_utc }}" ` | |
| -SkipBundleVerify ` | |
| -SkipBundleArchive ` | |
| -CertificatePath $env:EMERALD_SIGNING_CERT_PATH | |
| - name: Upload CI Windows x64 MSIX artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Emerald-Windows-MSIX-x64 | |
| path: ${{ github.workspace }}/artifacts/windows/final/*_x64.msix | |
| if-no-files-found: error | |
| retention-days: 14 | |
| - name: Upload CI Windows arm64 MSIX artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Emerald-Windows-MSIX-arm64 | |
| path: ${{ github.workspace }}/artifacts/windows/final/*_arm64.msix | |
| if-no-files-found: error | |
| retention-days: 14 | |
| - name: Upload CI Windows signing certificate artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Emerald-Windows-Signing-Certificate | |
| path: ${{ github.workspace }}/artifacts/windows/final/*.cer | |
| if-no-files-found: error | |
| retention-days: 14 | |
| - name: Upload release Windows package transfer artifact | |
| if: ${{ needs.ci-filter.outputs.is_release_flow == 'true' }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Emerald-Windows-ReleaseDraft-Assets | |
| path: ${{ github.workspace }}/artifacts/windows/final/* | |
| if-no-files-found: error | |
| retention-days: 14 | |
| - name: Cleanup signing certificate | |
| if: always() | |
| shell: pwsh | |
| run: | | |
| if ($env:EMERALD_SIGNING_CERT_PATH -and (Test-Path -LiteralPath $env:EMERALD_SIGNING_CERT_PATH)) { | |
| Remove-Item -LiteralPath $env:EMERALD_SIGNING_CERT_PATH -Force | |
| } | |
| publish-macos: | |
| name: macOS .app (arm64) | |
| needs: ci-filter | |
| if: ${{ needs.ci-filter.outputs.run_macos == 'true' }} | |
| runs-on: macos-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Dependencies | |
| uses: ./.github/steps/install_dependencies | |
| with: | |
| job-platform: macos | |
| - name: Publish macOS app | |
| shell: bash | |
| run: | | |
| OUTPUT_DIR="$GITHUB_WORKSPACE/artifacts/macos/Emerald-macOS-arm64" | |
| mkdir -p "$OUTPUT_DIR" | |
| dotnet publish ./Emerald/Emerald.csproj \ | |
| -c Release \ | |
| -f net10.0-desktop \ | |
| -r osx-arm64 \ | |
| -p:SelfContained=true \ | |
| -p:PackageFormat=app \ | |
| -p:PublishTrimmed=false \ | |
| -p:PublishSingleFile=false \ | |
| -p:Version="${{ needs.ci-filter.outputs.package_version }}" \ | |
| -p:FileVersion="${{ needs.ci-filter.outputs.package_version }}" \ | |
| -p:AssemblyVersion="${{ needs.ci-filter.outputs.package_version }}" \ | |
| -p:InformationalVersion="${{ needs.ci-filter.outputs.public_version }}" \ | |
| -p:EmeraldPackageVersion="${{ needs.ci-filter.outputs.package_version }}" \ | |
| -p:EmeraldPublicVersion="${{ needs.ci-filter.outputs.public_version }}" \ | |
| -p:EmeraldUpdateChannel="${{ needs.ci-filter.outputs.release_channel }}" \ | |
| -p:EmeraldReleaseTag="${{ needs.ci-filter.outputs.release_tag }}" \ | |
| -p:EmeraldCommitSha="${{ github.sha }}" \ | |
| -p:EmeraldBuildTimestampUtc="${{ needs.ci-filter.outputs.build_timestamp_utc }}" \ | |
| -o "$OUTPUT_DIR" | |
| - name: Zip macOS .app (preserve app bundle metadata) | |
| shell: bash | |
| run: | | |
| OUTPUT_DIR="$GITHUB_WORKSPACE/artifacts/macos/Emerald-macOS-arm64" | |
| APP_PATH="$(find "$OUTPUT_DIR" -maxdepth 2 -type d -name '*.app' | head -n 1)" | |
| if [ -z "$APP_PATH" ]; then | |
| echo "No .app bundle found in $OUTPUT_DIR" | |
| exit 1 | |
| fi | |
| ZIP_PATH="$GITHUB_WORKSPACE/Emerald-macOS-arm64-app.zip" | |
| ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$ZIP_PATH" | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Emerald-macOS-arm64-app | |
| path: ${{ github.workspace }}/Emerald-macOS-arm64-app.zip | |
| retention-days: 14 | |
| # Snap packages are built natively on each architecture — Uno Platform does not | |
| # support cross-compilation for snap targets as of the current SDK version. | |
| publish-linux: | |
| name: Linux Snap (${{ matrix.arch }}) | |
| needs: ci-filter | |
| if: ${{ needs.ci-filter.outputs.run_linux == 'true' }} | |
| runs-on: ${{ matrix.runner }} | |
| timeout-minutes: 60 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - arch: x64 | |
| runner: ubuntu-22.04 | |
| runtime: linux-x64 | |
| - arch: arm64 | |
| runner: ubuntu-22.04-arm | |
| runtime: linux-arm64 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Dependencies | |
| uses: ./.github/steps/install_dependencies | |
| with: | |
| job-platform: linux | |
| # Snapcraft is installed after the base dependencies so that the snap daemon | |
| # is ready before we invoke dotnet publish with PackageFormat=snap. | |
| # core22 matches the Ubuntu 22.04 runner base used by both matrix legs. | |
| # --destructive-mode is required in CI because LXD/Multipass are unavailable | |
| # on single-use GitHub-hosted runners; it is safe here because the environment | |
| # is ephemeral and discarded after the job completes. | |
| - name: Install Snapcraft and Multipass | |
| shell: bash | |
| run: | | |
| sudo apt-get update -y | |
| sudo apt-get install -y snapd | |
| sudo snap install core22 | |
| sudo snap install snapcraft --classic | |
| sudo snap install multipass | |
| - name: Publish Linux Snap (${{ matrix.arch }}) | |
| shell: bash | |
| env: | |
| # Modern Snapcraft equivalent to --destructive-mode | |
| SNAPCRAFT_BUILD_ENVIRONMENT: host | |
| run: | | |
| dotnet publish ./Emerald/Emerald.csproj \ | |
| -c Release \ | |
| -f net10.0-desktop \ | |
| -r "${{ matrix.runtime }}" \ | |
| -p:SelfContained=true \ | |
| -p:PackageFormat=snap \ | |
| -p:UnoSnapBuildProvider=none \ | |
| -p:UnoSnapcraftAdditionalParameters=--destructive-mode \ | |
| -p:PublishTrimmed=false \ | |
| -p:PublishSingleFile=false \ | |
| -p:Version="${{ needs.ci-filter.outputs.package_version }}" \ | |
| -p:FileVersion="${{ needs.ci-filter.outputs.package_version }}" \ | |
| -p:AssemblyVersion="${{ needs.ci-filter.outputs.package_version }}" \ | |
| -p:InformationalVersion="${{ needs.ci-filter.outputs.public_version }}" \ | |
| -p:EmeraldPackageVersion="${{ needs.ci-filter.outputs.package_version }}" \ | |
| -p:EmeraldPublicVersion="${{ needs.ci-filter.outputs.public_version }}" \ | |
| -p:EmeraldUpdateChannel="${{ needs.ci-filter.outputs.release_channel }}" \ | |
| -p:EmeraldReleaseTag="${{ needs.ci-filter.outputs.release_tag }}" \ | |
| -p:EmeraldCommitSha="${{ github.sha }}" \ | |
| -p:EmeraldBuildTimestampUtc="${{ needs.ci-filter.outputs.build_timestamp_utc }}" | |
| - name: Locate and stage snap artifact | |
| id: locate | |
| shell: bash | |
| run: | | |
| # Uno places the .snap in the publish output folder; find it regardless | |
| # of the exact versioned filename that snapcraft generates. | |
| SNAP_FILE="$(find . -name '*.snap' -not -path '*/.git/*' -type f | head -n 1)" | |
| if [ -z "$SNAP_FILE" ]; then | |
| echo "No .snap file found after publish" | |
| exit 1 | |
| fi | |
| echo "Found snap: $SNAP_FILE" | |
| STAGED="$GITHUB_WORKSPACE/Emerald-linux-${{ matrix.arch }}.snap" | |
| cp "$SNAP_FILE" "$STAGED" | |
| echo "snap_path=$STAGED" >> "$GITHUB_OUTPUT" | |
| - name: Upload CI Linux Snap artifact (${{ matrix.arch }}) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Emerald-linux-${{ matrix.arch }}-snap | |
| path: ${{ steps.locate.outputs.snap_path }} | |
| if-no-files-found: error | |
| retention-days: 14 | |
| - name: Upload release Linux Snap transfer artifact (${{ matrix.arch }}) | |
| if: ${{ needs.ci-filter.outputs.is_release_flow == 'true' }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Emerald-linux-${{ matrix.arch }}-ReleaseDraft-Snap | |
| path: ${{ steps.locate.outputs.snap_path }} | |
| if-no-files-found: error | |
| retention-days: 14 | |
| draft-release: | |
| name: Draft GitHub Release | |
| needs: [ci-filter, publish-windows, publish-macos, publish-linux] | |
| if: >- | |
| ${{ | |
| always() && | |
| needs.ci-filter.outputs.is_release_flow == 'true' && | |
| needs.publish-windows.result == 'success' && | |
| needs.publish-macos.result == 'success' && | |
| needs.publish-linux.result == 'success' && | |
| (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false) | |
| }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Download Windows artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: Emerald-Windows-ReleaseDraft-Assets | |
| path: release-assets/windows | |
| - name: Download macOS artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: Emerald-macOS-arm64-app | |
| path: release-assets/macos | |
| - name: Download Linux x64 Snap artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: Emerald-linux-x64-ReleaseDraft-Snap | |
| path: release-assets/linux | |
| - name: Download Linux arm64 Snap artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: Emerald-linux-arm64-ReleaseDraft-Snap | |
| path: release-assets/linux | |
| - name: Build release metadata files | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p release-assets/metadata | |
| mkdir -p release-assets/windows | |
| cat > release-assets/metadata/channel-info.json <<EOF | |
| { | |
| "channel": "${{ needs.ci-filter.outputs.release_channel }}", | |
| "publicVersion": "${{ needs.ci-filter.outputs.public_version }}", | |
| "packageVersion": "${{ needs.ci-filter.outputs.package_version }}", | |
| "tag": "${{ needs.ci-filter.outputs.release_tag }}", | |
| "commit": "${{ github.sha }}", | |
| "buildTimestampUtc": "${{ needs.ci-filter.outputs.build_timestamp_utc }}" | |
| } | |
| EOF | |
| if [ "${{ needs.ci-filter.outputs.release_channel }}" = "release" ]; then | |
| printf '%s\n' \ | |
| '<?xml version="1.0" encoding="utf-8"?>' \ | |
| '<AppInstaller xmlns="http://schemas.microsoft.com/appx/appinstaller/2018" Version="${{ needs.ci-filter.outputs.package_version }}" Uri="https://github.com/RiversideValley/Emerald/releases/latest/download/Emerald-Release.appinstaller">' \ | |
| ' <MainBundle Name="Riverside.Emerald" Publisher="CN=Riverside Valley" Version="${{ needs.ci-filter.outputs.package_version }}" Uri="https://github.com/RiversideValley/Emerald/releases/latest/download/Emerald-Windows-Signed-x64-arm64.appxbundle" />' \ | |
| ' <UpdateSettings>' \ | |
| ' <OnLaunch HoursBetweenUpdateChecks="0" />' \ | |
| ' <AutomaticBackgroundTask />' \ | |
| ' </UpdateSettings>' \ | |
| '</AppInstaller>' \ | |
| > release-assets/windows/Emerald-Release.appinstaller | |
| fi | |
| - name: Collect release file list | |
| id: files | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| { | |
| echo "files<<EOF" | |
| find release-assets/windows -maxdepth 1 -type f | sort | |
| find release-assets/macos -maxdepth 1 -type f | sort | |
| find release-assets/linux -maxdepth 1 -type f | sort | |
| find release-assets/metadata -maxdepth 1 -type f | sort | |
| echo "EOF" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Create draft release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ needs.ci-filter.outputs.release_tag }} | |
| name: Emerald ${{ needs.ci-filter.outputs.public_version }} | |
| target_commitish: ${{ github.sha }} | |
| draft: true | |
| prerelease: ${{ needs.ci-filter.outputs.release_is_prerelease == 'true' }} | |
| make_latest: ${{ needs.ci-filter.outputs.release_channel == 'release' }} | |
| generate_release_notes: true | |
| files: ${{ steps.files.outputs.files }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |