Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ jobs:
with:
fetch-depth: 0

- name: Configure git identity
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"

- name: Apply feature version bumps
run: |
python tools/feature_version_audit.py \
Expand Down
26 changes: 9 additions & 17 deletions .releaserc.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
const releaseType = process.env.RELEASE_TYPE || 'rc';
const isRC = (process.env.RELEASE_TYPE || 'rc') === 'rc';

module.exports = {
branches: [
{
name: 'dev',
...(releaseType === 'rc' ? { prerelease: 'rc' } : {}),
},
],
// RC: needs 'main' as non-prerelease anchor (semantic-release v25 requires >= 1).
// Stable: 'dev' is the release branch directly.
branches: isRC
? ['main', { name: 'dev', prerelease: 'rc' }]
: ['dev'],
plugins: [
'@semantic-release/commit-analyzer',
'@semantic-release/release-notes-generator',
Expand All @@ -17,16 +16,9 @@ module.exports = {
{
files: ['CMakeLists.txt'],
from: 'VERSION [0-9]+\\.[0-9]+\\.[0-9]+',
to: 'VERSION ${nextRelease.version}',
results: [
{
file: 'CMakeLists.txt',
hasChanged: true,
numReplacements: 1,
numMatches: 1,
},
],
countMatches: true,
// Strip prerelease suffix so CMake gets '1.5.0' not '1.5.0-rc.1'.
// No results assertion: stable after RC is a no-op (version already set).
to: "VERSION ${nextRelease.version.split('-')[0]}",
Comment on lines 18 to +21
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Inspect release plugin/action version references in repo config and lock files.
# Expected: Find the semantic-release action and any pinned replace-plugin versions, if present.

rg -n -C3 '(`@google/semantic-release-replace-plugin`|semantic-release-replace-plugin|cycjimmy/semantic-release-action)' \
  --iglob 'package*.json' \
  --iglob 'pnpm-lock.yaml' \
  --iglob 'yarn.lock' \
  --iglob '*.yaml' \
  --iglob '*.yml'

Repository: doodlum/skyrim-community-shaders

Length of output: 58


🏁 Script executed:

# Check if .releaserc.js exists and view its content
find . -name ".releaserc.js" -o -name ".releaserc" -o -name "releaserc*" | head -20

Repository: doodlum/skyrim-community-shaders

Length of output: 91


🏁 Script executed:

# Check package.json for semantic-release dependencies
fd -name 'package.json' -exec grep -l 'semantic-release\|release' {} \;

Repository: doodlum/skyrim-community-shaders

Length of output: 306


🏁 Script executed:

# Look at the repository structure
ls -la . | head -20

Repository: doodlum/skyrim-community-shaders

Length of output: 1300


🏁 Script executed:

# Read the .releaserc.js file
cat -n .releaserc.js

Repository: doodlum/skyrim-community-shaders

Length of output: 1386


🏁 Script executed:

# Check package.json for semantic-release dependencies
cat package.json

Repository: doodlum/skyrim-community-shaders

Length of output: 120


🏁 Script executed:

# Search for package.json anywhere in the repo
find . -name 'package.json' -type f

Repository: doodlum/skyrim-community-shaders

Length of output: 58


🏁 Script executed:

# Search for lock files
find . -name 'pnpm-lock.yaml' -o -name 'yarn.lock' -o -name 'package-lock.json' | head -5

Repository: doodlum/skyrim-community-shaders

Length of output: 58


🏁 Script executed:

# Check for any dependency specifications in other config files
grep -r 'google.*semantic-release-replace-plugin' . --include='*.json' --include='*.yaml' --include='*.yml' 2>/dev/null | head -10

Repository: doodlum/skyrim-community-shaders

Length of output: 170


🏁 Script executed:

# Read the release workflow to understand how the plugin is invoked
cat -n .github/workflows/release.yaml

Repository: doodlum/skyrim-community-shaders

Length of output: 1751


🌐 Web query:

@google/semantic-release-replace-plugin from callback support API documentation

💡 Result:

The @google/semantic-release-replace-plugin (also published as semantic-release-replace-plugin) supports callback functions for both the 'from' and 'to' options in its Replacement configuration interface. This is an advanced feature primarily for use with release.config.js (JavaScript config files), as JSON configs cannot express functions. Key details from the official API documentation: - from: Can be From or From[], where From is string | RegExp | FromCallback. FromCallback is defined as (filename: string, ...args: unknown[]) => RegExp | string. Consult replace-in-file docs for advanced matching with callbacks, RegExps, etc. - to: Can be To or To[], where To is string | ToCallback. ToCallback is (match: string, ...args: unknown[]) => string. Callback args vary: - For simple string 'from', 'to' callback simplest form receives the filename. - For RegExp 'from', args include captures, offset, matched string, etc. (per String.replace docs). Example for 'to' callback (from docs): { from: VERSION = 11, to: (matched) => VERSION: ${parseInt(matched.split('=')[1].trim) + 1}, } The plugin uses replace-in-file under the hood, adapting its API (single from/to vs. arrays). Templates like ${nextRelease.version} are rendered first using semantic-release context. Note: Requires release.config.js for callbacks; package.json configs are limited to strings. Pair with @semantic-release/git to commit changes. Official sources: GitHub repo at https://github.com/jpoehnelt/semantic-release-replace-plugin (docs/interfaces/Replacement.md and types). NPM pages confirm @google/ namespace is the same package.

Citations:


The callback proposal has a critical flaw: it breaks no-op behavior for stable releases.

The concern is valid—dropping results validation lets regex drift silently—and @google/semantic-release-replace-plugin does support callback-based from options. However, the proposed guard would throw an error when the CMake version pattern is absent, which occurs on stable releases after RC (when the pattern was already replaced). The comment explicitly states "stable after RC is a no-op (version already set)," but the callback would fail instead of allowing that no-op state.

To preserve no-op replacements while catching regex drift, consider this approach instead:

Alternative guard preserving no-op behavior

Rather than asserting the match exists upfront, validate that the pattern was either replaced OR already matched the desired state:

from: (filename) => {
  const contents = fs.readFileSync(filename, 'utf8');
  const alreadyMatches = /VERSION \d+\.\d+\.\d+(?!-)/m.test(contents);
  // Ensure pattern exists OR file already has desired version format (for no-op case)
  if (!alreadyMatches && !/VERSION \d+\.\d+\.\d+/.test(contents)) {
    throw new Error(`Missing CMake VERSION pattern in ${filename}`);
  }
  return /VERSION [0-9]+\.[0-9]+\.[0-9]+/gm;
},

This allows the regex to match (replacing any prerelease version) while still catching if the VERSION line is missing entirely.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.releaserc.js around lines 18 - 21, Replace the string "from" in
.releaserc.js with a callback that reads the file contents (use fs.readFileSync)
and first checks whether the file already contains a stable VERSION pattern
(e.g., /VERSION \d+\.\d+\.\d+(?!-)/) to allow the no-op case; if that stable
pattern is absent, verify the prerelease/version pattern (/VERSION
\d+\.\d+\.\d+/) exists and only then return the regex (/VERSION
[0-9]+\.[0-9]+\.[0-9]+/gm) to perform the replacement, otherwise throw a clear
error about the missing VERSION line so you catch regex drift without breaking
stable-after-RC no-ops.

},
],
},
Expand Down
Loading