diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index c557df56..e06818eb 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -4,7 +4,7 @@ updates:
directory: "/"
schedule:
interval: "weekly"
- target-branch: "master"
+ target-branch: "develop"
ignore:
- dependency-name: "Microsoft.Build.Tasks.Core"
versions: ["16.*"]
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 95bd54cb..526fcaa7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -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:
@@ -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:
@@ -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.
@@ -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:
@@ -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: |
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index ef22fb1f..2e0c25f9 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -1,17 +1,13 @@
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:
@@ -19,29 +15,42 @@ jobs:
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."
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
new file mode 100644
index 00000000..60a2b6cc
--- /dev/null
+++ b/.github/workflows/lint.yml
@@ -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 (click to expand)
'
+ $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 += ' '
+ }
+
+ $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 = ''
+ $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("")) | .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
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index fd44def1..728b57c4 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -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:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 42a023fc..b2ffa38e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -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.
@@ -104,24 +129,47 @@ dotnet test Tests/Confuser.CLI.Test/Confuser.CLI.Test.csproj -c Release --collec
Every PR receives an automatic coverage comment showing per-assembly line and branch coverage. The full HTML drill-down report is downloadable as the `coverage-report` artifact from the test workflow.
-## Commit Conventions
-
-We use [Conventional Commits](https://www.conventionalcommits.org/):
+## Commit Format
```
-feat(scope): add new feature
-fix(scope): fix a bug
-test(scope): add or update tests
-refactor(scope): code change that doesn't fix a bug or add a feature
-chore(scope): build, CI, dependency updates
-docs(scope): documentation changes
+:
+
+[optional body — what changed and why]
```
-Always reference the issue number: `fix(renamer): handle FnPtr types (#6)`
+**Types** — full words, matching branch naming:
+
+| Type | When to use |
+|------|-------------|
+| `feature` | New feature or capability added |
+| `fix` | Bug fix |
+| `test` | Adding or updating tests |
+| `refactor` | Code change that neither fixes a bug nor adds a feature |
+| `chore` | Build config, dependencies, tooling, project setup |
+| `docs` | Documentation only changes |
+| `hotfix` | Urgent fix applied directly to main |
+| `experiment` | Exploratory or throwaway work |
+
+**Rules:**
+- Full words only — no abbreviations (`feature` not `feat`)
+- No parenthesized scopes — the description should be clear enough
+- Reference issue number at end when applicable: `(#42)`
+- Lowercase first word after colon
+
+**Examples:**
+
+```
+feature: add symbol server support (#54)
+fix: handle locked file exception on folder scan (#42)
+test: add cross-framework integration tests
+chore: update dependencies
+docs: add plugin development guide
+refactor: extract base repository to reduce duplication
+```
## 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
diff --git a/README.md b/README.md
index 0c2c0814..103864ec 100644
--- a/README.md
+++ b/README.md
@@ -96,9 +96,9 @@ See the [Issues][issues] section. Please check existing issues before filing a n
## Contributing
1. Fork the repository
-2. Create a feature branch from `pre-release`
+2. Create a branch from `develop` (see [CONTRIBUTING.md](CONTRIBUTING.md) for naming conventions)
3. Make your changes and ensure CI passes
-4. Open a PR targeting `pre-release`
+4. Open a PR targeting `develop`
## License
@@ -127,6 +127,6 @@ Licensed under the MIT license. See [LICENSE.md][license] for details.
[license]: LICENSE.md
[project_format]: docs/ProjectFormat.md
-[img_ci]: https://github.com/mcpolo99/ConfuserExx/actions/workflows/ci.yml/badge.svg?branch=master
+[img_ci]: https://github.com/mcpolo99/ConfuserExx/actions/workflows/ci.yml/badge.svg?branch=main
[img_codeql]: https://github.com/mcpolo99/ConfuserExx/actions/workflows/codeql-analysis.yml/badge.svg
[img_license]: https://img.shields.io/github/license/mcpolo99/ConfuserExx.svg?style=flat