Speed up CI/CD runs, scope the developer CLI, and harden workflow hygiene #4
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Code Style | |
| on: | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - "application/**" | |
| - "developer-cli/**" | |
| - ".github/workflows/code-style.yml" | |
| - "!**.md" | |
| pull_request: | |
| paths: | |
| - "application/**" | |
| - "developer-cli/**" | |
| - ".github/workflows/code-style.yml" | |
| - "!**.md" | |
| workflow_dispatch: | |
| permissions: | |
| id-token: write | |
| contents: read | |
| pull-requests: write | |
| jobs: | |
| detect-changes: | |
| name: Detect Changes | |
| runs-on: ubuntu-24.04 | |
| outputs: | |
| backend_scope: ${{ steps.scope.outputs.backend_scope }} | |
| backend_label: ${{ steps.scope.outputs.backend_label }} | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v6 | |
| with: | |
| # Need history to diff against the base ref | |
| fetch-depth: 0 | |
| - name: Resolve Backend Scope | |
| id: scope | |
| env: | |
| BASE_REF: ${{ github.event.pull_request.base.sha || format('{0}~1', github.sha) }} | |
| HEAD_REF: ${{ github.event.pull_request.head.sha || github.sha }} | |
| run: | | |
| # Run scoped commands only when exactly one SCS's backend changed and nothing shared. | |
| # Anything shared (shared-kernel, AppGateway, root, or developer-cli) forces a full pass, | |
| # since per-SCS slnf scopes don't cover those projects. | |
| changed=$(git diff --name-only "$BASE_REF" "$HEAD_REF") | |
| account=false | |
| main=false | |
| other=false | |
| while IFS= read -r path; do | |
| case "$path" in | |
| application/account/Api/*|application/account/Core/*|application/account/Workers/*|application/account/Tests/*) | |
| account=true ;; | |
| application/main/Api/*|application/main/Core/*|application/main/Workers/*|application/main/Tests/*) | |
| main=true ;; | |
| application/AppGateway/*|application/shared-kernel/*|developer-cli/*) | |
| other=true ;; | |
| application/*) | |
| # Files directly under application/ (slnx, package.json, etc.) — treat as shared. | |
| # Subdirectories matched the cases above. | |
| other=true ;; | |
| esac | |
| done <<< "$changed" | |
| if [[ "$other" == "true" ]] || { [[ "$account" == "true" ]] && [[ "$main" == "true" ]]; }; then | |
| echo "backend_scope=" >> "$GITHUB_OUTPUT" | |
| echo "backend_label=full backend (PlatformPlatform.slnx)" >> "$GITHUB_OUTPUT" | |
| elif [[ "$account" == "true" ]]; then | |
| echo "backend_scope=--self-contained-system account" >> "$GITHUB_OUTPUT" | |
| echo "backend_label=account only" >> "$GITHUB_OUTPUT" | |
| elif [[ "$main" == "true" ]]; then | |
| echo "backend_scope=--self-contained-system main" >> "$GITHUB_OUTPUT" | |
| echo "backend_label=main only" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "backend_scope=" >> "$GITHUB_OUTPUT" | |
| echo "backend_label=full backend (default — no backend paths matched)" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Print Scope | |
| run: echo "Backend scope - ${{ steps.scope.outputs.backend_label }}" | |
| code-linting: | |
| name: Code Linting | |
| needs: detect-changes | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js Environment | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - name: Install Node Modules | |
| working-directory: application | |
| run: npm ci | |
| - name: Setup .NET Core SDK | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| global-json-file: application/global.json | |
| - name: Restore .NET Tools | |
| working-directory: application | |
| run: dotnet tool restore | |
| - name: Restore .NET Dependencies | |
| working-directory: application | |
| run: dotnet restore | |
| - name: Build Backend Solution | |
| working-directory: developer-cli | |
| run: dotnet run -- build --backend ${{ needs.detect-changes.outputs.backend_scope }} --quiet | |
| - name: Run Backend Linting | |
| working-directory: developer-cli | |
| run: | | |
| dotnet run lint --backend ${{ needs.detect-changes.outputs.backend_scope }} --no-build | tee lint-output.log | |
| if ! grep -q "No backend issues found!" lint-output.log; then | |
| echo "Code linting issues found." | |
| exit 1 | |
| fi | |
| - name: Build Frontend Artifacts | |
| working-directory: application | |
| run: npm run build | |
| - name: Run Frontend Linting | |
| working-directory: developer-cli | |
| run: dotnet run -- lint --frontend | |
| - name: Run Frontend Format Check | |
| working-directory: developer-cli | |
| run: | | |
| dotnet run -- format --frontend | |
| git diff --exit-code || { | |
| echo "Formatting issues detected. Please run 'dotnet run --project developer-cli -- format --frontend' locally and commit the formatted code." | |
| exit 1 | |
| } | |
| code-formatting: | |
| name: Code Formatting | |
| needs: detect-changes | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js Environment | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - name: Install Node Modules | |
| working-directory: application | |
| run: npm ci | |
| - name: Setup .NET Core SDK | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| global-json-file: application/global.json | |
| - name: Restore .NET Tools | |
| working-directory: application | |
| run: dotnet tool restore | |
| - name: Restore .NET Dependencies | |
| working-directory: application | |
| run: dotnet restore | |
| - name: Build Backend Solution | |
| working-directory: developer-cli | |
| run: dotnet run -- build --backend ${{ needs.detect-changes.outputs.backend_scope }} --quiet | |
| - name: Check for Code Formatting Issues | |
| working-directory: developer-cli | |
| run: | | |
| dotnet run format --backend ${{ needs.detect-changes.outputs.backend_scope }} --no-build | |
| git diff --exit-code || { | |
| echo "Formatting issues detected. Please run 'dotnet run --project developer-cli -- format --backend ${{ needs.detect-changes.outputs.backend_scope }}' locally and commit the formatted code." | |
| exit 1 | |
| } | |
| sonarcloud: | |
| name: SonarCloud Analysis | |
| needs: detect-changes | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js Environment | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - name: Install Node Modules | |
| working-directory: application | |
| run: npm ci | |
| - name: Setup .NET Core SDK | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| global-json-file: application/global.json | |
| - name: Restore .NET Tools | |
| working-directory: application | |
| run: dotnet tool restore | |
| - name: Restore .NET Dependencies | |
| working-directory: application | |
| run: dotnet restore | |
| - name: Generate and Set User Secret for Token Signing Key | |
| working-directory: application/shared-kernel/SharedKernel | |
| run: | | |
| # Extract UserSecretsId from the .csproj file | |
| USER_SECRETS_ID=$(grep -oP '(?<=<UserSecretsId>).*?(?=</UserSecretsId>)' SharedKernel.csproj) | |
| # Generate a 512-bit key and set it as a user secret that can be use for token signing when running tests | |
| dotnet user-secrets set "authentication-token-signing-key" "$(openssl rand -base64 64)" --id $USER_SECRETS_ID | |
| - name: Setup Java JDK for SonarScanner | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: "microsoft" | |
| java-version: "17" | |
| - name: Build Email Templates | |
| working-directory: application | |
| run: npx turbo run build --filter=@repo/emails | |
| - name: Run SonarCloud Analysis | |
| working-directory: application | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} | |
| run: | | |
| if [[ "${{ vars.SONAR_PROJECT_KEY }}" == "" ]] || [[ "${{ vars.SONAR_ORGANIZATION }}" == "" ]] || [[ "${{ secrets.SONAR_TOKEN }}" == "" ]]; then | |
| echo "SonarCloud is not enabled. Skipping SonarCloud analysis." | |
| exit 0 | |
| fi | |
| dotnet sonarscanner begin /k:"${{ vars.SONAR_PROJECT_KEY }}" /o:"${{ vars.SONAR_ORGANIZATION }}" /d:sonar.host.url="https://sonarcloud.io" && | |
| dotnet build PlatformPlatform.slnx --no-restore && | |
| dotnet test PlatformPlatform.slnx --no-build && | |
| dotnet sonarscanner end |