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 new file mode 100644 index 0000000..9ad578d --- /dev/null +++ b/.github/workflows/switch-release.yml @@ -0,0 +1,109 @@ +name: Switch build and release + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: switch-${{ github.workflow }}-${{ github.ref }} + 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@11d5960a326750d5838078e36cf38b85af677262 + + - 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@sha256:1fc388c3a0d34bd2045a6dadcb1020e069d5f876a187fd705de14b4440c00282 + outputs: + version: ${{ needs.version.outputs.version }} + steps: + - name: Check out source + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + + - name: Install generator dependencies + run: | + apt-get update -qq + apt-get install -y --no-install-recommends python3-jinja2 python3-jsonschema + + - 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 "${{ needs.version.outputs.version }}" + + - name: Upload build artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 + with: + name: SwitchNOW-${{ needs.version.outputs.version }}-${{ github.sha }} + path: | + 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.event_name == 'push' && github.ref == 'refs/heads/main' + needs: + - version + - build + runs-on: blacksmith-2vcpu-ubuntu-2404 + permissions: + contents: write + steps: + - name: Download build artifact + 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@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 + with: + 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: | + dist/SwitchNOW-${{ needs.build.outputs.version }}.nro + dist/SwitchNOW-${{ needs.build.outputs.version }}.zip diff --git a/CMakeLists.txt b/CMakeLists.txt index 6548d8d..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. @@ -33,7 +38,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 @@ -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 fd1610e..d389013 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 +``` + +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 ```text 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 17ffe80..f6b4e9c 100644 --- a/scripts/build-switch-msys2.sh +++ b/scripts/build-switch-msys2.sh @@ -18,8 +18,10 @@ 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" printf '\nBuilt: %s\n' "$(pwd)/build/switch/SwitchNOW.nro" 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/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"