-
Notifications
You must be signed in to change notification settings - Fork 222
Add github release logic when creating a release #3523
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 6 commits
7672c87
3ac9c39
44ae6db
faf99ad
971b29b
47230cf
cf69d4b
ac928ee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,11 +21,13 @@ Stryker.NET is a mutation testing framework for .NET projects. It allows you to | |
| ## Contributing Workflow | ||
|
|
||
| ### Code Standards | ||
|
|
||
| - Follow the repository's `.editorconfig` and [Microsoft C# coding guidelines](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions) | ||
| - Create or edit unit tests or integration tests for all changes | ||
| - Update documentation when adding features | ||
|
|
||
| ### Pull Request Title Convention | ||
|
|
||
| When creating or updating pull requests, **always** use Angular-style conventional commit format for PR titles: | ||
| - Format: `<type>(<scope>): <subject>` | ||
| - Types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert` | ||
|
|
@@ -38,13 +40,15 @@ When creating or updating pull requests, **always** use Angular-style convention | |
| **Why**: The project uses squash merging, so the PR title becomes the commit message in the main branch history. | ||
|
|
||
| ### Running Tests | ||
| - **Unit tests**: Run `dotnet test` in the `/src` directory | ||
|
|
||
| - **Unit tests**: Run `dotnet test` in the `/src` directory or use your IDE's test runner | ||
| - **Integration tests**: | ||
| - 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 | ||
|
|
||
| ### Testing Locally | ||
|
|
||
| To test Stryker.NET on a project: | ||
| 1. In `Stryker.CLI`, open `properties > Debug` | ||
| 2. Create a new Debug profile | ||
|
|
@@ -55,31 +59,3 @@ To test Stryker.NET on a 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
55
to
61
|
||
| ## Adding a New Mutator | ||
|
|
||
| See the full guide in [adding_a_mutator.md](../adding_a_mutator.md). | ||
|
|
||
| ### Key Points for Mutators | ||
| 1. **Purpose**: Generate mutations that look like possible human errors, not just any mutation | ||
| 2. **Performance**: Keep mutators fast - they're called on every syntax element | ||
| 3. **Buildable**: Generated mutations should compile in most situations | ||
| 4. **Killable**: Avoid mutations that always raise exceptions or are semantically equivalent | ||
| 5. **General**: Mutators should work for all projects, not be framework-specific | ||
|
|
||
| ### Implementation Steps | ||
| 1. Create a class inheriting from `MutatorBase<T>` and implementing `IMutator` | ||
| 2. Specify the expected `SyntaxNode` class you can mutate (e.g., `StatementSyntax`) | ||
| 3. Override the `MutationLevel` property (typically `Complete` or `Advanced`) | ||
| 4. Override `ApplyMutation<T>` to generate mutations | ||
| 5. Add an entry in the `Mutator` enum | ||
| 6. Create an instance in the `CsharpMutantOrchestrator` constructor | ||
| 7. Add comprehensive unit tests | ||
| 8. Update [docs/mutations.md](../docs/mutations.md) | ||
|
|
||
| ### Mutator Guidelines | ||
| - Use Roslyn APIs to work with syntax trees, not text transformations | ||
| - Each mutator is called on every syntax element recursively | ||
| - Return an empty list or `yield break` if no mutation can be generated | ||
| - Mutators must not throw exceptions | ||
| - Support various C# syntax versions (expression body vs block statement) | ||
| - Invest in unit tests early - look at existing mutator tests for examples | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,172 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Release | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workflow_dispatch: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| version: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: 'Override release version (e.g. 4.15.0). Leave empty to auto-detect from conventional commits.' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| required: false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contents: write | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false |
Copilot
AI
Apr 10, 2026
There was a problem hiding this comment.
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.
| release: | |
| release: | |
| if: github.ref == 'refs/heads/master' |
Copilot
AI
Apr 10, 2026
There was a problem hiding this comment.
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.
| uses: actions/checkout@v4 | |
| uses: actions/checkout@v6 |
Copilot
AI
Apr 24, 2026
There was a problem hiding this comment.
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.
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 |
Copilot
AI
Apr 10, 2026
There was a problem hiding this comment.
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.
| 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
AI
Apr 10, 2026
There was a problem hiding this comment.
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.
| 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
AI
Apr 10, 2026
There was a problem hiding this comment.
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
AI
Apr 10, 2026
There was a problem hiding this comment.
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
AI
Apr 10, 2026
There was a problem hiding this comment.
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
AI
Apr 10, 2026
There was a problem hiding this comment.
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.
| 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
AI
Apr 24, 2026
There was a problem hiding this comment.
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.
| 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
AI
Apr 24, 2026
There was a problem hiding this comment.
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).
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -15,4 +15,4 @@ For historical release notes prior to the consolidated changelog, see the packag | |||||
| ### Bug Fixes | ||||||
|
|
||||||
| * **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) | ||||||
| * 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) [#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) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,8 +2,8 @@ | |
| Releasing a new version of the Stryker.NET packages can be done by following these steps: | ||
| 1. Clone the repo or checkout (and pull) the master branch. | ||
| 2. Look at the commits since the last release and determine the next version number. If we are on 0.11.0 and there are only bugfixes and refactorings: we go to 0.11.1. If there are also new features or breaking changes, we go to 0.12.0. | ||
| 3. Run `npm run prepare-release` from the root of the repo and enter the new version number. | ||
| 4. Verify that the commit is on GitHub and the releases in GitHub have been made. | ||
| 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. | ||
|
Comment on lines
+5
to
+6
|
||
| 5. Wait for build on master to complete on Azure Pipelines and then start the Production environment on Azure Pipelines. | ||
| 6. Approve the Production environment on Azure Pipelines (this approval prevents accidental releases). | ||
|
|
||
|
|
||
There was a problem hiding this comment.
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.