diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml
index 2484cae..469015a 100644
--- a/.github/workflows/pr-check.yml
+++ b/.github/workflows/pr-check.yml
@@ -2,14 +2,13 @@ name: PR Check
on:
pull_request:
- push:
- branches: [ main, master, develop ]
permissions:
contents: read
jobs:
build:
+ name: build (${{ matrix.configuration }})
runs-on: ubuntu-latest
strategy:
@@ -29,3 +28,155 @@ jobs:
- name: Build ${{ matrix.configuration }}
run: dotnet build ModularityKit.Mutator.slnx -c ${{ matrix.configuration }} --no-restore
+
+ tests:
+ name: ${{ matrix.name }}
+ runs-on: ubuntu-latest
+ needs: build
+
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - name: test:core
+ command: dotnet test Tests/ModularityKit.Mutator.Tests/ModularityKit.Mutator.Tests.csproj -c Release --no-restore
+ - name: test:governance
+ command: dotnet test Tests/ModularityKit.Mutator.Governance.Tests/ModularityKit.Mutator.Governance.Tests.csproj -c Release --no-restore
+ - name: test:governance-redis
+ command: dotnet test Tests/ModularityKit.Mutator.Governance.Redis.Tests/ModularityKit.Mutator.Governance.Redis.Tests.csproj -c Release --no-restore
+
+ 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: Run ${{ matrix.name }}
+ run: ${{ matrix.command }}
+
+ examples-core:
+ name: ${{ matrix.name }}
+ runs-on: ubuntu-latest
+ needs: build
+
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - name: examples:core / BillingQuotas
+ command: dotnet run --project Examples/Core/BillingQuotas/BillingQuotas.csproj -c Release --no-restore
+ - name: examples:core / FeatureFlags
+ command: dotnet run --project Examples/Core/FeatureFlags/FeatureFlags.csproj -c Release --no-restore
+ - name: examples:core / IamRoles
+ command: dotnet run --project Examples/Core/IamRoles/IamRoles.csproj -c Release --no-restore
+ - name: examples:core / WorkflowApprovals
+ command: dotnet run --project Examples/Core/WorkflowApprovals/WorkflowApprovals.csproj -c Release --no-restore
+
+ 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: Run ${{ matrix.name }}
+ run: ${{ matrix.command }}
+
+ examples-governance:
+ name: ${{ matrix.name }}
+ runs-on: ubuntu-latest
+ needs: build
+
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - name: examples:governance / RequestLifecycle
+ command: dotnet run --project Examples/Governance/RequestLifecycle/RequestLifecycle.csproj -c Release --no-restore
+ - name: examples:governance / GovernedExecution
+ command: dotnet run --project Examples/Governance/GovernedExecution/GovernedExecution.csproj -c Release --no-restore
+ - name: examples:governance / DecisionTaxonomy
+ command: dotnet run --project Examples/Governance/DecisionTaxonomy/DecisionTaxonomy.csproj -c Release --no-restore
+ - name: examples:governance / ApprovalWorkflow
+ command: dotnet run --project Examples/Governance/ApprovalWorkflow/ApprovalWorkflow.csproj -c Release --no-restore
+ - name: examples:governance / VersionedResolution
+ command: dotnet run --project Examples/Governance/VersionedResolution/VersionedResolution.csproj -c Release --no-restore
+ - name: examples:governance / Queries
+ command: dotnet run --project Examples/Governance/Queries/Queries.csproj -c Release --no-restore
+
+ 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: Run ${{ matrix.name }}
+ run: ${{ matrix.command }}
+
+ examples-governance-redis:
+ name: examples:governance / RedisQueries
+ runs-on: ubuntu-latest
+ needs: build
+
+ 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: Start Redis
+ working-directory: Examples/Governance/RedisQueries
+ run: docker compose up -d
+
+ - name: Run RedisQueries
+ env:
+ MODULARITYKIT_REDIS: localhost:6379
+ run: dotnet run --project Examples/Governance/RedisQueries/RedisQueries.csproj -c Release --no-restore
+
+ - name: Stop Redis
+ if: ${{ always() }}
+ working-directory: Examples/Governance/RedisQueries
+ run: docker compose down
+
+ validation-summary:
+ name: validation summary
+ runs-on: ubuntu-latest
+ needs:
+ - build
+ - tests
+ - examples-core
+ - examples-governance
+ - examples-governance-redis
+ if: always()
+
+ steps:
+ - name: Report job results
+ run: |
+ echo "build: ${{ needs.build.result }}"
+ echo "tests: ${{ needs.tests.result }}"
+ echo "examples-core: ${{ needs.examples-core.result }}"
+ echo "examples-governance: ${{ needs.examples-governance.result }}"
+ echo "examples-governance-redis: ${{ needs.examples-governance-redis.result }}"
+
+ if [ "${{ needs.build.result }}" != "success" ] || \
+ [ "${{ needs.tests.result }}" != "success" ] || \
+ [ "${{ needs.examples-core.result }}" != "success" ] || \
+ [ "${{ needs.examples-governance.result }}" != "success" ] || \
+ [ "${{ needs.examples-governance-redis.result }}" != "success" ]; then
+ exit 1
+ fi
diff --git a/Tests/ModularityKit.Mutator.Governance.Tests/Approval/MutationRequestApprovalWorkflowApprovalTests.cs b/Tests/ModularityKit.Mutator.Governance.Tests/Approval/MutationRequestApprovalWorkflowApprovalTests.cs
index d4b9704..55c3b69 100644
--- a/Tests/ModularityKit.Mutator.Governance.Tests/Approval/MutationRequestApprovalWorkflowApprovalTests.cs
+++ b/Tests/ModularityKit.Mutator.Governance.Tests/Approval/MutationRequestApprovalWorkflowApprovalTests.cs
@@ -16,7 +16,7 @@ public void PendingApproval_maps_id_role_group_quorum_and_expiration_targets()
{
var expiresAt = DateTimeOffset.UtcNow.AddHours(1);
- var request = MutationRequestApprovalWorkflowTestSupport.CreateLinearApprovalRequest();
+ var request = MutationRequestApprovalWorkflowTestSupport.CreateTargetMappingApprovalRequest(expiresAt);
Assert.Equal(MutationRequestStatus.Pending, request.Status);
Assert.Equal(PendingMutationReason.Approval, request.PendingReason);
diff --git a/Tests/ModularityKit.Mutator.Governance.Tests/TestSupport/Approval/Workflow/MutationRequestApprovalWorkflowTestSupport.cs b/Tests/ModularityKit.Mutator.Governance.Tests/TestSupport/Approval/Workflow/MutationRequestApprovalWorkflowTestSupport.cs
index 905424f..756c666 100644
--- a/Tests/ModularityKit.Mutator.Governance.Tests/TestSupport/Approval/Workflow/MutationRequestApprovalWorkflowTestSupport.cs
+++ b/Tests/ModularityKit.Mutator.Governance.Tests/TestSupport/Approval/Workflow/MutationRequestApprovalWorkflowTestSupport.cs
@@ -29,6 +29,60 @@ public static MutationRequest CreateLinearApprovalRequest()
expectedStateVersion: "v10");
}
+ ///
+ /// Creates a request that exercises approval mapping for manager, quorum, role, and group targets.
+ ///
+ public static MutationRequest CreateTargetMappingApprovalRequest(DateTimeOffset expiresAt)
+ {
+ return MutationRequestFactory.PendingApproval(
+ stateId: "tenant-42:roles",
+ stateType: "IamRoleState",
+ mutationType: "GrantRoleMutation",
+ intent: CreateIntent(),
+ context: MutationContext.User("requester", "Requester", "Needs privileged access"),
+ requirements:
+ [
+ PolicyRequirement.Approval("alice", "Manager approval"),
+ new PolicyRequirement
+ {
+ Type = "Approval",
+ Description = "Security quorum",
+ Data = new
+ {
+ Approvers = new[] { "bob", "carol", "dave" },
+ StepOrder = 2,
+ ApprovalGroupId = "security-quorum",
+ Quorum = 2,
+ ExpiresAt = expiresAt,
+ Reason = "Security sign-off"
+ }
+ },
+ new PolicyRequirement
+ {
+ Type = "Approval",
+ Description = "Finance role approval",
+ Data = new
+ {
+ ApproverRole = "finance-approver",
+ StepOrder = 3,
+ Reason = "Finance sign-off"
+ }
+ },
+ new PolicyRequirement
+ {
+ Type = "Approval",
+ Description = "Operations group approval",
+ Data = new
+ {
+ ApproverGroup = "ops-oncall",
+ StepOrder = 4,
+ Reason = "Operations sign-off"
+ }
+ }
+ ],
+ expectedStateVersion: "v10");
+ }
+
///
/// Creates a request that exercises quorum-based approval requirements.
///