Skip to content

Add github release logic when creating a release#3523

Open
richardwerkman wants to merge 8 commits intomasterfrom
feature/github-releases
Open

Add github release logic when creating a release#3523
richardwerkman wants to merge 8 commits intomasterfrom
feature/github-releases

Conversation

@richardwerkman
Copy link
Copy Markdown
Member

@richardwerkman richardwerkman commented Apr 4, 2026

Addresses #3494

Update:
I've tested during the latest release and the script seems to be working. Except for the missing header in the github release for Defects and Features.

Todo:

  • Fix missing headers in github releases

Copilot AI review requested due to automatic review settings April 4, 2026 14:58
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds automation to the release preparation workflow so that creating a new version also creates a corresponding GitHub Release, and it updates documentation to reflect a move toward a consolidated root CHANGELOG.md.

Changes:

  • Update prepare-release.js to generate release notes, create an annotated Git tag containing those notes, and create a GitHub Release via the gh CLI.
  • Adjust release procedure docs to mention automatic GitHub Release creation.
  • Update the root CHANGELOG.md introduction to position it as the consolidated changelog going forward.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
stryker-net.code-workspace Minor formatting/structure fix.
RELEASING.md Documents the new release automation behavior.
prepare-release.js Adds changelog generation, annotated tagging, and GitHub Release creation logic.
CHANGELOG.md Rewords intro to a consolidated changelog with links to historical per-package changelogs.
.github/copilot-instructions.md Formatting tweaks and removal of mutator-specific section.

Comment thread prepare-release.js
if (!versionSuffix) {
console.log(`Updating changelog`);
commitMessageLines.push(`- dotnet-stryker@${newVersionNumber}`);
releaseNotes = execSync(`npx conventional-changelog-cli -p angular --tag-prefix "dotnet-stryker@"`, { encoding: 'utf8' }).trim();
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

releaseNotes is captured by running conventional-changelog-cli without limiting the output, which typically prints the entire changelog history to stdout. That means the annotated tag message (and therefore gh release ... --notes-from-tag) can become huge/incorrect (entire history instead of just this release) and may even fail due to execSync maxBuffer. Consider generating only the latest release section (e.g., --release-count 1 / -r 1) and ensure the options match whatever you write into CHANGELOG.md so the tag notes and file contents stay consistent.

Suggested change
releaseNotes = execSync(`npx conventional-changelog-cli -p angular --tag-prefix "dotnet-stryker@"`, { encoding: 'utf8' }).trim();
const changelogCommand = 'npx conventional-changelog-cli -p angular --tag-prefix "dotnet-stryker@" --release-count 1';
releaseNotes = execSync(changelogCommand, { encoding: 'utf8' }).trim();

Copilot uses AI. Check for mistakes.
Comment thread prepare-release.js
Comment on lines 67 to 70
console.log('Updating azure-pipelines.yml');
replaceVersionNumber('./azure-pipelines.yml', `VersionBuildNumber: $[counter('${oldVersion}', 1)]`, `VersionBuildNumber: $[counter('${versionPrefix}', 1)]`);
replaceVersionNumber('./azure-pipelines.yml', `PackageVersion: '${oldVersion}'`, `PackageVersion: '${versionPrefix}'`);

Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

The temp file .release-notes.md is deleted only if git tag succeeds; if git tag throws, the file is left behind in the repo root. Using a try/finally cleanup (and ideally a unique temp file location such as os.tmpdir()/fs.mkdtemp) would prevent leftover files and avoid collisions if the script is re-run.

Copilot uses AI. Check for mistakes.
Comment thread prepare-release.js
Comment on lines 79 to 83
console.log(`Creating commit`);
exec('git add .');
exec(`git commit ${commitMessageLines.map(entry => `-m "${entry}"`).join(' ')}`);

console.log(`Pushing commit ${versionSuffix?'':' and tags'}`);
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

newVersionNumber is interpolated into shell commands (git tag ...${newVersionNumber}... and gh release create ...${newVersionNumber}...) executed via execSync with a string, which runs through a shell. Even though this is a maintainer script, it’s safer to validate the version input (e.g., strict semver) and/or use execFileSync/spawnSync with an argument array to avoid shell injection and quoting issues.

Copilot uses AI. Check for mistakes.
Comment thread RELEASING.md
Comment on lines +5 to +6
3. Run `npm run prepare-release` from the root of the repo and enter the new version number. This will automatically create GitHub releases for the new tags with the correct release notes from the changelogs.
4. Verify that the commit is on GitHub and that the GitHub releases for the new version have been created.
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

The text says this will create GitHub releases for “the new tags” (plural) with notes from “the changelogs”, but prepare-release.js currently creates a single dotnet-stryker@... tag/release and updates only the root CHANGELOG.md. Please adjust the wording to match the actual behavior (singular), or update the script to create releases for multiple tags if that’s the intent.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 10, 2026 08:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 7 comments.

Comments suppressed due to low confidence (1)

.github/copilot-instructions.md:62

  • This PR is focused on release automation, but this file also removes the “Adding a New Mutator” guidance section entirely. If that removal is intentional, it should be called out in the PR description; otherwise, consider moving it to a separate PR to keep changes scoped.
6. Run with `Stryker.CLI` as the startup project

**Note**: Running Stryker on itself doesn't work as assemblies will be in use. To run Stryker on the stryker codebase, use the official nuget release via `dotnet tool install dotnet-stryker` and then `dotnet stryker`.


Comment on lines +56 to +58
- name: Generate changelog
run: conventional-changelog -p angular -t "dotnet-stryker@" > /tmp/release-notes.md

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

conventional-changelog is run before updating package.json/csproj versions. In prepare-release.js, the changelog is generated after package.json is updated, which suggests the changelog generator relies on the current version from package.json. As written, the generated notes/tag message may be stamped with the old version. Consider moving changelog generation after updating package.json (or passing the intended version explicitly, if supported).

Copilot uses AI. Check for mistakes.
contents: write

jobs:
release:
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

This workflow can be manually dispatched on any branch, but it commits, tags, and pushes directly to the checked-out ref. It should be guarded to run only from the release branch (e.g., master) to avoid accidentally creating release commits/tags from a feature branch.

Suggested change
release:
release:
if: github.ref == 'refs/heads/master'

Copilot uses AI. Check for mistakes.

permissions:
contents: write

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

Release workflows should use concurrency to prevent two manual dispatches from racing (e.g., two runs creating the same tag or pushing overlapping commits). Consider adding a concurrency group like release-${{ github.ref }} with cancel-in-progress: false.

Suggested change
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

Copilot uses AI. Check for mistakes.
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

Other workflows in this repo use actions/checkout@v6 (e.g., .github/workflows/integration-test.yaml). For consistency and to stay on the same major version baseline, consider updating this to actions/checkout@v6 as well.

Suggested change
uses: actions/checkout@v4
uses: actions/checkout@v6

Copilot uses AI. Check for mistakes.
node-version: 20

- name: Install changelog tools
run: npm install -g conventional-changelog-cli@5 conventional-recommended-bump@6 semver@7
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

npm install -g conventional-changelog-cli@5 conventional-recommended-bump@6 semver@7 pins only major versions. For a release workflow, this can lead to non-reproducible releases if a minor/patch introduces breaking behavior. Consider pinning to exact versions (or using a lockfile-based install) to make the release process deterministic.

Suggested change
run: npm install -g conventional-changelog-cli@5 conventional-recommended-bump@6 semver@7
run: npm install -g conventional-changelog-cli@5.0.0 conventional-recommended-bump@6.1.0 semver@7.6.3

Copilot uses AI. Check for mistakes.
Comment thread RELEASING.md
Comment thread prepare-release.js
exec('git push --follow-tags');
if (!versionSuffix) {
try {
const execSync = require('node:child_process').execSync;
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

execSync is already imported at the top of this file; re-requiring it here (with a different module specifier) is redundant and makes it less clear which execSync is in use. Consider reusing the existing import instead of shadowing it.

Suggested change
const execSync = require('node:child_process').execSync;

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 10, 2026 15:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 6 comments.

Comment on lines +50 to +55
echo "old_prefix=$OLD_PREFIX" >> "$GITHUB_OUTPUT"
echo "old_suffix=$OLD_SUFFIX" >> "$GITHUB_OUTPUT"
echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
echo "new_prefix=$NEW_PREFIX" >> "$GITHUB_OUTPUT"
echo "new_suffix=$NEW_SUFFIX" >> "$GITHUB_OUTPUT"

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

Writing untrusted values directly into $GITHUB_OUTPUT via echo "key=$value" can allow output-injection if inputs.version contains newlines or delimiter characters. Use the documented multiline-safe output format (e.g., key<<EOF ... EOF) or otherwise sanitize/escape NEW_VERSION/suffix before writing to $GITHUB_OUTPUT.

Suggested change
echo "old_prefix=$OLD_PREFIX" >> "$GITHUB_OUTPUT"
echo "old_suffix=$OLD_SUFFIX" >> "$GITHUB_OUTPUT"
echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
echo "new_prefix=$NEW_PREFIX" >> "$GITHUB_OUTPUT"
echo "new_suffix=$NEW_SUFFIX" >> "$GITHUB_OUTPUT"
write_github_output() {
local key="$1"
local value="$2"
local delimiter
delimiter=$(uuidgen)
{
echo "${key}<<${delimiter}"
echo "$value"
echo "${delimiter}"
} >> "$GITHUB_OUTPUT"
}
write_github_output "old_prefix" "$OLD_PREFIX"
write_github_output "old_suffix" "$OLD_SUFFIX"
write_github_output "new_version" "$NEW_VERSION"
write_github_output "new_prefix" "$NEW_PREFIX"
write_github_output "new_suffix" "$NEW_SUFFIX"

Copilot uses AI. Check for mistakes.
Comment on lines +105 to +117
run: |
node << 'EOF'
const fs = require('fs');
const { OLD_PREFIX, OLD_SUFFIX, NEW_PREFIX } = process.env;
const oldVersion = OLD_SUFFIX ? `${OLD_PREFIX}-${OLD_SUFFIX}` : OLD_PREFIX;
let content = fs.readFileSync('azure-pipelines.yml', 'utf8');
content = content.replace(
`VersionBuildNumber: $[counter('${oldVersion}', 1)]`,
`VersionBuildNumber: $[counter('${NEW_PREFIX}', 1)]`
);
content = content.replace(
`PackageVersion: '${oldVersion}'`,
`PackageVersion: '${NEW_PREFIX}'`
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

This forces PackageVersion to NEW_PREFIX and ignores NEW_SUFFIX/NEW_VERSION. If inputs.version includes a prerelease (e.g. 4.16.0-beta.1), the tag/release will be prerelease but Azure Pipelines will be updated to build/publish the stable 4.16.0, creating a version mismatch. Use NEW_VERSION (or NEW_PREFIX + NEW_SUFFIX) when updating PackageVersion, and consider whether the counter() key should also incorporate prerelease vs stable to avoid mixing build counters across channels.

Suggested change
run: |
node << 'EOF'
const fs = require('fs');
const { OLD_PREFIX, OLD_SUFFIX, NEW_PREFIX } = process.env;
const oldVersion = OLD_SUFFIX ? `${OLD_PREFIX}-${OLD_SUFFIX}` : OLD_PREFIX;
let content = fs.readFileSync('azure-pipelines.yml', 'utf8');
content = content.replace(
`VersionBuildNumber: $[counter('${oldVersion}', 1)]`,
`VersionBuildNumber: $[counter('${NEW_PREFIX}', 1)]`
);
content = content.replace(
`PackageVersion: '${oldVersion}'`,
`PackageVersion: '${NEW_PREFIX}'`
NEW_VERSION: ${{ steps.version.outputs.new_version }}
run: |
node << 'EOF'
const fs = require('fs');
const { OLD_PREFIX, OLD_SUFFIX, NEW_PREFIX, NEW_VERSION } = process.env;
const oldVersion = OLD_SUFFIX ? `${OLD_PREFIX}-${OLD_SUFFIX}` : OLD_PREFIX;
let content = fs.readFileSync('azure-pipelines.yml', 'utf8');
content = content.replace(
`VersionBuildNumber: $[counter('${oldVersion}', 1)]`,
`VersionBuildNumber: $[counter('${NEW_VERSION}', 1)]`
);
content = content.replace(
`PackageVersion: '${oldVersion}'`,
`PackageVersion: '${NEW_VERSION}'`

Copilot uses AI. Check for mistakes.
Comment on lines +56 to +71
- name: Generate changelog
run: conventional-changelog -p angular -t "dotnet-stryker@" > /tmp/release-notes.md

- name: Update CHANGELOG.md
run: |
node << 'EOF'
const fs = require('fs');
const releaseNotes = fs.readFileSync('/tmp/release-notes.md', 'utf8').trim();
const changelog = fs.readFileSync('CHANGELOG.md', 'utf8');
const marker = '<!-- changelog -->';
if (!changelog.includes(marker)) {
console.error('CHANGELOG.md is missing the <!-- changelog --> marker');
process.exit(1);
}
fs.writeFileSync('CHANGELOG.md', changelog.replace(marker, `${marker}\n\n${releaseNotes}`));
EOF
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

conventional-changelog is executed before the repo is tagged and before package.json is updated, which can cause /tmp/release-notes.md to represent the wrong section (e.g., “Unreleased” or the previous release) depending on existing tags and tool behavior. To ensure the GitHub release notes and inserted changelog section correspond exactly to NEW_VERSION, generate notes in a way that targets the unreleased range for the upcoming version (or update version/tag first and then generate notes against that state).

Copilot uses AI. Check for mistakes.
Comment on lines +86 to +97
for (const file of csprojFiles) {
let content = fs.readFileSync(file, 'utf8');
content = content.replace(
`<VersionPrefix>${OLD_PREFIX}</VersionPrefix>`,
`<VersionPrefix>${NEW_PREFIX}</VersionPrefix>`
);
content = content.replace(
/<VersionSuffix>.*<\/VersionSuffix>/,
`<VersionSuffix>${NEW_SUFFIX}</VersionSuffix>`
);
fs.writeFileSync(file, content);
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

The release workflow relies on string replacements that can silently do nothing if the file format changes (e.g., whitespace differences, multiple occurrences, missing tags). For release automation, it’s safer to assert that each expected replacement happened (and fail the workflow if not), so you don’t end up tagging/publishing a release with inconsistent version metadata.

Copilot uses AI. Check for mistakes.
- On **Windows**: Run `.\integration-tests.ps1` in the root of the repo (PowerShell 7 recommended)
- On **macOS/Linux**: Run `pwsh ./integration-tests.ps1` in the root of the repo (requires [PowerShell 7](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell))
- Always run unit tests and integration tests before committing changes
- Always run unit tests and integration after making a change to ensure nothing is broken
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

This sentence is missing a word and reads incorrectly; update 'integration' to 'integration tests' for clarity and grammar.

Suggested change
- Always run unit tests and integration after making a change to ensure nothing is broken
- Always run unit tests and integration tests after making a change to ensure nothing is broken

Copilot uses AI. Check for mistakes.
Comment thread CHANGELOG.md

* **baseline:** S3 Provider Cleanup ([#3491](https://github.com/stryker-mutator/stryker-net/issues/3491)) ([4a40c42](https://github.com/stryker-mutator/stryker-net/commit/4a40c42ded7ffdd343f991388ddc4da111ee9d04))
* handle null Messages in TestRunAccumulator.Aggregate ([#3513](https://github.com/stryker-mutator/stryker-net/issues/3513)) ([58a89b7](https://github.com/stryker-mutator/stryker-net/commit/58a89b73236e53e3419bc91fa1f36402c69835c7)), closes [#3510](https://github.com/stryker-mutator/stryker-net/issues/3510) [#3510](https://github.com/stryker-mutator/stryker-net/issues/3510) [#3510](https://github.com/stryker-mutator/stryker-net/issues/3510) No newline at end of file
* handle null Messages in TestRunAccumulator.Aggregate ([#3513](https://github.com/stryker-mutator/stryker-net/issues/3513)) ([58a89b7](https://github.com/stryker-mutator/stryker-net/commit/58a89b73236e53e3419bc91fa1f36402c69835c7)), closes [#3510](https://github.com/stryker-mutator/stryker-net/issues/3510) [#3510](https://github.com/stryker-mutator/stryker-net/issues/3510) [#3510](https://github.com/stryker-mutator/stryker-net/issues/3510)
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

The “closes” clause repeats #3510 multiple times, which makes the changelog noisy and harder to read. Suggest collapsing it to a single closes #3510 reference (or a single markdown link) to keep the entry clean.

Suggested change
* handle null Messages in TestRunAccumulator.Aggregate ([#3513](https://github.com/stryker-mutator/stryker-net/issues/3513)) ([58a89b7](https://github.com/stryker-mutator/stryker-net/commit/58a89b73236e53e3419bc91fa1f36402c69835c7)), closes [#3510](https://github.com/stryker-mutator/stryker-net/issues/3510) [#3510](https://github.com/stryker-mutator/stryker-net/issues/3510) [#3510](https://github.com/stryker-mutator/stryker-net/issues/3510)
* handle null Messages in TestRunAccumulator.Aggregate ([#3513](https://github.com/stryker-mutator/stryker-net/issues/3513)) ([58a89b7](https://github.com/stryker-mutator/stryker-net/commit/58a89b73236e53e3419bc91fa1f36402c69835c7)), closes [#3510](https://github.com/stryker-mutator/stryker-net/issues/3510)

Copilot uses AI. Check for mistakes.
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
1 New Security Hotspots (required ≤ 0)

See analysis details on SonarQube Cloud

Co-authored-by: Copilot <copilot@github.com>
Copilot AI review requested due to automatic review settings April 24, 2026 14:35
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated 4 comments.

- name: Create git tag
env:
NEW_VERSION: ${{ steps.version.outputs.new_version }}
run: git tag -a "dotnet-stryker@${NEW_VERSION}" -F /tmp/release-notes.md
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

The git tag -a ... -F /tmp/release-notes.md uses git’s default message cleanup, which strips lines starting with # (markdown headings). That’s likely why section headers (e.g., Features/Bug Fixes) go missing. Use --cleanup=verbatim here as well (consistent with prepare-release.js) so tag annotations preserve markdown headings.

Suggested change
run: git tag -a "dotnet-stryker@${NEW_VERSION}" -F /tmp/release-notes.md
run: git tag -a --cleanup=verbatim "dotnet-stryker@${NEW_VERSION}" -F /tmp/release-notes.md

Copilot uses AI. Check for mistakes.
Comment on lines +153 to +172
- name: Create git tag
env:
NEW_VERSION: ${{ steps.version.outputs.new_version }}
run: git tag -a "dotnet-stryker@${NEW_VERSION}" -F /tmp/release-notes.md

- name: Push changes and tags
run: git push --follow-tags

- name: Create GitHub release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NEW_VERSION: ${{ steps.version.outputs.new_version }}
run: |
{
cat /tmp/release-notes.md
printf "\n---\n\n**NuGet:** https://www.nuget.org/packages/dotnet-stryker/%s\n" "${NEW_VERSION}"
} > /tmp/gh-release-notes.md
gh release create "dotnet-stryker@${NEW_VERSION}" \
--title "dotnet-stryker@${NEW_VERSION}" \
--notes-file /tmp/gh-release-notes.md
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

This workflow always creates a tag and a GitHub Release even when NEW_VERSION includes a prerelease suffix (e.g. -alpha.1). The existing prepare-release.js intentionally skips tagging/release creation for suffixed versions, so this would change current behavior and can publish prereleases as normal releases. Consider either (1) skipping tag/release steps when new_suffix is non-empty, or (2) creating the GitHub release with --prerelease (and deciding whether tags should be created for prereleases).

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +22
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

Repo workflows consistently use actions/checkout@v6 (see .github/workflows/integration-test.yaml and stryker-on-stryker.yaml), but this new workflow uses actions/checkout@v4. Aligning the version avoids having multiple major versions of the same core action across workflows and makes updates/maintenance easier.

Suggested change
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
uses: actions/checkout@v6
with:
fetch-depth: 0

Copilot uses AI. Check for mistakes.
Comment on lines 55 to 61
3. Set `Launch` as `Project`
4. Set `WorkingDirectory` to a unit test project directory
5. You can use projects in `.\integrationtest\TargetProjects` for testing
6. Run with `Stryker.CLI` as the startup project

**Note**: Running Stryker on itself doesn't work as assemblies will be in use. To run Stryker on the stryker codebase, use the official nuget release via `dotnet tool install dotnet-stryker` and then `dotnet stryker`.

Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

This PR is scoped to adding GitHub release logic, but this change removes the entire “Adding a New Mutator” section from the Copilot instructions. If that removal is unintentional, it should be reverted or moved to a separate PR to keep the release-related changes focused.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants