From 259c7473e08e193777c5c8d8c06f900eac9af427 Mon Sep 17 00:00:00 2001 From: Framer Date: Sat, 7 Nov 2026 22:40:42 +0100 Subject: [PATCH 1/4] fix(release): package complete binaries instead of Qt plugin folders --- .github/workflows/release.yml | 79 +++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 27 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 28de72131d..224f73b233 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -77,9 +77,8 @@ jobs: with: pattern: frameropia-*-${{ inputs.sha }} path: artifacts + merge-multiple: false - # Asset names drop the commit sha: the tag already identifies the build, and stable names let - # the notes table link to them. (Not named dist/: the repository has one.) - name: Package release files shell: bash run: | @@ -87,34 +86,60 @@ jobs: rm -rf release-assets mkdir -p release-assets shopt -s nullglob - strip_sha() { sed "s/-${SHA}//" <<< "$1"; } - artifacts=(artifacts/*/) - ((${#artifacts[@]} > 0)) || { echo "No build artifacts were downloaded" >&2; exit 1; } - for artifact in "${artifacts[@]}"; do + artifact_dirs=(artifacts/*/) + + # download-artifact may extract the only matching artifact directly into + # artifacts/. Never mistake Qt plugin directories for build artifacts. + if [[ -s artifacts/frameropia.exe && -s artifacts/frameropia-cli.exe ]]; then + artifact_dirs=(artifacts/) + fi + (("${#artifact_dirs[@]}" > 0)) || { + echo "No build artifacts were downloaded" >&2 + exit 1 + } + + packaged=0 + for artifact in "${artifact_dirs[@]}"; do name=$(basename "$artifact") - appimages=("$artifact"*.AppImage) - mac_zips=("$artifact"*.zip) - if ((${#appimages[@]} > 0)); then - # Linux: ship the AppImage and tar.gz as they are. - for file in "${appimages[@]}" "$artifact"*.tar.gz; do - [[ -f "$file" ]] || continue - cp "$file" "release-assets/$(strip_sha "$(basename "$file")")" - done - elif ((${#mac_zips[@]} > 0)); then - # macOS: the app bundle zip and the dmg. - for file in "${mac_zips[@]}" "$artifact"*.dmg; do - [[ -f "$file" ]] || continue - cp "$file" "release-assets/$(strip_sha "$(basename "$file")")" - done - else - # Windows: upload-artifact stores the bin folder; zip it once for the release. - (cd "$artifact" && zip -qr "${GITHUB_WORKSPACE}/release-assets/$(strip_sha "$name").zip" .) + if [[ "$artifact" == artifacts/ ]]; then + name="frameropia-windows-x86_64-$SHA" fi + case "$name" in + frameropia-windows-*-"$SHA") + # A valid Windows archive contains BOTH complete executables, + # their DLLs and Qt plugin subdirectories in ONE ZIP. + test -s "$artifact/frameropia.exe" + test -s "$artifact/frameropia-cli.exe" + out="release-assets/${name%-$SHA}.zip" + (cd "$artifact" && zip -qr "$GITHUB_WORKSPACE/$out" .) + unzip -Z1 "$out" | grep -qx 'frameropia.exe' + unzip -Z1 "$out" | grep -qx 'frameropia-cli.exe' + packaged=$((packaged+1)) + ;; + frameropia-linux-*-"$SHA") + for ext in AppImage tar.gz; do + file="$artifact/frameropia-${name#frameropia-}.$ext" + [[ -f "$file" ]] || continue + cp "$file" "release-assets/$(basename "$file" | sed "s/-$SHA//")" + packaged=$((packaged+1)) + done + ;; + frameropia-macos-*-"$SHA") + for ext in zip dmg; do + file="$artifact/frameropia-${name#frameropia-}.$ext" + [[ -f "$file" ]] || continue + cp "$file" "release-assets/$(basename "$file" | sed "s/-$SHA//")" + packaged=$((packaged+1)) + done + ;; + *) + echo "Unexpected build artifact directory: $name" >&2 + exit 1 + ;; + esac done - files=(release-assets/*) - ((${#files[@]} > 0)) || { echo "Build artifacts contained no release files" >&2; exit 1; } - printf 'Prepared %s release assets\n' "${#files[@]}" - ls -la release-assets + ((packaged > 0)) || { echo "No valid release assets" >&2; exit 1; } + ls -lah release-assets - name: Write release notes shell: bash From 322deefd9da1361f65a54c75738dec698f844598 Mon Sep 17 00:00:00 2001 From: Framer Date: Sat, 7 Nov 2026 22:41:40 +0100 Subject: [PATCH 2/4] fix(release): handle flattened artifacts and correct Linux/macOS filenames --- .github/workflows/release.yml | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 224f73b233..ce8c939540 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -92,6 +92,15 @@ jobs: # artifacts/. Never mistake Qt plugin directories for build artifacts. if [[ -s artifacts/frameropia.exe && -s artifacts/frameropia-cli.exe ]]; then artifact_dirs=(artifacts/) + else + # Likewise a single Linux/macOS artifact can be flattened by the action. + root_packages=(artifacts/frameropia-"$SHA"-*.AppImage + artifacts/frameropia-"$SHA"-*.tar.gz + artifacts/frameropia-"$SHA"-*.zip + artifacts/frameropia-"$SHA"-*.dmg) + if (("${#root_packages[@]}" > 0)); then + artifact_dirs=(artifacts/) + fi fi (("${#artifact_dirs[@]}" > 0)) || { echo "No build artifacts were downloaded" >&2 @@ -102,7 +111,14 @@ jobs: for artifact in "${artifact_dirs[@]}"; do name=$(basename "$artifact") if [[ "$artifact" == artifacts/ ]]; then - name="frameropia-windows-x86_64-$SHA" + if [[ -s artifacts/frameropia.exe ]]; then + name="frameropia-windows-x86_64-$SHA" + else + first="${root_packages[0]##*/}" + platform="${first#frameropia-$SHA-}" + platform="${platform%%.*}" + name="frameropia-$platform-$SHA" + fi fi case "$name" in frameropia-windows-*-"$SHA") @@ -117,18 +133,22 @@ jobs: packaged=$((packaged+1)) ;; frameropia-linux-*-"$SHA") + platform="${name#frameropia-}" + platform="${platform%-$SHA}" for ext in AppImage tar.gz; do - file="$artifact/frameropia-${name#frameropia-}.$ext" - [[ -f "$file" ]] || continue - cp "$file" "release-assets/$(basename "$file" | sed "s/-$SHA//")" + file="$artifact/frameropia-$SHA-$platform.$ext" + [[ -s "$file" ]] || continue + cp "$file" "release-assets/frameropia-$platform.$ext" packaged=$((packaged+1)) done ;; frameropia-macos-*-"$SHA") + platform="${name#frameropia-}" + platform="${platform%-$SHA}" for ext in zip dmg; do - file="$artifact/frameropia-${name#frameropia-}.$ext" - [[ -f "$file" ]] || continue - cp "$file" "release-assets/$(basename "$file" | sed "s/-$SHA//")" + file="$artifact/frameropia-$SHA-$platform.$ext" + [[ -s "$file" ]] || continue + cp "$file" "release-assets/frameropia-$platform.$ext" packaged=$((packaged+1)) done ;; From b4272f075bbf3fe8f203d7eee43dc45af02393d6 Mon Sep 17 00:00:00 2001 From: Framer Date: Sat, 7 Nov 2026 22:43:21 +0100 Subject: [PATCH 3/4] release: repair v0.0.1 archive, title and asset list from verified build --- .github/workflows/repair-v0.0.1.yml | 98 +++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 .github/workflows/repair-v0.0.1.yml diff --git a/.github/workflows/repair-v0.0.1.yml b/.github/workflows/repair-v0.0.1.yml new file mode 100644 index 0000000000..fb78dc694d --- /dev/null +++ b/.github/workflows/repair-v0.0.1.yml @@ -0,0 +1,98 @@ +name: repair-v0.0.1-release + +# One-time repair of a published release that accidentally uploaded Qt plugin folders. +# Reuses the exact successful v0.0.1 Windows artifact, without changing the git tag. +on: + push: + branches: [nx2] + paths: + - .github/workflows/repair-v0.0.1.yml + +permissions: + contents: write + actions: read + +jobs: + repair: + if: github.repository == 'Framerr/Frameropia' + runs-on: ubuntu-24.04 + env: + GH_TOKEN: ${{ github.token }} + TAG: v0.0.1 + ORIGINAL_SHA: 4db9b59173315eace20b03d6178e77a2d4f36445 + ARCHIVE: frameropia-windows-x86_64.zip + steps: + - name: Check out trusted source + uses: actions/checkout@v7 + with: + persist-credentials: false + + - name: Download the successful original Windows build + uses: actions/download-artifact@v8 + with: + name: eglantine-windows-x86_64-4db9b59173315eace20b03d6178e77a2d4f36445 + run-id: 42410526945 + github-token: ${{ github.token }} + path: original-build + + - name: Verify release tag and prepare a complete ZIP + shell: bash + run: | + set -euo pipefail + actual=$(gh api "repos/$GITHUB_REPOSITORY/git/ref/tags/$TAG" --jq '.object.sha') + [[ "$actual" == "$ORIGINAL_SHA" ]] || { + echo "Release tag does not point to the original build; refusing to modify it" >&2 + exit 1 + } + test -s original-build/eglantine.exe + test -s original-build/eden-cli.exe + (cd original-build && zip -qr "../$ARCHIVE" .) + test -s "$ARCHIVE" + unzip -Z1 "$ARCHIVE" | grep -qx 'eglantine.exe' + unzip -Z1 "$ARCHIVE" | grep -qx 'eden-cli.exe' + unzip -Z1 "$ARCHIVE" | grep -qE '^(plugins/|platforms/)' + echo "Verified the original binaries and Qt runtime files in $ARCHIVE" + + - name: Repair release notes and published assets + shell: bash + run: | + set -euo pipefail + gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null + gh release upload "$TAG" "$ARCHIVE" --repo "$GITHUB_REPOSITORY" --clobber + + cat docs/releases/v0.0.1.md > repaired-notes.md + cat >>repaired-notes.md <<'NOTES' + + ## Windows download + + [Download the complete Windows x86_64 archive](https://github.com/Framerr/Frameropia/releases/download/v0.0.1/frameropia-windows-x86_64.zip) + + **Historical executable names:** this v0.0.1 build was compiled before the Frameropia application rebrand. Extract the entire ZIP and run `eglantine.exe`; the included CLI is `eden-cli.exe`. Future builds use `frameropia.exe` and `frameropia-cli.exe`. Do not extract Qt plugin folders separately. + NOTES + + gh release edit "$TAG" --repo "$GITHUB_REPOSITORY" \ + --title 'Frameropia v0.0.1 (legacy test build)' \ + --notes-file repaired-notes.md --prerelease + + # Only remove the eight known accidental Qt plugin archives. + for stale in generic.zip iconengines.zip imageformats.zip \ + networkinformation.zip platforms.zip plugins.zip styles.zip tls.zip; do + if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" --json assets \ + --jq '.assets[].name' | grep -Fxq "$stale"; then + gh release delete-asset "$TAG" "$stale" \ + --repo "$GITHUB_REPOSITORY" --yes + fi + done + + - name: Verify the corrected release + shell: bash + run: | + set -euo pipefail + assets=$(gh release view "$TAG" --repo "$GITHUB_REPOSITORY" --json assets \ + --jq '.assets[].name') + test "$assets" = "$ARCHIVE" || { + echo "Unexpected assets remaining:" >&2 + echo "$assets" >&2 + exit 1 + } + gh release view "$TAG" --repo "$GITHUB_REPOSITORY" From bdcc62fbafb821970aa4c92226f95121b1c171eb Mon Sep 17 00:00:00 2001 From: Framer Date: Sat, 7 Nov 2026 22:44:58 +0100 Subject: [PATCH 4/4] fix(build): correct parent CMake override for Frameropia CLI output --- .github/workflows/fork-windows-check.yml | 1 + src/CMakeLists.txt | 2 +- tools/ci/check-frameropia-branding.sh | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/fork-windows-check.yml b/.github/workflows/fork-windows-check.yml index d89cf882d1..df03d8dde3 100644 --- a/.github/workflows/fork-windows-check.yml +++ b/.github/workflows/fork-windows-check.yml @@ -7,6 +7,7 @@ on: paths: - .github/workflows/fork-windows-check.yml - .github/workflows/build-windows.yml + - src/CMakeLists.txt - src/yuzu/** - src/yuzu_cmd/** - src/qt_common/** diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c15294ff7f..7f54849854 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -285,7 +285,7 @@ endif() if(YUZU_CMD) add_subdirectory(yuzu_cmd) - set_target_properties(yuzu-cmd PROPERTIES OUTPUT_NAME "eden-cli") + set_target_properties(yuzu-cmd PROPERTIES OUTPUT_NAME "frameropia-cli") endif() if(ENABLE_QT) diff --git a/tools/ci/check-frameropia-branding.sh b/tools/ci/check-frameropia-branding.sh index 9e3c37db8e..d872178668 100644 --- a/tools/ci/check-frameropia-branding.sh +++ b/tools/ci/check-frameropia-branding.sh @@ -17,6 +17,7 @@ require src/yuzu/configuration/configure.ui "Frameropia Configuration" require CMakeModules/GenerateSCMRev.cmake 'set(REPO_NAME "Frameropia")' require src/yuzu/CMakeLists.txt 'OUTPUT_NAME "frameropia"' require src/yuzu_cmd/CMakeLists.txt 'OUTPUT_NAME "frameropia-cli"' +require src/CMakeLists.txt 'OUTPUT_NAME "frameropia-cli"' require .github/workflows/build-windows.yml 'frameropia.exe' require .github/workflows/build-linux.yml 'build/release/bin/frameropia' require .github/workflows/build-macos.yml 'build/release/bin/frameropia.app'