diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 382108982..10790d187 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -24,4 +24,4 @@
"rollForward": false
}
}
-}
\ No newline at end of file
+}
diff --git a/.csharpierignore b/.csharpierignore
index 0fc6daabb..af0d3708a 100644
--- a/.csharpierignore
+++ b/.csharpierignore
@@ -1,2 +1,2 @@
-ArchUnitNETTests/Fluent/Syntax/Elements/TypeSyntaxElementsTests.cs
+ArchUnitNETTests/Fluent/Syntax/Elements/TypeSyntaxElementsTests.cs
ArchUnitNETTests/Fluent/Syntax/Elements/ObjectSyntaxElementsTests.cs
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 368266182..478477017 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -1,2 +1,3 @@
60e7aa44819edda932026dc2254db2876e70ead3
-dce4f8e835aea7f610b6cdda6f89b62a711df35b
\ No newline at end of file
+dce4f8e835aea7f610b6cdda6f89b62a711df35b
+1619721dee9a8aac6570eaffe13993b3eee12838
diff --git a/.gitconfig b/.gitconfig
index 5226ad694..a714c2604 100644
--- a/.gitconfig
+++ b/.gitconfig
@@ -1,2 +1,2 @@
[blame]
- ignoreRevsFile = .git-blame-ignore-revs
\ No newline at end of file
+ ignoreRevsFile = .git-blame-ignore-revs
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 2fcc75d36..3fd621781 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -53,7 +53,7 @@ body:
.That()
.ImplementInterface(typeof(IExampleInterface))
.As("Example Classes");
-
+
[Fact]
public void TypesShouldBeInCorrectLayer()
{
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 9d90ee921..e70875e13 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -10,35 +10,36 @@ on:
release:
types: [published]
+permissions:
+ contents: read
+
jobs:
- formatting:
- name: Check formatting
+ lint:
+ name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- - name: Setup .NET
- uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0
with:
- dotnet-version: 10.0.400
- - name: Install tools
- run: dotnet tool restore
- - name: Check formatting
- run: dotnet csharpier check .
+ persist-credentials: false
+ - name: Setup mise
+ uses: jdx/mise-action@3c2e0cf82a5b2e5249f0d3635a4d83d0ae861518 # v4.2.5
+ - name: Check formatting and lint
+ run: mise run check
coverage:
name: Check code coverage
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- - name: Setup .NET
- uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0
with:
- dotnet-version: 10.0.400
+ persist-credentials: false
+ - name: Setup mise
+ uses: jdx/mise-action@3c2e0cf82a5b2e5249f0d3635a4d83d0ae861518 # v4.2.5
- name: Run tests
run: dotnet test -c Debug --collect:"XPlat Code Coverage" --settings coverlet.runsettings ArchUnitNETTests/
- name: Upload coverage reports to Codecov
- uses: codecov/codecov-action@v7.0.0
+ uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
run-tests:
@@ -50,17 +51,17 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- - name: Setup .NET
- uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0
with:
- dotnet-version: 10.0.400
+ persist-credentials: false
+ - name: Setup mise
+ uses: jdx/mise-action@3c2e0cf82a5b2e5249f0d3635a4d83d0ae861518 # v4.2.5
- name: Run tests
run: dotnet test -c Debug
publish-docs:
name: Publish documentation
runs-on: ubuntu-latest
needs:
- - formatting
+ - lint
- coverage
- run-tests
permissions:
@@ -70,18 +71,22 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: ./current
+ persist-credentials: false
- name: Checkout gh-pages branch
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: gh-pages
path: ./docs
+ # Credentials are needed here: the later "Commit and push changes" /
+ # "Update readthedocs preview" steps push to this checkout.
+ persist-credentials: true # zizmor: ignore[artipacked]
- name: Setup doxygen
run: sudo apt-get install doxygen graphviz
- name: Setup environment
run: |
if [[ "$GITHUB_REF" =~ ^"refs/tags/"[0-9]+.[0-9]+.[0-9]+$ ]]; then
docs_subpath="stable"
- else
+ else
if [[ "$GITHUB_REF" =~ ^"refs/tags/"[0-9]+.[0-9]+.[0-9]+-[a-z]+.[0-9]+$ ]]; then
docs_subpath="preview"
else
@@ -92,9 +97,11 @@ jobs:
echo "DOCS_OUTPUT_DIR=$GITHUB_WORKSPACE/docs/$docs_subpath" >> "$GITHUB_ENV"
- name: Generate documentation
working-directory: ./current/documentation
+ env:
+ DOCS_OUTPUT_DIR: ${{ env.DOCS_OUTPUT_DIR }}
run: |
set -eo pipefail
- rm -rf "${{ env.DOCS_OUTPUT_DIR }}"
+ rm -rf "$DOCS_OUTPUT_DIR"
doxygen
touch .nojekyll
- name: Check release conditions
@@ -131,16 +138,16 @@ jobs:
runs-on: windows-latest
environment: deploy
needs:
- - formatting
+ - lint
- coverage
- run-tests
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- - name: Setup .NET
- uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0
with:
- dotnet-version: 10.0.400
+ persist-credentials: false
+ - name: Setup mise
+ uses: jdx/mise-action@3c2e0cf82a5b2e5249f0d3635a4d83d0ae861518 # v4.2.5
- name: Build
run: dotnet build -c Release
- name: Pack
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index c30e1d3c6..60c2bd310 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -17,18 +17,20 @@ jobs:
security-events: write
strategy:
fail-fast: false
- matrix:
- language: ["csharp"]
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
with:
- languages: ${{ matrix.language }}
- - name: Autobuild
- uses: github/codeql-action/autobuild@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
+ languages: "csharp"
+ - name: Setup mise
+ uses: jdx/mise-action@3c2e0cf82a5b2e5249f0d3635a4d83d0ae861518 # v4.2.5
+ - name: Build
+ run: dotnet build -c Release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
with:
- category: "/language:${{matrix.language}}"
+ category: "/language:csharp"
diff --git a/.gitleaks.toml b/.gitleaks.toml
new file mode 100644
index 000000000..2e6f292af
--- /dev/null
+++ b/.gitleaks.toml
@@ -0,0 +1,10 @@
+[extend]
+useDefault = true
+
+[allowlist]
+# gitleaks' `dir` mode scans the working tree regardless of git tracking, so
+# gitignored local IDE state (e.g. JetBrains .idea/workspace.xml, common for
+# this C# project's contributors) gets scanned even though it's never committed.
+paths = [
+ '''\.idea/''',
+]
diff --git a/.mise/tasks/check b/.mise/tasks/check
new file mode 100755
index 000000000..2fcd4879d
--- /dev/null
+++ b/.mise/tasks/check
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+#MISE description="Run formatting and lint checks via hk"
+#USAGE flag "-f --fix" help="Apply fixes instead of only reporting them"
+set -euo pipefail
+
+if [ "${usage_fix:-}" = "true" ]; then
+ hk check --all --fix --no-fail-fast
+else
+ hk check --all --no-fail-fast
+fi
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 3d706bcdd..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,35 +0,0 @@
-language: csharp
-solution: ArchUnit.sln
-jobs:
- include:
- - stage: linux_build
- dotnet: 6.0.110
- mono: none
- os: linux
- dist: focal
- script:
- - chmod +x ./Travis/test_linux.sh && ./Travis/test_linux.sh
- before_deploy:
- - sudo apt-get install doxygen doxygen-doc graphviz
- deploy:
- skip_cleanup: true
- provider: script
- script: chmod +x ./Travis/deploy_documentation.sh && ./Travis/deploy_documentation.sh
- on:
- tags: true
- all_branches: true
- - stage: windows_build
- mono: none
- os: windows
- before_script:
- - choco install dotnet-6.0-sdk --version=6.0.402
- - PowerShell -Command 'Set-ExecutionPolicy -ExecutionPolicy RemoteSigned'
- script:
- - PowerShell -File Travis/test_windows.ps1 -tag "$TRAVIS_TAG"
- deploy:
- skip_cleanup: true
- provider: script
- script: PowerShell -File Travis/deploy.ps1 -apiKey $NUGET_API_KEY -source $NUGET_SOURCE
- on:
- tags: true
- all_branches: true
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 000000000..7e906e80e
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,9 @@
+# AGENTS.md
+
+- Setup: `mise install` (also restores NuGet packages and local .NET tools)
+- Build: `dotnet build`
+- Test: `dotnet test`
+- Lint/format check: `mise run check`
+- Lint/format autofix: `mise run check --fix`
+- Run build, test, and `mise run check` before finishing a task
+- Sign off commits per the [DCO](DCO): `git commit -s`
diff --git a/ArchUnit.sln.DotSettings b/ArchUnit.sln.DotSettings
index c1aee607c..22d8dab12 100644
--- a/ArchUnit.sln.DotSettings
+++ b/ArchUnit.sln.DotSettings
@@ -3,7 +3,7 @@
Required
Required
Required
-
+
False
True
@@ -12,4 +12,4 @@
True
True
True
-
\ No newline at end of file
+
diff --git a/ArchUnitNET/ArchUnitNET.csproj.DotSettings b/ArchUnitNET/ArchUnitNET.csproj.DotSettings
index 5b3eb4004..fae1cdddc 100644
--- a/ArchUnitNET/ArchUnitNET.csproj.DotSettings
+++ b/ArchUnitNET/ArchUnitNET.csproj.DotSettings
@@ -1,8 +1,8 @@
-
+
Required
Required
Required
Required
False
- True
\ No newline at end of file
+ True
diff --git a/ArchUnitNETTests/Fluent/Syntax/Elements/ObjectSyntaxElementsTests.cs b/ArchUnitNETTests/Fluent/Syntax/Elements/ObjectSyntaxElementsTests.cs
index beeefb49f..9a482324e 100644
--- a/ArchUnitNETTests/Fluent/Syntax/Elements/ObjectSyntaxElementsTests.cs
+++ b/ArchUnitNETTests/Fluent/Syntax/Elements/ObjectSyntaxElementsTests.cs
@@ -253,7 +253,7 @@ public async Task CallAnyTest()
helper.AddSnapshotHeader("No violations");
var should = MethodMembers().That().Are(helper.MethodWithSingleDependency).Should();
-
+
helper.AddSnapshotSubHeader("Conditions");
should.CallAny(helper.CalledMethod).AssertNoViolations(helper);
should.CallAny(new List { helper.CalledMethod }).AssertNoViolations(helper);
@@ -305,7 +305,7 @@ public async Task CallAnyTest()
helper.AddSnapshotHeader("Input with multiple dependencies");
should = MethodMembers().That().Are(helper.MethodWithMultipleDependencies).Should();
-
+
helper.AddSnapshotSubHeader("Conditions");
should.CallAny(helper.CalledMethod1, helper.MethodWithoutDependencies).AssertNoViolations(helper);
should.CallAny(helper.MethodWithoutDependencies).AssertOnlyViolations(helper);
@@ -367,13 +367,13 @@ public async Task DependOnAnyTest()
helper.AddSnapshotHeader("Referenced type");
should = Types().That().Are(helper.ClassWithReferencedTypeDependency).Should();
-
+
helper.AddSnapshotSubHeader("Conditions");
should.DependOnAny(helper.ReferencedType).AssertNoViolations(helper);
-
+
helper.AddSnapshotSubHeader("Predicates");
should.Be(Types().That().DependOnAny(helper.ReferencedType)).AssertNoViolations(helper);
-
+
helper.AddSnapshotHeader("Empty arguments");
should = Types().That().Are(helper.ClassWithMultipleDependencies).Should();
@@ -517,7 +517,7 @@ public async Task FollowCustomPredicateTest()
helper.AddSnapshotSubHeader("Predicates");
should.BeTypesThat().FollowCustomPredicate(new CustomPredicate()).AssertNoViolations(helper);
should.BeTypesThat().FollowCustomPredicate(t => t.Name == "ChildClass", "follow custom predicate").AssertNoViolations(helper);
-
+
helper.AddSnapshotHeader("Violations");
should = Types().That().Are(helper.BaseClass).Should();
@@ -1146,7 +1146,7 @@ public async Task HaveNameTest()
should.Be(Types().That().HaveAssemblyQualifiedNameStartingWith(helper.BaseClass.Name)).AssertOnlyViolations(helper);
should.Be(Types().That().HaveAssemblyQualifiedNameEndingWith(helper.BaseClass.Namespace.FullName)).AssertOnlyViolations(helper);
should.Be(Types().That().HaveAssemblyQualifiedNameContaining(helper.NonExistentObjectName)).AssertOnlyViolations(helper);
-
+
await helper.AssertSnapshotMatches();
}
@@ -1351,13 +1351,13 @@ public async Task NotDependOnAnyTest()
helper.AddSnapshotHeader("Referenced type");
should = Types().That().Are(helper.ClassWithReferencedTypeDependency).Should();
-
+
helper.AddSnapshotSubHeader("Conditions");
should.NotDependOnAny(helper.ReferencedType).AssertOnlyViolations(helper);
-
+
helper.AddSnapshotHeader("Predicates");
should.Be(Types().That().DoNotDependOnAny(helper.ReferencedType)).AssertOnlyViolations(helper);
-
+
helper.AddSnapshotHeader("Empty arguments");
should = Types().That().Are(helper.ChildClass).Should();
@@ -1770,7 +1770,7 @@ public async Task NotHaveAttributeWithArgumentsTest()
helper.AddSnapshotHeader("Empty arguments");
should = Types().That().Are(helper.ClassWithSingleAttributeWithArguments).Should();
-
+
helper.AddSnapshotSubHeader("Conditions");
should.NotHaveAttributeWithArguments(helper.Attribute1, new List