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. ///