From 26426454bce323106d9b5b512ad5befdc8fac494 Mon Sep 17 00:00:00 2001 From: zortos293 <65777760+zortos293@users.noreply.github.com> Date: Tue, 11 Aug 2026 09:45:41 +0000 Subject: [PATCH 1/3] Add Blacksmith Switch build and release CI --- .github/workflows/switch-release.yml | 85 ++++++++++++++++++++++++++++ CMakeLists.txt | 2 +- README.md | 11 ++++ scripts/build-switch-msys2.sh | 1 + scripts/package-release.sh | 63 +++++++++++++++++++++ scripts/read-version.sh | 20 +++++++ 6 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/switch-release.yml create mode 100644 scripts/package-release.sh create mode 100644 scripts/read-version.sh diff --git a/.github/workflows/switch-release.yml b/.github/workflows/switch-release.yml new file mode 100644 index 0000000..72c0753 --- /dev/null +++ b/.github/workflows/switch-release.yml @@ -0,0 +1,85 @@ +name: Switch build and release + +on: + push: + branches: + - main + tags: + - "v*" + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: switch-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref_type != 'tag' }} + +jobs: + build: + name: Build Switch NRO + runs-on: blacksmith-4vcpu-ubuntu-2404 + container: devkitpro/devkita64:20260219 + outputs: + version: ${{ steps.version.outputs.version }} + steps: + - name: Check out source + uses: actions/checkout@v4 + + - name: Install generator dependencies + run: | + apt-get update -qq + apt-get install -y --no-install-recommends python3-jinja2 python3-jsonschema + + - name: Read and validate version + id: version + shell: bash + run: | + version="$(bash scripts/read-version.sh)" + if [[ "$GITHUB_REF_TYPE" == "tag" && "$GITHUB_REF_NAME" != "v$version" ]]; then + echo "Tag $GITHUB_REF_NAME does not match application version v$version." >&2 + exit 1 + fi + echo "version=$version" >> "$GITHUB_OUTPUT" + + - name: Build NRO + env: + OPENNOW_BUILD_JOBS: "4" + run: bash scripts/build-switch-msys2.sh + + - name: Package release files + run: bash scripts/package-release.sh "${{ steps.version.outputs.version }}" + + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: SwitchNOW-${{ steps.version.outputs.version }}-${{ github.sha }} + path: | + dist/SwitchNOW-${{ steps.version.outputs.version }}.nro + dist/SwitchNOW-${{ steps.version.outputs.version }}.zip + if-no-files-found: error + + release: + name: Publish GitHub release + if: github.ref_type == 'tag' + needs: build + runs-on: blacksmith-2vcpu-ubuntu-2404 + permissions: + contents: write + steps: + - name: Download build artifact + uses: actions/download-artifact@v4 + with: + name: SwitchNOW-${{ needs.build.outputs.version }}-${{ github.sha }} + path: dist + + - name: Publish release with generated notes + uses: softprops/action-gh-release@v2 + with: + name: OpenNOW Switch ${{ github.ref_name }} + generate_release_notes: true + fail_on_unmatched_files: true + files: | + dist/SwitchNOW-${{ needs.build.outputs.version }}.nro + dist/SwitchNOW-${{ needs.build.outputs.version }}.zip diff --git a/CMakeLists.txt b/CMakeLists.txt index 6548d8d..e0bc197 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,7 @@ pkg_check_modules(JANSSON REQUIRED IMPORTED_TARGET jansson) add_subdirectory(extern/borealis/library) add_subdirectory(extern/libpeer) -target_include_directories(borealis PUBLIC ${DEVKITPRO}/portlibs/switch/include) +target_include_directories(borealis SYSTEM AFTER PUBLIC ${DEVKITPRO}/portlibs/switch/include) file(GLOB_RECURSE APP_SOURCES CONFIGURE_DEPENDS app/src/*.cpp diff --git a/README.md b/README.md index fd1610e..4bb6088 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,17 @@ Create a release archive with: .\scripts\package-release.ps1 -Version 0.0.6 ``` +On Linux or in CI, use the equivalent shell entry point: + +```bash +bash scripts/package-release.sh 0.0.6 +``` + +Pushing a version tag such as `v0.0.6` runs the Blacksmith release workflow, +publishes both files to GitHub Releases, and generates notes from the changes +since the previous release. The tag must match the version in +`app/src/app_version.hpp` and `CMakeLists.txt`. + ## Repository layout ```text diff --git a/scripts/build-switch-msys2.sh b/scripts/build-switch-msys2.sh index 17ffe80..24e90f1 100644 --- a/scripts/build-switch-msys2.sh +++ b/scripts/build-switch-msys2.sh @@ -20,6 +20,7 @@ detect_build_jobs() { opennow_build_jobs="${OPENNOW_BUILD_JOBS:-$(detect_build_jobs)}" cmake -B build/switch -G Ninja +cmake --build build/switch --target cjson mbedtls srtp2 usrsctp -j"$opennow_build_jobs" cmake --build build/switch --target SwitchNOW.nro -j"$opennow_build_jobs" printf '\nBuilt: %s\n' "$(pwd)/build/switch/SwitchNOW.nro" diff --git a/scripts/package-release.sh b/scripts/package-release.sh new file mode 100644 index 0000000..37a6944 --- /dev/null +++ b/scripts/package-release.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ $# -lt 1 || $# -gt 2 ]]; then + printf 'Usage: %s [build-directory]\n' "$0" >&2 + exit 2 +fi + +version="$1" +build_directory="${2:-switch}" + +if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then + printf 'Invalid release version: %s\n' "$version" >&2 + exit 2 +fi + +repo="$(cd "$(dirname "$0")/.." && pwd)" +nro="$repo/build/$build_directory/SwitchNOW.nro" + +if [[ ! -f "$nro" ]]; then + printf 'Missing build artifact: %s. Run the Switch build first.\n' "$nro" >&2 + exit 1 +fi + +dist="$repo/dist" +package_name="SwitchNOW-$version" +package_root="$dist/$package_name" +switch_directory="$package_root/switch/SwitchNOW" +versioned_nro="$dist/$package_name.nro" +zip_path="$dist/$package_name.zip" + +rm -rf "$package_root" +rm -f "$versioned_nro" "$zip_path" +mkdir -p "$switch_directory" + +cp "$nro" "$switch_directory/SwitchNOW.nro" +cp "$nro" "$versioned_nro" +cp "$repo/resources/icon/icon.jpg" "$switch_directory/icon.jpg" +cp "$repo/resources/icon/icon.png" "$switch_directory/icon.png" +cp "$repo/README.md" "$package_root/README.md" + +cat > "$package_root/INSTALL.txt" <&2 + exit 1 +fi + +if [[ "$header_version" != "$cmake_version" ]]; then + printf 'Version mismatch: app_version.hpp has %s, CMakeLists.txt has %s.\n' \ + "$header_version" "$cmake_version" >&2 + exit 1 +fi + +printf '%s\n' "$header_version" From 1140ca4510ed5c2d09dd77c52fd49fd9951dd6b0 Mon Sep 17 00:00:00 2001 From: zortos293 <65777760+zortos293@users.noreply.github.com> Date: Tue, 11 Aug 2026 10:44:57 +0000 Subject: [PATCH 2/3] Automate release version increments --- .github/workflows/switch-release.yml | 68 +++++++++++++++++++--------- CMakeLists.txt | 14 +++++- README.md | 8 ++-- app/src/app_version.hpp | 6 ++- scripts/build-switch-msys2.sh | 3 +- scripts/next-release-version.sh | 18 ++++++++ scripts/read-version.sh | 4 +- 7 files changed, 89 insertions(+), 32 deletions(-) create mode 100644 scripts/next-release-version.sh diff --git a/.github/workflows/switch-release.yml b/.github/workflows/switch-release.yml index 72c0753..02bc3cb 100644 --- a/.github/workflows/switch-release.yml +++ b/.github/workflows/switch-release.yml @@ -4,8 +4,6 @@ on: push: branches: - main - tags: - - "v*" pull_request: workflow_dispatch: @@ -14,15 +12,47 @@ permissions: concurrency: group: switch-${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.ref_type != 'tag' }} + cancel-in-progress: true jobs: + version: + name: Resolve next release version + runs-on: blacksmith-2vcpu-ubuntu-2404 + outputs: + version: ${{ steps.release.outputs.version }} + steps: + - name: Check out source + uses: actions/checkout@v4 + + - name: Increment latest GitHub release + id: release + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + existing_tag="$( + gh api --paginate "repos/$GITHUB_REPOSITORY/releases?per_page=100" \ + --jq ".[] | select(.draft == false and .prerelease == false and .target_commitish == \"$GITHUB_SHA\") | .tag_name" \ + | head -n 1 + )" + + if [[ "$existing_tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + version="${existing_tag#v}" + else + latest_tag="$(gh api "repos/$GITHUB_REPOSITORY/releases/latest" --jq .tag_name 2>/dev/null || printf 'v0.0.0')" + version="$(bash scripts/next-release-version.sh "$latest_tag")" + fi + + echo "version=$version" >> "$GITHUB_OUTPUT" + echo "Building OpenNOW Switch v$version" + build: name: Build Switch NRO + needs: version runs-on: blacksmith-4vcpu-ubuntu-2404 container: devkitpro/devkita64:20260219 outputs: - version: ${{ steps.version.outputs.version }} + version: ${{ needs.version.outputs.version }} steps: - name: Check out source uses: actions/checkout@v4 @@ -32,38 +62,30 @@ jobs: apt-get update -qq apt-get install -y --no-install-recommends python3-jinja2 python3-jsonschema - - name: Read and validate version - id: version - shell: bash - run: | - version="$(bash scripts/read-version.sh)" - if [[ "$GITHUB_REF_TYPE" == "tag" && "$GITHUB_REF_NAME" != "v$version" ]]; then - echo "Tag $GITHUB_REF_NAME does not match application version v$version." >&2 - exit 1 - fi - echo "version=$version" >> "$GITHUB_OUTPUT" - - name: Build NRO env: OPENNOW_BUILD_JOBS: "4" + OPENNOW_VERSION: ${{ needs.version.outputs.version }} run: bash scripts/build-switch-msys2.sh - name: Package release files - run: bash scripts/package-release.sh "${{ steps.version.outputs.version }}" + run: bash scripts/package-release.sh "${{ needs.version.outputs.version }}" - name: Upload build artifact uses: actions/upload-artifact@v4 with: - name: SwitchNOW-${{ steps.version.outputs.version }}-${{ github.sha }} + name: SwitchNOW-${{ needs.version.outputs.version }}-${{ github.sha }} path: | - dist/SwitchNOW-${{ steps.version.outputs.version }}.nro - dist/SwitchNOW-${{ steps.version.outputs.version }}.zip + dist/SwitchNOW-${{ needs.version.outputs.version }}.nro + dist/SwitchNOW-${{ needs.version.outputs.version }}.zip if-no-files-found: error release: name: Publish GitHub release - if: github.ref_type == 'tag' - needs: build + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + needs: + - version + - build runs-on: blacksmith-2vcpu-ubuntu-2404 permissions: contents: write @@ -77,7 +99,9 @@ jobs: - name: Publish release with generated notes uses: softprops/action-gh-release@v2 with: - name: OpenNOW Switch ${{ github.ref_name }} + tag_name: v${{ needs.version.outputs.version }} + name: OpenNOW Switch v${{ needs.version.outputs.version }} + target_commitish: ${{ github.sha }} generate_release_notes: true fail_on_unmatched_files: true files: | diff --git a/CMakeLists.txt b/CMakeLists.txt index e0bc197..6822fe4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,11 @@ set(CMAKE_TOOLCHAIN_FILE ${DEVKITPRO}/cmake/Switch.cmake CACHE FILEPATH "devkitP project(SwitchNOW LANGUAGES C CXX) +set(OPENNOW_VERSION "0.0.6" CACHE STRING "OpenNOW application version") +if (NOT OPENNOW_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+$") + message(FATAL_ERROR "OPENNOW_VERSION must use major.minor.patch format") +endif () + set(PLATFORM_SWITCH ON) # One Deko3D application supports both NVDEC zero-copy and software-decoded # YUV uploads. Decoder selection is a runtime setting rather than a build type. @@ -67,7 +72,12 @@ target_link_directories(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/extern/ffmpeg/lib ) -target_compile_definitions(${PROJECT_NAME} PRIVATE PLATFORM_SWITCH __SWITCH__ HAS_SOCKLEN_T=1) +target_compile_definitions(${PROJECT_NAME} PRIVATE + PLATFORM_SWITCH + __SWITCH__ + HAS_SOCKLEN_T=1 + OPENNOW_APP_VERSION="${OPENNOW_VERSION}" +) if (PLATFORM_SWITCH) target_compile_definitions(${PROJECT_NAME} PRIVATE USE_DK_RENDERER BOREALIS_USE_DEKO3D OPENNOW_ENABLE_NVDEC) find_program(NX_UAM_EXE NAMES uam HINTS "${DEVKITPRO}/tools/bin") @@ -122,7 +132,7 @@ target_link_libraries(${PROJECT_NAME} ) set(PROJECT_AUTHOR "OpenCloudGaming") -set(PROJECT_VERSION_STRING "0.0.6") +set(PROJECT_VERSION_STRING "${OPENNOW_VERSION}") set(PROJECT_TITLEID "05004F4E4F575358") set(PROJECT_ICON ${CMAKE_CURRENT_SOURCE_DIR}/resources/icon/icon.jpg) set(PROJECT_ROMFS_DIR ${CMAKE_BINARY_DIR}/romfs) diff --git a/README.md b/README.md index 4bb6088..d389013 100644 --- a/README.md +++ b/README.md @@ -131,10 +131,10 @@ On Linux or in CI, use the equivalent shell entry point: bash scripts/package-release.sh 0.0.6 ``` -Pushing a version tag such as `v0.0.6` runs the Blacksmith release workflow, -publishes both files to GitHub Releases, and generates notes from the changes -since the previous release. The tag must match the version in -`app/src/app_version.hpp` and `CMakeLists.txt`. +After a change reaches `main`, the Blacksmith release workflow increments the +patch version from the latest GitHub release, embeds it in the app and NRO +metadata, publishes both files, and generates notes from the changes since the +previous release. Pull requests run the same build without publishing. ## Repository layout diff --git a/app/src/app_version.hpp b/app/src/app_version.hpp index 1f20bcd..effbf1d 100644 --- a/app/src/app_version.hpp +++ b/app/src/app_version.hpp @@ -1,8 +1,12 @@ #pragma once +#ifndef OPENNOW_APP_VERSION +#define OPENNOW_APP_VERSION "0.0.6" +#endif + namespace opennow { -inline constexpr const char* kAppVersion = "0.0.6"; +inline constexpr const char* kAppVersion = OPENNOW_APP_VERSION; } // namespace opennow diff --git a/scripts/build-switch-msys2.sh b/scripts/build-switch-msys2.sh index 24e90f1..f6b4e9c 100644 --- a/scripts/build-switch-msys2.sh +++ b/scripts/build-switch-msys2.sh @@ -18,8 +18,9 @@ detect_build_jobs() { } opennow_build_jobs="${OPENNOW_BUILD_JOBS:-$(detect_build_jobs)}" +opennow_version="${OPENNOW_VERSION:-$(bash scripts/read-version.sh)}" -cmake -B build/switch -G Ninja +cmake -B build/switch -G Ninja -DOPENNOW_VERSION="$opennow_version" cmake --build build/switch --target cjson mbedtls srtp2 usrsctp -j"$opennow_build_jobs" cmake --build build/switch --target SwitchNOW.nro -j"$opennow_build_jobs" diff --git a/scripts/next-release-version.sh b/scripts/next-release-version.sh new file mode 100644 index 0000000..e47f436 --- /dev/null +++ b/scripts/next-release-version.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ $# -ne 1 ]]; then + printf 'Usage: %s \n' "$0" >&2 + exit 2 +fi + +latest_tag="$1" +if [[ ! "$latest_tag" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then + printf 'Latest release tag is not a semantic version: %s\n' "$latest_tag" >&2 + exit 1 +fi + +printf '%s.%s.%s\n' \ + "$((10#${BASH_REMATCH[1]}))" \ + "$((10#${BASH_REMATCH[2]}))" \ + "$((10#${BASH_REMATCH[3]} + 1))" diff --git a/scripts/read-version.sh b/scripts/read-version.sh index 5da22d3..9e3076e 100644 --- a/scripts/read-version.sh +++ b/scripts/read-version.sh @@ -3,8 +3,8 @@ set -euo pipefail cd "$(dirname "$0")/.." -header_version="$(sed -n 's/.*kAppVersion = "\([^"]*\)".*/\1/p' app/src/app_version.hpp)" -cmake_version="$(sed -n 's/set(PROJECT_VERSION_STRING "\([^"]*\)")/\1/p' CMakeLists.txt)" +header_version="$(sed -n 's/^#define OPENNOW_APP_VERSION "\([^"]*\)"$/\1/p' app/src/app_version.hpp)" +cmake_version="$(sed -n 's/set(OPENNOW_VERSION "\([^"]*\)" CACHE.*/\1/p' CMakeLists.txt)" if [[ -z "$header_version" || -z "$cmake_version" ]]; then printf 'Unable to read the application version from app_version.hpp and CMakeLists.txt.\n' >&2 From e34dadf300517fb09c187c743bbb445240548a5e Mon Sep 17 00:00:00 2001 From: zortos293 <65777760+zortos293@users.noreply.github.com> Date: Tue, 11 Aug 2026 10:51:27 +0000 Subject: [PATCH 3/3] Pin release workflow dependencies --- .github/actionlint.yaml | 4 ++++ .github/workflows/switch-release.yml | 12 ++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 .github/actionlint.yaml diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml new file mode 100644 index 0000000..f3b5e40 --- /dev/null +++ b/.github/actionlint.yaml @@ -0,0 +1,4 @@ +self-hosted-runner: + labels: + - blacksmith-2vcpu-ubuntu-2404 + - blacksmith-4vcpu-ubuntu-2404 diff --git a/.github/workflows/switch-release.yml b/.github/workflows/switch-release.yml index 02bc3cb..9ad578d 100644 --- a/.github/workflows/switch-release.yml +++ b/.github/workflows/switch-release.yml @@ -22,7 +22,7 @@ jobs: version: ${{ steps.release.outputs.version }} steps: - name: Check out source - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 - name: Increment latest GitHub release id: release @@ -50,12 +50,12 @@ jobs: name: Build Switch NRO needs: version runs-on: blacksmith-4vcpu-ubuntu-2404 - container: devkitpro/devkita64:20260219 + container: devkitpro/devkita64@sha256:1fc388c3a0d34bd2045a6dadcb1020e069d5f876a187fd705de14b4440c00282 outputs: version: ${{ needs.version.outputs.version }} steps: - name: Check out source - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 - name: Install generator dependencies run: | @@ -72,7 +72,7 @@ jobs: run: bash scripts/package-release.sh "${{ needs.version.outputs.version }}" - name: Upload build artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 with: name: SwitchNOW-${{ needs.version.outputs.version }}-${{ github.sha }} path: | @@ -91,13 +91,13 @@ jobs: contents: write steps: - name: Download build artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 with: name: SwitchNOW-${{ needs.build.outputs.version }}-${{ github.sha }} path: dist - name: Publish release with generated notes - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 with: tag_name: v${{ needs.version.outputs.version }} name: OpenNOW Switch v${{ needs.version.outputs.version }}