chore(release): check #11
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: Reusable CI Checks | ||
| on: | ||
| workflow_dispatch: | ||
| workflow_call: | ||
| inputs: | ||
| runall: | ||
| required: false | ||
| type: boolean | ||
| default: false | ||
| base_sha: | ||
| required: false | ||
| type: string | ||
| head_sha: | ||
| required: false | ||
| type: string | ||
| secrets: | ||
| UNITTESTS_APPSETTINGS_DEVELOPMENT: | ||
| required: true | ||
| WASMSTATICCLIENT_APPSETTINGS_DEVELOPMENT: | ||
| required: true | ||
| WASMSERVERHOSTCLIENT_APPSETTINGS_DEVELOPMENT: | ||
| required: true | ||
| WASMSERVERHOST_APPSETTINGS_DEVELOPMENT: | ||
| required: true | ||
| UNITTESTS_APPSETTINGS_PRODUCTION: | ||
| required: true | ||
| WASMSTATICCLIENT_APPSETTINGS_PRODUCTION: | ||
| required: true | ||
| WASMSERVERHOSTCLIENT_APPSETTINGS_PRODUCTION: | ||
| required: true | ||
| WASMSERVERHOST_APPSETTINGS_PRODUCTION: | ||
| required: true | ||
| TEL_GIT_PACKAGES_TOKEN: | ||
| required: true | ||
| env: | ||
| # Permission | ||
| TEL_GIT_PACKAGES_TOKEN: ${{ secrets.TEL_GIT_PACKAGES_TOKEN }} | ||
| # Nuget Set Up | ||
| NUGET_PACKAGES_OUTPUT_PATH: ${{ github.workspace }}/CICDPackageLocation | ||
| LOCAL_PACKAGES_PATH: ${{ github.workspace }}/CICDPackageLocation | ||
| # Build Set Up | ||
| # May need coverlet.collector xplat if using the packaged version to test | ||
| USE_TEL_BLAZOR_COMPONENTS_PROJECT_REFERENCE: true | ||
| # Check Dummy Data | ||
| TELBLAZOR_PACKAGE_VERSION: "0.0.0-ci-checks" | ||
| jobs: | ||
| # Build Package | ||
| # Build Solution useing package | ||
| reuseable-ci-checks-solution-build: | ||
| name: Check solution builds as Release | ||
| runs-on: ubuntu-latest | ||
| continue-on-error: ${{ inputs.runall }} | ||
| outputs: | ||
| status: ${{ job.status }} | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: Setup .NET | ||
| uses: actions/setup-dotnet@v4 | ||
| with: | ||
| global-json-file: global.json | ||
| - name: Replace nuget.config with CI template | ||
| run: | | ||
| rm -f nuget.config | ||
| cp nuget.config.cicd nuget.config | ||
| - name: Replace local environment variable in nuget config because cant provide it as a parameter | ||
| run: | | ||
| sed -i "s|%TEL_BLAZOR_PACKAGE_SOURCE%|$LOCAL_PACKAGES_PATH|g" nuget.config | ||
| - name: Create appsettings development from secrets | ||
| run: | | ||
| declare -A paths | ||
| paths["./TELBlazor.Components.UnitTests/appsettings.Development.json"]='${{ secrets.UNITTESTS_APPSETTINGS_DEVELOPMENT }}' | ||
| paths["./TELBlazor.Components.ShowCase.WasmStaticClient/wwwroot/appsettings.Development.json"]='${{ secrets.WASMSTATICCLIENT_APPSETTINGS_DEVELOPMENT }}' | ||
| paths["./TELBlazor.Components.ShowCase.E2ETests.WasmServerHost/TELBlazor.Components.ShowCase.E2ETests.WasmServerHost.Client/wwwroot/appsettings.Development.json"]='${{ secrets.WASMSERVERHOSTCLIENT_APPSETTINGS_DEVELOPMENT }}' | ||
| paths["./TELBlazor.Components.ShowCase.E2ETests.WasmServerHost/TELBlazor.Components.ShowCase.E2ETests.WasmServerHost/appsettings.Development.json"]='${{ secrets.WASMSERVERHOST_APPSETTINGS_DEVELOPMENT }}' | ||
| paths["./TELBlazor.Components.UnitTests/appsettings.Production.json"]='${{ secrets.UNITTESTS_APPSETTINGS_PRODUCTION }}' | ||
| paths["./TELBlazor.Components.ShowCase.WasmStaticClient/wwwroot/appsettings.Production.json"]='${{ secrets.WASMSTATICCLIENT_APPSETTINGS_PRODUCTION }}' | ||
| paths["./TELBlazor.Components.ShowCase.E2ETests.WasmServerHost/TELBlazor.Components.ShowCase.E2ETests.WasmServerHost.Client/wwwroot/appsettings.Production.json"]='${{ secrets.WASMSERVERHOSTCLIENT_APPSETTINGS_PRODUCTION }}' | ||
| paths["./TELBlazor.Components.ShowCase.E2ETests.WasmServerHost/TELBlazor.Components.ShowCase.E2ETests.WasmServerHost/appsettings.Production.json"]='${{ secrets.WASMSERVERHOST_APPSETTINGS_PRODUCTION }}' | ||
| for path in "${!paths[@]}"; do | ||
| mkdir -p "$(dirname "$path")" | ||
| printf '%s' "${paths[$path]}" > "$path" | ||
| done | ||
| - name: Clean lock files because the newly generated package file will superseed the locks | ||
| run: | | ||
| find . -name "packages.lock.json" -type f -exec rm -f {} \; | ||
| - name: Set up Node.js so we have gulp for retrieving TEL Frontend Css | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| - name: Install npm packages so we have gulp for retrieving TEL Frontend Css | ||
| run: npm ci | ||
| - name: Install wasm-tools workload (wasm-tools used for delinking so can test against optimised client wasm using TELBlazor package) | ||
| run: dotnet workload install wasm-tools --skip-manifest-update --source https://api.nuget.org/v3/index.json | ||
| - name: Build and create package locally | ||
| run: | | ||
| dotnet build TELBlazor.Components -c Release \ | ||
| /p:TELBlazorPackageVersion=$TELBLAZOR_PACKAGE_VERSION \ | ||
| /p:NugetPackagesOutputPath=$NUGET_PACKAGES_OUTPUT_PATH \ | ||
| /p:UseTELBlazorComponentsProjectReference=$USE_TEL_BLAZOR_COMPONENTS_PROJECT_REFERENCE \ | ||
| /p:DisablePackageGeneration=false | ||
| - name: Build solution without generating new package | ||
| run: | | ||
| dotnet build TELBlazor.sln -c Release \ | ||
| /p:TELBlazorPackageVersion=$TELBLAZOR_PACKAGE_VERSION \ | ||
| /p:NugetPackagesOutputPath=$NUGET_PACKAGES_OUTPUT_PATH \ | ||
| /p:UseTELBlazorComponentsProjectReference=$USE_TEL_BLAZOR_COMPONENTS_PROJECT_REFERENCE \ | ||
| /p:DisablePackageGeneration=true | ||
| reuseable-ci-checks-branch-name-check: | ||
| name: Check branch names | ||
| if: success() || failure() | ||
| continue-on-error: ${{ inputs.runall }} | ||
| outputs: | ||
| status: ${{ job.status }} | ||
| runs-on: ubuntu-latest | ||
| # Checkout so can get access to the file | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
| steps: | ||
| - name: Validate Branch Name | ||
| run: | | ||
| echo "📂 GITHUB_WORKSPACE is: $GITHUB_WORKSPACE" | ||
| echo "📂 Current working directory is: $(pwd)" | ||
| echo "📂 Listing files in current dir:" | ||
| ls | ||
| ls -alh | ||
| echo "📂 Listing files in workspace root:" | ||
| ls -alh "$GITHUB_WORKSPACE" | ||
| #BRANCH_NAME="${GITHUB_HEAD_REF}" | ||
| BRANCH_NAME="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}" | ||
| echo "Validating branch name: $BRANCH_NAME" | ||
| # Read allowed branch patterns from .releaserc.json | ||
| RELEASERC_PATH="${{ github.workspace }}/.releaserc.json" | ||
| echo "Using releaserc at: $RELEASERC_PATH" | ||
| ALLOWED_BRANCHES=$(jq -r '.branches[].name' $RELEASERC_PATH) | ||
| VALID=false | ||
| for pattern in $ALLOWED_BRANCHES; do | ||
| # Convert wildcard * into regex | ||
| REGEX="^${pattern//\*/.*}$" | ||
| if [[ "$BRANCH_NAME" =~ $REGEX ]]; then | ||
| VALID=true | ||
| break | ||
| fi | ||
| done | ||
| # Always allow dependabot branches for CI | ||
| # Semver will ignore the branch but will bump the collected dependabot changes branch | ||
| if [[ "$BRANCH_NAME" =~ ^dependabot/ ]]; then | ||
| echo "✅ Branch is a dependabot branch its not for release or versioning but for merging into the dependabot collection branch" | ||
| VALID=true | ||
| fi | ||
| if [ "$VALID" = true ]; then | ||
| echo "✅ Branch name is valid" | ||
| else | ||
| echo "❌ Invalid branch name: $BRANCH_NAME" | ||
| echo "Allowed branch patterns:" | ||
| echo "$ALLOWED_BRANCHES" | ||
| exit 1 | ||
| fi | ||
| # qqqq drop | ||
| # if [[ "$BRANCH_NAME" =~ ^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test|sample|security|config|bugfix|hotfix)-[a-zA-Z0-9._/-]+$ ]] || [[ "$BRANCH_NAME" == "master" ]]; then | ||
| # echo "✅ Branch name is valid" | ||
| # else | ||
| # echo "❌ Invalid branch name: $BRANCH_NAME" | ||
| # echo "Branch names must follow one of the allowed prefixes:" | ||
| # echo " build-*, feat-*, fix-*, bugfix-*, hotfix-*, build-*, chore-*, ci-*, docs-*, perf-*, refactor-*, revert-*, style-*, test-*, sample-*, security-*, config-*, bugfix-*, hotfix-*" | ||
| # exit 1 | ||
| # fi | ||
| reuseable-ci-checks-commitlint: | ||
| name: Check commit names | ||
| runs-on: ubuntu-latest | ||
| if: success() || failure() | ||
| continue-on-error: ${{ inputs.runall }} | ||
| outputs: | ||
| status: ${{ job.status }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| - uses: wagoid/commitlint-github-action@v5 | ||
| with: | ||
| configFile: .commitlintrc.json | ||
| # Only set from/to if inputs are provided, otherwise let action use defaults | ||
| from: ${{ inputs.base_sha != '' && inputs.base_sha || null }} | ||
| to: ${{ inputs.head_sha != '' && inputs.head_sha || null }} | ||
| reuseable-ci-e2e-unit-tests: | ||
| name: E2E Unit threshold and code report trigger | ||
| timeout-minutes: 60 | ||
| runs-on: ubuntu-latest | ||
| if: success() || failure() | ||
| continue-on-error: ${{ inputs.runall }} | ||
| outputs: | ||
| status: ${{ job.status }} | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: Setup .NET | ||
| uses: actions/setup-dotnet@v4 | ||
| with: | ||
| global-json-file: global.json | ||
| - name: Replace nuget.config with CI template | ||
| run: | | ||
| rm -f nuget.config | ||
| cp nuget.config.cicd nuget.config | ||
| - name: Replace local environment variable in nuget config because cant provide it as a parameter | ||
| run: | | ||
| sed -i "s|%TEL_BLAZOR_PACKAGE_SOURCE%|$LOCAL_PACKAGES_PATH|g" nuget.config | ||
| - name: Clean lock files because the newly generated package file will superseed the locks | ||
| run: | | ||
| find . -name "packages.lock.json" -type f -exec rm -f {} \; | ||
| - name: Create appsettings development from secrets | ||
| run: | | ||
| declare -A paths | ||
| paths["./TELBlazor.Components.UnitTests/appsettings.Development.json"]='${{ secrets.UNITTESTS_APPSETTINGS_DEVELOPMENT }}' | ||
| paths["./TELBlazor.Components.ShowCase.WasmStaticClient/wwwroot/appsettings.Development.json"]='${{ secrets.WASMSTATICCLIENT_APPSETTINGS_DEVELOPMENT }}' | ||
| paths["./TELBlazor.Components.ShowCase.E2ETests.WasmServerHost/TELBlazor.Components.ShowCase.E2ETests.WasmServerHost.Client/wwwroot/appsettings.Development.json"]='${{ secrets.WASMSERVERHOSTCLIENT_APPSETTINGS_DEVELOPMENT }}' | ||
| paths["./TELBlazor.Components.ShowCase.E2ETests.WasmServerHost/TELBlazor.Components.ShowCase.E2ETests.WasmServerHost/appsettings.Development.json"]='${{ secrets.WASMSERVERHOST_APPSETTINGS_DEVELOPMENT }}' | ||
| paths["./TELBlazor.Components.UnitTests/appsettings.Production.json"]='${{ secrets.UNITTESTS_APPSETTINGS_PRODUCTION }}' | ||
| paths["./TELBlazor.Components.ShowCase.WasmStaticClient/wwwroot/appsettings.Production.json"]='${{ secrets.WASMSTATICCLIENT_APPSETTINGS_PRODUCTION }}' | ||
| paths["./TELBlazor.Components.ShowCase.E2ETests.WasmServerHost/TELBlazor.Components.ShowCase.E2ETests.WasmServerHost.Client/wwwroot/appsettings.Production.json"]='${{ secrets.WASMSERVERHOSTCLIENT_APPSETTINGS_PRODUCTION }}' | ||
| paths["./TELBlazor.Components.ShowCase.E2ETests.WasmServerHost/TELBlazor.Components.ShowCase.E2ETests.WasmServerHost/appsettings.Production.json"]='${{ secrets.WASMSERVERHOST_APPSETTINGS_PRODUCTION }}' | ||
| for path in "${!paths[@]}"; do | ||
| mkdir -p "$(dirname "$path")" | ||
| printf '%s' "${paths[$path]}" > "$path" | ||
| done | ||
| - name: Set up Node.js so we have gulp for retrieving TEL Frontend Css | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| - name: Install npm packages so we have gulp for retrieving TEL Frontend Css | ||
| run: npm ci | ||
| - name: Install ReportGenerator | ||
| run: dotnet tool restore | ||
| - name: Install wasm-tools workload (wasm-tools used for delinking so can test against optimised client wasm using TELBlazor package) | ||
| run: dotnet workload install wasm-tools --skip-manifest-update --source https://api.nuget.org/v3/index.json | ||
| - name: Build and create package locally | ||
| run: | | ||
| dotnet build TELBlazor.Components -c Release \ | ||
| /p:TELBlazorPackageVersion=$TELBLAZOR_PACKAGE_VERSION \ | ||
| /p:NugetPackagesOutputPath=$NUGET_PACKAGES_OUTPUT_PATH \ | ||
| /p:UseTELBlazorComponentsProjectReference=$USE_TEL_BLAZOR_COMPONENTS_PROJECT_REFERENCE \ | ||
| /p:DisablePackageGeneration=false | ||
| - name: Build solution without generating new package | ||
| run: | | ||
| dotnet build TELBlazor.sln -c Release \ | ||
| /p:TELBlazorPackageVersion=$TELBLAZOR_PACKAGE_VERSION \ | ||
| /p:NugetPackagesOutputPath=$NUGET_PACKAGES_OUTPUT_PATH \ | ||
| /p:UseTELBlazorComponentsProjectReference=$USE_TEL_BLAZOR_COMPONENTS_PROJECT_REFERENCE \ | ||
| /p:DisablePackageGeneration=true | ||
| - name: Ensure browsers are installed | ||
| run: pwsh TELBlazor.Components.ShowCase.E2ETests/bin/Release/net8.0/playwright.ps1 install --with-deps | ||
| - name: Run tests with coverage threshold check | ||
| id: unit_e2e_tests | ||
| run: | | ||
| dotnet test --no-build --no-restore -c Release \ | ||
| /p:TELBlazorPackageVersion=$TELBLAZOR_PACKAGE_VERSION \ | ||
| /p:NugetPackagesOutputPath=$NUGET_PACKAGES_OUTPUT_PATH \ | ||
| /p:UseTELBlazorComponentsProjectReference=$USE_TEL_BLAZOR_COMPONENTS_PROJECT_REFERENCE \ | ||
| /p:DisablePackageGeneration=true | ||
| continue-on-error: true | ||
| - name: Generate Coverage Report | ||
| run: | | ||
| dotnet reportgenerator \ | ||
| -reports:"**/AllTestResults/**/coverage.cobertura.xml" \ | ||
| -targetdir:CoverageReport \ | ||
| -reporttypes:"Html;XmlSummary" | ||
| - name: Upload coverage report | ||
| if: always() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: coverage-report | ||
| path: CoverageReport | ||
| - name: Get artifact location | ||
| env: | ||
| # requires local set env | ||
| GH_TOKEN: ${{ secrets.TEL_GIT_PACKAGES_TOKEN }} | ||
| run: | | ||
| # Get the artifact list for the current workflow run | ||
| ARTIFACT_LIST=$(gh api "repos/TechnologyEnhancedLearning/TELBlazor/actions/runs/${GITHUB_RUN_ID}/artifacts") | ||
| # Echo the entire artifact list for debugging purposes | ||
| echo "Artifact List: $ARTIFACT_LIST" | ||
| ARTIFACT_URL=$(echo "$ARTIFACT_LIST" | jq -r '.artifacts[] | select(.name=="coverage-report") | .url') | ||
| # Echo the artifact URL to confirm | ||
| echo "Artifact URL: $ARTIFACT_URL" | ||
| echo "artifact_url=$ARTIFACT_URL" >> $GITHUB_ENV | ||
| - name: Trigger workflow in TELBlazor-CodeReport repo | ||
| run: | | ||
| repo_owner="TechnologyEnhancedLearning" | ||
| repo_name="TELBlazor-CodeReport" | ||
| event_type="artifact_ready" | ||
| # Trigger the workflow | ||
| curl -L \ | ||
| -X POST \ | ||
| -H "Accept: application/vnd.github+json" \ | ||
| -H "Authorization: Bearer $TEL_GIT_PACKAGES_TOKEN" \ | ||
| -H "X-GitHub-Api-Version: 2022-11-28" \ | ||
| https://api.github.com/repos/$repo_owner/$repo_name/dispatches \ | ||
| -d "{\"event_type\": \"$event_type\", \"client_payload\": {\"artifact_url\": \"$artifact_url\"}}" | ||
| - name: Fail job if test failed after report is generated | ||
| if: steps.unit_e2e_tests.outcome != 'success' | ||
| run: | | ||
| echo "{{steps.unit_e2e_tests.outcome }}" | ||
| echo "❌ One or more steps failed." | ||
| exit 1 | ||
| reuseable-ci-checks-check-for-failed-jobs: | ||
| name: Check for failures | ||
| if: ${{ inputs.runall }} | ||
| needs: | ||
| - reuseable-ci-checks-solution-build | ||
| - reuseable-ci-checks-branch-name-check | ||
| - reuseable-ci-checks-commitlint | ||
| - reuseable-ci-e2e-unit-tests | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Check Job Results | ||
| run: | | ||
| echo "Solution Build: ${{ needs.reuseable-ci-checks-solution-build.outputs.status }}" | ||
| echo "Branch Name Check: ${{ needs.reuseable-ci-checks-branch-name-check.outputs.status }}" | ||
| echo "Commit Lint Check: ${{ needs.reuseable-ci-checks-commitlint.outputs.status }}" | ||
| echo "Tests: ${{ needs.reuseable-ci-e2e-unit-tests.outputs.status }}" | ||
| # Check if any job is not success (failure, cancelled, skipped) | ||
| if [[ "${{ needs.reuseable-ci-checks-solution-build.outputs.status }}" != "success" || \ | ||
| "${{ needs.reuseable-ci-checks-branch-name-check.outputs.status }}" != "success" || \ | ||
| "${{ needs.reuseable-ci-checks-commitlint.outputs.status }}" != "success" || \ | ||
| "${{ needs.reuseable-ci-e2e-unit-tests.outputs.status }}" != "success" ]]; then | ||
| echo "❌ One or more jobs failed." | ||
| exit 1 | ||
| fi | ||
| continue-on-error: false | ||