From 943e33d71f6f609097ff53e44202e89ce9025ece Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Mon, 6 Jul 2026 00:48:17 -0700 Subject: [PATCH 1/5] chore: use shared alandtse/nexus-workflows upload-nexus.yml reusable workflow Splits the Nexus upload out of the monolithic build job into its own job that calls the shared reusable workflow, replacing the inline dotnet-installed agc93/NexusUploader (UNEX_COOKIES) with the maintained BUTR.NexusUploader fork via UNEX_NEXUSMODS_SESSION_COOKIE, matching sibling repos. Also adds check_existing: true for idempotent re-runs (safe against duplicate changelog entries as of nexus-workflows v1.5.2, alandtse/nexus-workflows#8). UNEX_NEXUSMODS_SESSION_COOKIE and UNEX_APIKEY were already distributed to this repo by the Nexus-Secrets controller; UNEX_COOKIES is no longer used and can be removed once this lands. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01G5JEn6sUpkBx2o68oLBmqk --- .github/workflows/build.yml | 54 ++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8c46b6e..2b80841 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,6 +23,11 @@ jobs: include: - os: windows-latest vcpkgCommitId: '6f7ffeb18f99796233b958aaaf14ec7bd4fb64b2' + outputs: + new_release_published: ${{ steps.semantic.outputs.new_release_published }} + new_release_version: ${{ steps.semantic.outputs.new_release_version }} + new_release_git_tag: ${{ steps.semantic.outputs.new_release_git_tag }} + new_release_notes: ${{ steps.semantic.outputs.new_release_notes }} steps: - uses: actions/checkout@v3 @@ -77,30 +82,25 @@ jobs: file: build/release-msvc/MergeMapper_${{ steps.semantic.outputs.new_release_version }}.7z tag: ${{ steps.semantic.outputs.new_release_git_tag }} overwrite: true - - name: Setup Dotnet - if: steps.semantic.outputs.new_release_published == 'true' - uses: actions/setup-dotnet@v3 - with: - dotnet-version: '3.1.x' - - name: Download NexusUploader - if: steps.semantic.outputs.new_release_published == 'true' - run: dotnet tool install -g NexusUploader - - name: Upload files to Nexus - # https://github.com/agc93/nexus-uploader - if: steps.semantic.outputs.new_release_published == 'true' - env: - UNEX_COOKIES: ${{ secrets.UNEX_COOKIES }} - UNEX_APIKEY: ${{ secrets.UNEX_APIKEY }} - UNEX_GAME: skyrimspecialedition - UNEX_MODID: 74689 - UNEX_FILENAME: MergeMapper - UNEX_FILEDESCRIPTION: |- - See Description -> Requirements for installation instructions. - PDB is for crash debugging and can be removed. - UNEX_PREVIOUSFILE: "auto" - file: build/release-msvc/MergeMapper_${{ steps.semantic.outputs.new_release_version }}.7z - version: ${{ steps.semantic.outputs.new_release_version }} - changelog: ${{ steps.semantic.outputs.new_release_notes }} - run: | - unex upload $UNEX_MODID $file -v $version - unex changelog $version "$changelog" + + nexus-upload: + needs: job + if: needs.job.outputs.new_release_published == 'true' + uses: alandtse/nexus-workflows/.github/workflows/upload-nexus.yml@dceaf2d82ecf19569a0282930cc4322422c44b3a # v1.5.2 + with: + nexus_game_id: skyrimspecialedition + nexus_mod_id: "74689" + tag_name: ${{ needs.job.outputs.new_release_git_tag }} + mod_version: ${{ needs.job.outputs.new_release_version }} + mod_filename: MergeMapper + changelog: ${{ needs.job.outputs.new_release_notes }} + file_description: |- + See Description -> Requirements for installation instructions. + PDB is for crash debugging and can be removed. + previous_file: auto + # Idempotent re-runs; safe against duplicate changelog reposts as of + # nexus-workflows v1.5.2 (alandtse/nexus-workflows#8). + check_existing: true + secrets: + UNEX_NEXUSMODS_SESSION_COOKIE: ${{ secrets.UNEX_NEXUSMODS_SESSION_COOKIE }} + UNEX_APIKEY: ${{ secrets.UNEX_APIKEY }} From 3bbaa4b37e99dbf7bd3f4c61ef3904c2b8d6a449 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Mon, 6 Jul 2026 01:28:49 -0700 Subject: [PATCH 2/5] chore: use @main pin for consistency with the rest of the fleet Most repos calling this reusable workflow already track @main rather than a pinned SHA; switching this one back matches that convention. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01G5JEn6sUpkBx2o68oLBmqk --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2b80841..a00d6e3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -86,7 +86,7 @@ jobs: nexus-upload: needs: job if: needs.job.outputs.new_release_published == 'true' - uses: alandtse/nexus-workflows/.github/workflows/upload-nexus.yml@dceaf2d82ecf19569a0282930cc4322422c44b3a # v1.5.2 + uses: alandtse/nexus-workflows/.github/workflows/upload-nexus.yml@main with: nexus_game_id: skyrimspecialedition nexus_mod_id: "74689" From 251189c23c86fae5fd51961e672bef98f789f959 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Mon, 6 Jul 2026 01:57:43 -0700 Subject: [PATCH 3/5] fix: modernize semantic-release-action to v4 and drop achingbrain plugin alias cycjimmy/semantic-release-action@v3 with the @achingbrain/semantic-release-github tarball-aliased @semantic-release/github install was failing npm install (no usable stderr surfaced by the action, just a generic "Command failed" error). .releaserc already references the plain @semantic-release/github plugin, and fallout_vr_address_library already runs cleanly on @v4 with the plain package, so this drops the years-old alias workaround and matches that known-working config. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01G5JEn6sUpkBx2o68oLBmqk --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a00d6e3..1cd8551 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,14 +54,14 @@ jobs: run: echo "root='${{ steps.runvcpkg.outputs.RUNVCPKG_VCPKG_ROOT_OUT }}', triplet='${{ steps.runvcpkg.outputs.RUNVCPKG_VCPKG_DEFAULT_TRIPLET_OUT }}'" - name: Semantic Release - uses: cycjimmy/semantic-release-action@v3 + uses: cycjimmy/semantic-release-action@v4 id: semantic # Need an `id` for output variables with: # You can specify specifying version range for the extra plugins if you prefer. extra_plugins: | @semantic-release/changelog @semantic-release/git - @semantic-release/github@"https://registry.npmjs.org/@achingbrain/semantic-release-github/-/semantic-release-github-0.0.0.tgz" + @semantic-release/github @google/semantic-release-replace-plugin dry_run: false env: From 056a3a3c0fb2511a9d84fb93ce56a6a8cb5acf59 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Mon, 6 Jul 2026 02:01:26 -0700 Subject: [PATCH 4/5] chore: bump third-party actions to latest majors actions/checkout v3->v7, lukka/run-vcpkg v10->v11, cycjimmy/semantic-release-action v4->v6, svenstaro/upload-release-action 2.3.0->2.11.5. lukka/run-cmake and lukka/get-cmake were already tracking their latest majors. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01G5JEn6sUpkBx2o68oLBmqk --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1cd8551..761bba2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,7 +30,7 @@ jobs: new_release_notes: ${{ steps.semantic.outputs.new_release_notes }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v7 - uses: lukka/get-cmake@latest - name: Dump the content of $RUNNER_TEMP run: find $RUNNER_TEMP @@ -40,7 +40,7 @@ jobs: shell: bash - name: Restore artifacts, or setup vcpkg (do not install any package) - uses: lukka/run-vcpkg@v10 + uses: lukka/run-vcpkg@v11 id: runvcpkg with: # This specifies the location of vcpkg, where it is going to be restored from cache, or create from scratch. @@ -54,7 +54,7 @@ jobs: run: echo "root='${{ steps.runvcpkg.outputs.RUNVCPKG_VCPKG_ROOT_OUT }}', triplet='${{ steps.runvcpkg.outputs.RUNVCPKG_VCPKG_DEFAULT_TRIPLET_OUT }}'" - name: Semantic Release - uses: cycjimmy/semantic-release-action@v4 + uses: cycjimmy/semantic-release-action@v6 id: semantic # Need an `id` for output variables with: # You can specify specifying version range for the extra plugins if you prefer. @@ -75,7 +75,7 @@ jobs: buildPreset: Release-MSVC - name: Upload files to a GitHub release if: steps.semantic.outputs.new_release_published == 'true' - uses: svenstaro/upload-release-action@2.3.0 + uses: svenstaro/upload-release-action@2.11.5 with: repo_token: ${{ secrets.GITHUB_TOKEN }} file_glob: true From ca81274c3653d71e46c98f287f6dfe043953e1a7 Mon Sep 17 00:00:00 2001 From: Alan Tse Date: Mon, 6 Jul 2026 19:45:48 -0700 Subject: [PATCH 5/5] ci: add pre-commit config and modernize the credential-check workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pre-commit.ci was erroring on this PR ("error during ci config") because the repo had no .pre-commit-config.yaml at all. Adds one, which surfaced: - trailing-whitespace/EOF fixes in a handful of files (whitespace only, including src/MergeMapper.cpp) - unex-check.yml still used the old agc93/NexusUploader tool and UNEX_COOKIES secret, both already replaced in the real upload path by this PR — migrated it to BUTR.NexusUploader + UNEX_NEXUSMODS_SESSION_COOKIE/UNEX_APIKEY so the daily credential check actually validates what's used - check-json excludes .vscode/ (VS Code config files are JSONC, not JSON) - actionlint's report on build.yml's `${{ runner.workspace }}` is suppressed via -ignore rather than "fixed": it's not a valid expression context, but the CI run already confirmed the resulting path resolves correctly in practice, and the technically-correct replacement (github.workspace) is a different directory (one level deeper), which would be a real behavior change disguised as a lint fix Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01G5JEn6sUpkBx2o68oLBmqk --- .github/workflows/unex-check.yml | 25 ++++++++--------- .pre-commit-config.yaml | 27 +++++++++++++++++++ .releaserc | 2 +- .vscode/tasks.json | 2 +- LICENSE | 2 +- contrib/Distribution/Config/MergeMapper.yaml | 2 +- contrib/Distribution/fomod/ModuleConfig.xml | Bin 4038 -> 4039 bytes contrib/Distribution/fomod/info.xml | Bin 636 -> 637 bytes src/MergeMapper.cpp | 8 +++--- 9 files changed, 46 insertions(+), 22 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/unex-check.yml b/.github/workflows/unex-check.yml index 1207e4b..6dc4a64 100644 --- a/.github/workflows/unex-check.yml +++ b/.github/workflows/unex-check.yml @@ -10,24 +10,21 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup Dotnet - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@v5 with: - dotnet-version: '3.1.x' - include-prerelease: false - - name: Download NexusUploader - run: dotnet tool install -g NexusUploader - - name: Check Nexus Cookies - # https://github.com/agc93/nexus-uploader + dotnet-version: 8.x.x + - name: Download BUTR.NexusUploader + run: dotnet tool install -g BUTR.NexusUploader + - name: Check Nexus session cookie + # https://github.com/BUTR/BUTR.NexusUploader env: - UNEX_COOKIES: ${{ secrets.UNEX_COOKIES }} - UNEX_APIKEY: ${{ secrets.UNEX_APIKEY }} + UNEX_SESSION_COOKIE: ${{ secrets.UNEX_NEXUSMODS_SESSION_COOKIE }} run: | - unex check --cookie + unex check --session-cookie "$UNEX_SESSION_COOKIE" - name: Check Nexus API Key - # https://github.com/agc93/nexus-uploader - # https://www.nexusmods.com/users/myaccount?tab=api%20access + # https://github.com/BUTR/BUTR.NexusUploader + # https://www.nexusmods.com/users/myaccount?tab=api%20access env: - UNEX_COOKIES: ${{ secrets.UNEX_COOKIES }} UNEX_APIKEY: ${{ secrets.UNEX_APIKEY }} run: | - unex check --key $UNEX_APIKEY \ No newline at end of file + unex check --key "$UNEX_APIKEY" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..2d8b6e7 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,27 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-json + exclude: ^\.vscode/ # VS Code config files are JSONC (allow comments) + - id: check-added-large-files + + - repo: https://github.com/rhysd/actionlint + rev: v1.7.12 + hooks: + - id: actionlint + # lukka/run-vcpkg's own templates use `${{ runner.workspace }}` (an Azure + # Pipelines-style context carried over as boilerplate); it evaluates to + # empty on GitHub-hosted runners but the resulting relative path still + # resolves correctly in practice (confirmed by real CI runs). Swapping to + # `github.workspace` is not equivalent (one directory level deeper) and + # would change the actual vcpkg cache path, so this is suppressed rather + # than "fixed". + args: + - -ignore + - 'property "workspace" is not defined in object type' diff --git a/.releaserc b/.releaserc index 8e4ed6c..9855b48 100644 --- a/.releaserc +++ b/.releaserc @@ -48,4 +48,4 @@ } ] ] -} \ No newline at end of file +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 362f04b..20b7c4d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -38,4 +38,4 @@ } } ] -} \ No newline at end of file +} diff --git a/LICENSE b/LICENSE index 46061f5..8cbbbce 100644 --- a/LICENSE +++ b/LICENSE @@ -199,4 +199,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file + limitations under the License. diff --git a/contrib/Distribution/Config/MergeMapper.yaml b/contrib/Distribution/Config/MergeMapper.yaml index 69bf935..b41c4c8 100644 --- a/contrib/Distribution/Config/MergeMapper.yaml +++ b/contrib/Distribution/Config/MergeMapper.yaml @@ -1,3 +1,3 @@ debug: logLevel: debug - flushLevel: trace \ No newline at end of file + flushLevel: trace diff --git a/contrib/Distribution/fomod/ModuleConfig.xml b/contrib/Distribution/fomod/ModuleConfig.xml index 5452650b2e92347f5f9e9f6c630b4250470ec479..fc0281a68be0475935450ba64f1c6b33612b0482 100644 GIT binary patch delta 9 QcmX>me_VdUF@8oa02Jc`TmS$7 delta 7 OcmX>ue@uSEF@69JHv>@s diff --git a/contrib/Distribution/fomod/info.xml b/contrib/Distribution/fomod/info.xml index ca21b148968e74e6c037e460be51ef4dd5fb6f5a..6d47714e5321bd332703aabb608560155490b70d 100644 GIT binary patch delta 9 Qcmeyv@|R^p4HF|502O)zI{*Lx delta 7 Ocmey%@`q(Z4HEzl5Cbp( diff --git a/src/MergeMapper.cpp b/src/MergeMapper.cpp index 3848eb2..c4cdbb4 100644 --- a/src/MergeMapper.cpp +++ b/src/MergeMapper.cpp @@ -246,13 +246,13 @@ std::pair MergeMapperInterface001::GetOriginalFormID(co return std::make_pair(modName, formID); } -bool MergeMapperPluginAPI::MergeMapperInterface001::isMerge(const char* modName) { +bool MergeMapperPluginAPI::MergeMapperInterface001::isMerge(const char* modName) { std::string espkey = modName; toLower(espkey); return reverseMergeMap.contains(espkey); } -bool MergeMapperPluginAPI::MergeMapperInterface001::wasMerged(const char* modName) { +bool MergeMapperPluginAPI::MergeMapperInterface001::wasMerged(const char* modName) { std::string espkey = modName; toLower(espkey); return mergeMap.contains(espkey); @@ -281,9 +281,9 @@ bool MergeMapperInterface001::CheckForRedundantPlugins() { for (auto i = 0; i < modCount; i++) { const auto file = files[i]; plugin = std::string{file->GetFilename()}; - oldPlugin = std::string{MergeMapperInterface001::GetNewFormID(plugin.c_str(), 0).first}; + oldPlugin = std::string{MergeMapperInterface001::GetNewFormID(plugin.c_str(), 0).first}; logger::debug(fmt::runtime(fileFormat), file->GetCompileIndex(), "", plugin); - result = isRedundant(plugin, oldPlugin) || result; + result = isRedundant(plugin, oldPlugin) || result; } for (auto i = 0; i < lightCount; i++) { const auto file = smallfiles[i];