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
7 changes: 7 additions & 0 deletions .github/config/auto-assign.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
addAssignees: author

addReviewers: false

skipKeywords:
- wip
- draft
43 changes: 43 additions & 0 deletions .github/config/labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
abstractions:
- changed-files:
- any-glob-to-any-file:
- src/Abstractions/**

runtime:
- changed-files:
- any-glob-to-any-file:
- src/Runtime/**

examples:
- changed-files:
- any-glob-to-any-file:
- Examples/**

tests:
- changed-files:
- any-glob-to-any-file:
- Tests/**
- '**/*Tests.cs'

benchmark:
- changed-files:
- any-glob-to-any-file:
- Benchmarks/**

documentation:
- changed-files:
- any-glob-to-any-file:
- Docs/**
- '*.md'
- readme.md

architecture:
- changed-files:
- any-glob-to-any-file:
- Docs/Decision/**
- .github/config/**

ci:
- changed-files:
- any-glob-to-any-file:
- .github/**
51 changes: 51 additions & 0 deletions .github/config/labels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
- name: bug
color: "d73a4a"
description: Something is broken or incorrect

- name: enhancement
color: "a2eeef"
description: New functionality or behavior

- name: documentation
color: "0075ca"
description: Documentation updates and additions

- name: architecture
color: "8B5E3C"
description: Design, structure, and API-shape changes

- name: abstractions
color: "5B4B8A"
description: Public abstractions and contracts

- name: runtime
color: "8A4F7D"
description: Runtime implementation and execution flow

- name: examples
color: "1d76db"
description: Runnable examples and sample apps

- name: ci
color: "5319e7"
description: CI/CD and repository automation changes

- name: tests
color: "fbca04"
description: Test coverage and test changes

- name: performance
color: "0e4d92"
description: Performance improvements or regressions

- name: benchmark
color: "5319e7"
description: Benchmark coverage and performance measurement changes

- name: breaking-change
color: "b60205"
description: Introduces a breaking change

- name: skip-changelog
color: "ededed"
description: Exclude this change from release notes
20 changes: 20 additions & 0 deletions .github/config/pr-title-checker.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"LABEL": {
"name": "",
"color": "EEEEEE"
},
"CHECKS": {
"regexp": "^(feat|fix|docs|style|refactor|perf|test|build|ci|chore)(\\([a-z0-9-]+\\))?: .+$",
"regexpFlags": "i",
"ignoreLabels": [
"State One",
"State Two"
],
"alwaysPassCI": false
},
"MESSAGES": {
"success": "PR title matches the required format.",
"failure": "PR title must match: type(optional-scope): description",
"notice": "Allowed types: feat, fix, docs, style, refactor, perf, test, build, ci, chore."
}
}
27 changes: 27 additions & 0 deletions .github/workflows/labels-sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Labels Sync

on:
push:
branches: [ main ]
paths:
- .github/config/labels.yml
- .github/workflows/labels-sync.yml
workflow_dispatch:

permissions:
issues: write
contents: read

jobs:
sync:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v5

- name: Sync repository labels
uses: EndBug/label-sync@v2
with:
config-file: .github/config/labels.yml
delete-other-labels: true
97 changes: 97 additions & 0 deletions .github/workflows/pr-automation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: Pull Request Automation

on:
pull_request_target:
types: [ opened, edited, synchronize, reopened, ready_for_review, labeled, unlabeled ]

permissions:
contents: read
issues: write
pull-requests: write

jobs:
assign-author:
if: github.event.action == 'opened' || github.event.action == 'ready_for_review'
runs-on: ubuntu-latest

steps:
- name: Assign PR author
uses: kentaro-m/auto-assign-action@v2.0.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
configuration-path: .github/config/auto-assign.yml

title-check:
runs-on: ubuntu-latest

steps:
- name: Check PR title
uses: thehanimo/pr-title-checker@v1.4.3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
pass_on_octokit_error: false
configuration_path: .github/config/pr-title-checker.json

labeler:
runs-on: ubuntu-latest

steps:
- name: Label changed files
uses: actions/labeler@v6
with:
configuration-path: .github/config/labeler.yml
sync-labels: true

performance-labeler:
runs-on: ubuntu-latest

steps:
- name: Apply Performance label from issues or PR text
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { owner, repo } = context.repo;
const pr = context.payload.pull_request;
const text = `${pr.title}\n${pr.body || ''}`.toLowerCase();
const keywordMatch = /(perf|performance|benchmark|optimiz|allocation|memory pressure|throughput|latency)/i.test(text);
const issueNumbers = new Set();

for (const match of text.matchAll(/(?:closes|fixes|related to)\s+#(\d+)/gi)) {
issueNumbers.add(Number(match[1]));
}

for (const match of text.matchAll(/#(\d+)/g)) {
issueNumbers.add(Number(match[1]));
}

let issueMatch = false;

for (const number of issueNumbers) {
const issue = await github.rest.issues.get({ owner, repo, issue_number: number });
const labels = issue.data.labels.map(label => label.name);

if (labels.includes('performance')) {
issueMatch = true;
break;
}
}

if (!keywordMatch && !issueMatch) {
core.info('Performance label not applicable for this PR.');
return;
}

const currentLabels = pr.labels.map(label => label.name);
if (currentLabels.includes('performance')) {
core.info('Performance label already present.');
return;
}

await github.rest.issues.addLabels({
owner,
repo,
issue_number: pr.number,
labels: ['performance']
});
core.info('Performance label added.');
31 changes: 31 additions & 0 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: PR Check

on:
pull_request:
push:
branches: [ main, master, develop ]

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
configuration: [ Debug, Release ]

steps:
- uses: actions/checkout@v5

- uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x

- name: Restore
run: dotnet restore ModularityKit.Mutator.slnx

- name: Build ${{ matrix.configuration }}
run: dotnet build ModularityKit.Mutator.slnx -c ${{ matrix.configuration }} --no-restore
59 changes: 59 additions & 0 deletions .github/workflows/publish-artifacts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Publish Artifacts

on:
workflow_call:
inputs:
package_version:
description: "Optional package version, usually the release tag without the leading v."
required: false
type: string

permissions:
contents: read

jobs:
package:
name: Pack library
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v5

- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x

- name: Restore
run: dotnet restore src/ModularityKit.Mutator.csproj

- name: Resolve package version
id: version
env:
PACKAGE_VERSION: ${{ inputs.package_version }}
REF_NAME: ${{ github.ref_name }}
run: |
version="$PACKAGE_VERSION"
if [ -z "$version" ]; then
version="$REF_NAME"
fi
version="${version#v}"
if ! printf '%s' "$version" | grep -Eq '^[0-9]+(\.[0-9]+){1,2}([-+][0-9A-Za-z.-]+)?$'; then
version="0.1.0"
fi
echo "package_version=$version" >> "$GITHUB_OUTPUT"

- name: Pack package
run: >
dotnet pack src/ModularityKit.Mutator.csproj
-c Release
--no-restore
-o nupkg
-p:PackageVersion=${{ steps.version.outputs.package_version }}

- name: Upload package
uses: actions/upload-artifact@v4
with:
name: ModularityKit.Mutator-nupkg
path: nupkg/*.nupkg
42 changes: 42 additions & 0 deletions .github/workflows/publish-attested.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Publish Attested

on:
workflow_dispatch:

permissions:
contents: write
id-token: write
attestations: write
artifact-metadata: write

jobs:
publish:
uses: ./.github/workflows/publish-artifacts.yml

release:
name: Upload artifacts to draft release
runs-on: ubuntu-latest
needs: publish

steps:
- name: Checkout
uses: actions/checkout@v5

- name: Download published artifacts
uses: actions/download-artifact@v6
with:
pattern: ModularityKit.Mutator-nupkg
path: dist
merge-multiple: true

- name: Create or update draft release
env:
GITHUB_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
DIST_DIR: dist
FIND_DRAFT: "true"
ENSURE_DRAFT: "true"
FAIL_MESSAGE: "No draft release found. Release Drafter must create the draft before artifacts can be uploaded."
ASSET_PATTERNS: |
*
run: python3 -m scripts.releases.upload_release_assets
Loading