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
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ updates:
directory: "/"
schedule:
interval: "weekly"
target-branch: "master"
target-branch: "develop"
ignore:
- dependency-name: "Microsoft.Build.Tasks.Core"
versions: ["16.*"]
Expand Down
26 changes: 12 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ name: ci

on:
push:
branches: [master, pre-release, feature/**, fix/**]
branches: [main, develop]
paths-ignore: ['**.md', 'docs/**', 'LICENSE*']
pull_request:
branches: [master, pre-release]
branches: [main, develop]
paths-ignore: ['**.md', 'docs/**', 'LICENSE*']

concurrency:
Expand Down Expand Up @@ -89,10 +89,10 @@ jobs:
ConfuserEx.zip
Confuser.MSBuild.Tasks/bin/Release/*.nupkg

# Pre-release: on push to pre-release branch
pre-release:
# Dev build: on push to develop branch
dev-release:
needs: build
if: github.event_name == 'push' && github.ref == 'refs/heads/pre-release'
if: github.event_name == 'push' && github.ref == 'refs/heads/develop'
runs-on: windows-2025
timeout-minutes: 5
permissions:
Expand All @@ -111,25 +111,24 @@ jobs:
run: |
$ver = nbgv get-version -v NuGetPackageVersion
echo "VERSION=$ver" >> $env:GITHUB_OUTPUT
Write-Host "Pre-release version: $ver"

- name: Download artifacts
uses: actions/download-artifact@v5
with:
name: confuserex-packages

- name: Create or update pre-release
- name: Create or update dev release
uses: softprops/action-gh-release@v2
with:
tag_name: pre-release
name: "Pre-release v${{ steps.version.outputs.VERSION }}"
tag_name: dev-latest
name: "Dev build v${{ steps.version.outputs.VERSION }}"
prerelease: true
make_latest: false
body: |
**Pre-release build** — for testing only, not production use.
**Development build** — for testing only, not production use.

Version: `${{ steps.version.outputs.VERSION }}`
Branch: `pre-release`
Branch: `develop`
Commit: ${{ github.sha }}

Download the binaries below to test recent fixes and features before they are included in a stable release.
Expand All @@ -139,10 +138,10 @@ jobs:
ConfuserEx.zip
*.nupkg

# Release: only on PR merge to master
# Release: only on PR merge to main
release:
needs: build
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: windows-2025
timeout-minutes: 5
permissions:
Expand All @@ -161,7 +160,6 @@ jobs:
run: |
$ver = nbgv get-version -v NuGetPackageVersion
echo "VERSION=$ver" >> $env:GITHUB_OUTPUT
Write-Host "Version: $ver"

- name: Configure git identity
run: |
Expand Down
29 changes: 19 additions & 10 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -1,47 +1,56 @@
name: "CodeQL"

on:
push:
branches: [master, release/*]
pull_request:
branches: [master]
schedule:
- cron: "26 4 * * 0"
- cron: "0 3 * * 1" # Every Monday 3am UTC
workflow_dispatch: # Manual trigger from Actions tab

permissions:
contents: read
security-events: write
pull-requests: read
actions: read

jobs:
analyze:
name: Analyze
runs-on: windows-2025

strategy:
fail-fast: false

steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 0
submodules: recursive

- name: Check for recent commits
id: check
shell: pwsh
run: |
$count = (git log --oneline --since="7 days ago" | Measure-Object).Count
echo "has_changes=$($count -gt 0)" >> $env:GITHUB_OUTPUT
Write-Host "Commits in last 7 days: $count"

- name: Initialize CodeQL
if: steps.check.outputs.has_changes == 'True' || github.event_name == 'workflow_dispatch'
uses: github/codeql-action/init@v3
with:
languages: csharp

- name: Setup MSBuild
if: steps.check.outputs.has_changes == 'True' || github.event_name == 'workflow_dispatch'
uses: microsoft/setup-msbuild@v2

- name: Restore
if: steps.check.outputs.has_changes == 'True' || github.event_name == 'workflow_dispatch'
run: msbuild Confuser2.sln -t:Restore -verbosity:minimal

- name: Build
if: steps.check.outputs.has_changes == 'True' || github.event_name == 'workflow_dispatch'
run: msbuild Confuser2.sln -p:Configuration=Release -verbosity:minimal

- name: Perform CodeQL Analysis
if: steps.check.outputs.has_changes == 'True' || github.event_name == 'workflow_dispatch'
uses: github/codeql-action/analyze@v3

- name: Skip notice
if: steps.check.outputs.has_changes != 'True' && github.event_name != 'workflow_dispatch'
run: echo "No commits in the last 7 days — skipping analysis."
35 changes: 0 additions & 35 deletions .github/workflows/format.yml

This file was deleted.

145 changes: 145 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
name: lint

on:
push:
paths-ignore: ['**.md', 'docs/**', 'LICENSE*']
pull_request:
branches: [main, develop]
paths-ignore: ['**.md', 'docs/**', 'LICENSE*']

concurrency:
group: lint-${{ github.ref }}
cancel-in-progress: true

jobs:
lint:
runs-on: windows-2025
timeout-minutes: 5
permissions:
contents: read
pull-requests: write
issues: write
env:
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
steps:
- uses: actions/checkout@v5

- name: Cache NuGet packages
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.vcxproj') }}
restore-keys: |
${{ runner.os }}-nuget-

- name: Restore
run: dotnet restore Confuser2.sln

- name: Check whitespace
id: whitespace
run: dotnet format whitespace Confuser2.sln --verify-no-changes --verbosity minimal 2>&1 | Tee-Object -Variable wsOutput
shell: pwsh
continue-on-error: true

- name: Check style
id: style
run: dotnet format style Confuser2.sln --verify-no-changes --severity warn 2>&1 | Tee-Object -Variable styleOutput
shell: pwsh
continue-on-error: true

- name: Check analyzers
id: analyzers
run: dotnet format analyzers Confuser2.sln --verify-no-changes --severity warn 2>&1 | Tee-Object -Variable analyzerOutput
shell: pwsh
continue-on-error: true

- name: Build lint report
if: always()
id: report
shell: pwsh
run: |
$ws = '${{ steps.whitespace.outcome }}'
$st = '${{ steps.style.outcome }}'
$an = '${{ steps.analyzers.outcome }}'
$anyFailed = ($ws -eq 'failure') -or ($st -eq 'failure') -or ($an -eq 'failure')

$md = @()
$md += '## Lint Results'
$md += ''

if (-not $anyFailed) {
$md += '> :white_check_mark: **All checks passed**'
} else {
$md += '> :warning: **Issues found** — run `dotnet format Confuser2.sln` locally to fix'
}

$md += ''
$md += '| Check | Result |'
$md += '|-------|--------|'

$icon = if ($ws -eq 'success') { ':white_check_mark:' } else { ':x:' }
$md += "| Whitespace (indentation, line endings) | $icon |"

$icon = if ($st -eq 'success') { ':white_check_mark:' } else { ':x:' }
$md += "| Style (IDE rules, naming, var usage) | $icon |"

$icon = if ($an -eq 'success') { ':white_check_mark:' } else { ':x:' }
$md += "| Analyzers (CA*, RCS* rules) | $icon |"

# Get specific violations if any failed
if ($anyFailed) {
$md += ''
$md += '<details><summary><strong>Details (click to expand)</strong></summary>'
$md += ''
$md += '```'
# Re-run to capture output
$violations = dotnet format Confuser2.sln --verify-no-changes --verbosity diagnostic 2>&1 | Select-String 'error|warning' | Select-Object -First 30
foreach ($v in $violations) { $md += $v.ToString().Trim() }
if ($violations.Count -ge 30) { $md += '... (truncated, run dotnet format locally for full list)' }
$md += '```'
$md += ''
$md += '</details>'
}

$md -join "`n" | Set-Content -Path 'lint-report.md' -Encoding utf8
$md -join "`n" >> $env:GITHUB_STEP_SUMMARY

echo "any_failed=$anyFailed" >> $env:GITHUB_OUTPUT

- name: Post PR comment
if: always() && github.event_name == 'pull_request'
uses: marocchino/sticky-pull-request-comment@v2
with:
header: lint-report
path: lint-report.md

- name: Post issue comment
if: always() && github.event_name == 'push' && github.event.pull_request == null
shell: pwsh
run: |
# Extract issue number from branch name (e.g. 54-nuget-packages → 54)
$branch = "${{ github.ref_name }}"
if ($branch -match '^(\d+)-') {
$issueNumber = $Matches[1]
$marker = '<!-- lint-bot -->'
$body = $marker + "`n" + (Get-Content 'lint-report.md' -Raw)

# Find existing lint comment
$comments = gh api "repos/${{ github.repository }}/issues/$issueNumber/comments" --jq '.[] | select(.body | startswith("<!-- lint-bot -->")) | .id' 2>$null
if ($comments) {
# Update existing
gh api "repos/${{ github.repository }}/issues/comments/$comments" -X PATCH -f body="$body" 2>$null
} else {
# Create new
gh issue comment $issueNumber --repo ${{ github.repository }} --body "$body" 2>$null
}
}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Fail if issues found
if: always() && steps.report.outputs.any_failed == 'True'
shell: pwsh
run: |
Write-Host "::warning::Lint issues found. Run 'dotnet format Confuser2.sln' locally to fix."
exit 1
5 changes: 1 addition & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
name: test

on:
push:
branches: [master, pre-release, feature/**, fix/**]
paths-ignore: ['**.md', 'docs/**', 'LICENSE*']
pull_request:
branches: [master, pre-release]
branches: [main, develop]
paths-ignore: ['**.md', 'docs/**', 'LICENSE*']

concurrency:
Expand Down
31 changes: 28 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,37 @@ Contributions of any kind are welcome. For bugfixes and unit tests, you can subm
## Getting Started

1. Fork the repository
2. Create a feature branch from `pre-release`: `git checkout -b feat/my-feature pre-release`
2. Create a branch from `develop` (see naming conventions below)
3. Make your changes and ensure CI passes
4. Open a PR targeting `pre-release`
4. Open a PR targeting `develop`

See [README.md](README.md#building-from-source) for build prerequisites.

## Branch Naming Convention

### With an issue (preferred)

Use GitHub's built-in branch creation:

```bash
gh issue develop 42 --checkout
# → creates branch: 42-fix-samba-timeout (auto-sanitized by GitHub)
```

### Without an issue

| Scenario | Pattern | Example |
|----------|---------|---------|
| Feature | `feature/{description}` | `feature/add-symbol-server` |
| Chore | `chore/{description}` | `chore/update-dependencies` |
| Documentation | `docs/{description}` | `docs/add-plugin-guide` |
| Hotfix (urgent) | `hotfix/{description}` | `hotfix/crash-on-startup` |
| Experiment | `experiment/{description}` | `experiment/avalonia-port` |

**Slug rules:** lowercase, words separated by `-`, no special characters, max ~50 chars.

All branches target `develop` except `hotfix/` which branches from and merges to `main`.

## Testing Policy

Every PR must maintain or improve test coverage. We use a **ratchet strategy** — coverage only goes up, never down.
Expand Down Expand Up @@ -121,7 +146,7 @@ Always reference the issue number: `fix(renamer): handle FnPtr types (#6)`

## Pull Request Process

1. PRs target `pre-release`, not `master`
1. PRs target `develop`, not `main`
2. CI must pass (build + tests + coverage)
3. Coverage must not decrease
4. Only include files that are part of your change — no unrelated modifications
Expand Down
Loading
Loading