From b2f903eefe986d5439552c70a2394219e2448a49 Mon Sep 17 00:00:00 2001 From: James Dawson Date: Tue, 10 Sep 2024 11:31:48 +0100 Subject: [PATCH] Additional options for running the standardised build process (#50) - New reusable workflow that runs the standardised build process using a single job - New composite action that encapsulates the standardised build process --- .github/workflows/ci-composite-action.yml | 62 +++++ .github/workflows/ci-matrix.yml | 4 + .github/workflows/ci-single-job.yml | 62 +++++ .github/workflows/ci.yml | 4 + .../scripted-build-single-job-pipeline.yml | 94 ++++++++ README.md | 98 ++++++-- actions/run-build-process/action.yml | 212 ++++++++++++++++++ actions/run-scripted-build/action.yml | 2 + 8 files changed, 525 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/ci-composite-action.yml create mode 100644 .github/workflows/ci-single-job.yml create mode 100644 .github/workflows/scripted-build-single-job-pipeline.yml create mode 100644 actions/run-build-process/action.yml diff --git a/.github/workflows/ci-composite-action.yml b/.github/workflows/ci-composite-action.yml new file mode 100644 index 0000000..bf61d04 --- /dev/null +++ b/.github/workflows/ci-composite-action.yml @@ -0,0 +1,62 @@ +name: ci-compositie-action +on: + pull_request: + branches: + - main + paths: + - .github/workflows/ci-composite-action.yml + - actions/** + workflow_dispatch: + inputs: + forcePublish: + description: When true the Publish stage will always be run, otherwise it only runs for tagged versions. + required: false + default: false + type: boolean + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + actions: write # enable cache clean-up + checks: write # enable test result annotations + contents: write # enable creating releases + issues: read + packages: write # enable publishing packages + pull-requests: write # enable test result annotations + +jobs: + build: + name: Build + runs-on: ubuntu-latest + outputs: + semver: ${{ steps.run_build.outputs.semver }} + major: ${{ steps.run_build.outputs.major }} + majorMinor: ${{ steps.run_build.outputs.majorMinor }} + preReleaseTag: ${{ steps.run_build.outputs.preReleaseTag }} + + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1 + with: + fetch-depth: 0 + - uses: ./actions/prepare-env-vars-and-secrets + id: prepareEnvVarsAndSecrets + with: + environmentVariablesYaml: | + BUILDVAR_NuGetPublishSource: "${{ startsWith(github.ref, 'refs/tags/') && 'https://api.nuget.org/v3/index.json' || 'https://nuget.pkg.github.com/endjin/index.json' }}" + secretsYaml: | + NUGET_API_KEY: "${{ startsWith(github.ref, 'refs/tags/') && secrets.ENDJIN_NUGET_APIKEY || secrets.ENDJIN_GITHUB_PUBLISHER_PAT }}" + SBOM_ANALYSIS_RELEASE_READER_PAT: "${{ secrets.ENDJIN_GITHUB_READER_PAT }}" + - uses: ./actions/run-build-process + id: run_build + with: + netSdkVersion: '8.x' + # workflow_dispatch inputs are always strings, the type property is just for the UI + forcePublish: ${{ github.event.inputs.forcePublish == 'true' }} + sbomOutputStorageAccountName: ${{ vars.SBOM_OUTPUT_STORAGE_ACCOUNT_NAME }} + sbomOutputStorageContainerName: ${{ vars.SBOM_OUTPUT_STORAGE_CONTAINER_NAME }} + buildEnv: ${{ steps.prepareEnvVarsAndSecrets.outputs.environmentVariablesYamlBase64}} + buildSecrets: ${{ steps.prepareEnvVarsAndSecrets.outputs.secretsYamlBase64 }} + token: ${{ secrets.GITHUB_TOKEN }} + diff --git a/.github/workflows/ci-matrix.yml b/.github/workflows/ci-matrix.yml index 9c3ec3e..f2fbb55 100644 --- a/.github/workflows/ci-matrix.yml +++ b/.github/workflows/ci-matrix.yml @@ -3,6 +3,10 @@ on: pull_request: branches: - main + paths: + - .github/workflows/ci-matrix.yml + - .github/workflows/scripted-build-matrix-pipeline.yml + - actions/** workflow_dispatch: inputs: forcePublish: diff --git a/.github/workflows/ci-single-job.yml b/.github/workflows/ci-single-job.yml new file mode 100644 index 0000000..9969d9f --- /dev/null +++ b/.github/workflows/ci-single-job.yml @@ -0,0 +1,62 @@ +name: ci-single-job +on: + pull_request: + branches: + - main + paths: + - .github/workflows/ci-single-job.yml + - .github/workflows/scripted-build-single-job-pipeline.yml + - actions/** + workflow_dispatch: + inputs: + forcePublish: + description: When true the Publish stage will always be run, otherwise it only runs for tagged versions. + required: false + default: false + type: boolean + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + actions: write # enable cache clean-up + checks: write # enable test result annotations + contents: write # enable creating releases + issues: read + packages: write # enable publishing packages + pull-requests: write # enable test result annotations + +jobs: + prepareConfig: + name: Prepare Configuration + runs-on: ubuntu-latest + outputs: + RESOLVED_ENV_VARS: ${{ steps.prepareEnvVarsAndSecrets.outputs.environmentVariablesYamlBase64 }} + RESOLVED_SECRETS: ${{ steps.prepareEnvVarsAndSecrets.outputs.secretsYamlBase64 }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + + # Declare any environment variables and/or secrets that need to be available inside the build process + - uses: ./actions/prepare-env-vars-and-secrets + id: prepareEnvVarsAndSecrets + with: + environmentVariablesYaml: | + BUILDVAR_NuGetPublishSource: "${{ startsWith(github.ref, 'refs/tags/') && 'https://api.nuget.org/v3/index.json' || 'https://nuget.pkg.github.com/endjin/index.json' }}" + secretsYaml: | + NUGET_API_KEY: "${{ startsWith(github.ref, 'refs/tags/') && secrets.ENDJIN_NUGET_APIKEY || secrets.ENDJIN_GITHUB_PUBLISHER_PAT }}" + SBOM_ANALYSIS_RELEASE_READER_PAT: "${{ secrets.ENDJIN_GITHUB_READER_PAT }}" + + build: + needs: prepareConfig + uses: ./.github/workflows/scripted-build-single-job-pipeline.yml + with: + netSdkVersion: '8.x' + # workflow_dispatch inputs are always strings, the type property is just for the UI + forcePublish: ${{ github.event.inputs.forcePublish == 'true' }} + buildEnv: ${{ needs.prepareConfig.outputs.RESOLVED_ENV_VARS }} + secrets: + buildAzureCredentials: ${{ secrets.ENDJIN_PROD_ACR_READER_CREDENTIALS }} + buildSecrets: ${{ needs.prepareConfig.outputs.RESOLVED_SECRETS }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee51068..b856dea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,10 @@ on: pull_request: branches: - main + paths: + - .github/workflows/ci.yml + - .github/workflows/scripted-build-pipeline.yml + - actions/** workflow_dispatch: inputs: forcePublish: diff --git a/.github/workflows/scripted-build-single-job-pipeline.yml b/.github/workflows/scripted-build-single-job-pipeline.yml new file mode 100644 index 0000000..6b9faee --- /dev/null +++ b/.github/workflows/scripted-build-single-job-pipeline.yml @@ -0,0 +1,94 @@ +on: + workflow_call: + inputs: + netSdkVersion: + description: The primary .NET SDK version required for the build process, as per the syntax required by the 'setup-dotnet' action. + required: true + type: string + default: '8.0.x' + additionalNetSdkVersion: + description: An additional .NET SDK version required for the build process, as per the syntax required by the 'setup-dotnet' action. + required: false + type: string + pythonVersion: + description: Specify an additional Python version required for the build process + required: false + type: string + configuration: + description: The target build configuration. + required: false + default: 'Release' + type: string + buildEnv: + description: A JSON object representing the environment variables required when running the build script. + required: false + type: string + buildArtifactName: + description: If set, during the test phase, uploads a GitHub artifact with the provided name (path must be specified in `artifactPath`) + required: false + type: string + buildArtifactPath: + description: If set, during the test phase, uploads a GitHub artifact with the provided path (name must be specified in `artifactName`). The path can be a file, directory or wildcard pattern; multiple paths can be specified using newline demiliter. + required: false + type: string + forcePublish: + description: When true, the Publish stage will be run regardless of the current branch or tag. + required: false + default: false + type: boolean + buildScriptPath: + description: The path to the build script to run. + required: false + default: ./build.ps1 + type: string + buildTasks: + description: The tasks that need to be run as part of the build process, formatted as a comma-delimited string (e.g. 'FullBuild' or 'Build,Test'). + required: false + default: '' + type: string + runsOn: + description: The operating system to run all stages of this workflow. + required: false + default: ubuntu-latest + type: string + + secrets: + buildAzureCredentials: + required: false + buildSecrets: + description: A YAML string representing a dictionary of secrets required when running the 'compile' stage of this workflow. + required: false + +jobs: + build: + name: Build + runs-on: ${{ inputs.runsOn }} + outputs: + semver: ${{ steps.run_build.outputs.semver }} + major: ${{ steps.run_build.outputs.major }} + majorMinor: ${{ steps.run_build.outputs.majorMinor }} + preReleaseTag: ${{ steps.run_build.outputs.preReleaseTag }} + + steps: + - uses: endjin/Endjin.RecommendedPractices.GitHubActions/actions/run-build-process@main + id: run_build + with: + netSdkVersion: ${{ inputs.netSdkVersion }} + additionalNetSdkVersion: ${{ inputs.additionalNetSdkVersion }} + buildArtifactName: ${{ inputs.buildArtifactName }} + buildArtifactPath: ${{ inputs.buildArtifactPath }} + buildScriptPath: ${{ inputs.buildScriptPath }} + buildTasks: ${{ inputs.buildTasks }} + codeCoverageSummaryDir: ${{ vars.CODE_COVERAGE_SUMMARY_DIR || '_codeCoverage' }} + codeCoverageSummaryFile: ${{ vars.CODE_COVERAGE_SUMMARY_FILE || 'SummaryGithub.md' }} + configuration: ${{ inputs.configuration }} + pythonVersion: ${{ inputs.pythonVersion }} + runsOn: ${{ inputs.runsOn }} + # workflow_dispatch inputs are always strings, the type property is just for the UI + forcePublish: ${{ github.event.inputs.forcePublish == 'true' }} + sbomOutputStorageAccountName: ${{ vars.SBOM_OUTPUT_STORAGE_ACCOUNT_NAME }} + sbomOutputStorageContainerName: ${{ vars.SBOM_OUTPUT_STORAGE_CONTAINER_NAME }} + buildEnv: ${{ inputs.buildEnv }} + buildSecrets: ${{ secrets.buildSecrets }} + buildAzureCredentials: ${{ secrets.buildAzureCredentials }} + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 0342b60..1ff70e4 100644 --- a/README.md +++ b/README.md @@ -2,32 +2,104 @@ This repository contains [re-usable GitHub Action workflows](https://docs.github.com/en/actions/using-workflows/reusing-workflows) and [composite actions](https://docs.github.com/en/actions/creating-actions/creating-a-composite-action) for our standardised CI processes. +Our standardised build process is divided into the following phases: +- Compile +- Test +- Analyse +- Package +- Publish + +By default, the 'Publish' phase is only executed for tagged versions or when manually triggered with the 'Force Publish' option enabled. + +> ***USAGE TIP**: For smaller/less complex repositories, you will likely get the quickest build times by using the `run-build-process` composite action, an example of how to consume this in your repo's `build.yml` can be found [here](.github/workflows/ci-composite-action.yml)*. + ## Reusable Workflows + +### Multi-Job Workflows +These run the logical phases of the build process using discrete jobs, which can be beneficial for large builds due to the parallelisation when running tests and building packages. + - `scripted-build-pipeline` - encapsulates our standard CI build process, using separate jobs for Compile, Test, Package & Publish phases - `scripted-build-matrix-pipeline` - as above, except the Test phase includes [matrix](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow) support +The diagram below shows the high-level process that the non-matrix multi-job workflow implements: + +```mermaid +graph LR + compile["Compile"]-->analyse["Code Analysis"] + analyse-->test["Run Tests"] + test-->pubtests["Publish Test Results"] + analyse-->package["Build Packages"] + pubtests-->publish["Publish Packages"] + package-->publish +``` + +The diagram below illustrates the different high-level process for the matrix-enabled version of the multi-job workflow: + +```mermaid +graph LR + compile["Compile"]-->analyse["Code Analysis"] + analyse-->test1["Run Tests (matrix 1)"] + analyse-->test2["Run Tests (matrix 2)"] + test1-->pubtests["Publish Test Results"] + test2-->pubtests["Publish Test Results"] + analyse-->package["Build Packages"] + pubtests-->publish["Publish Packages"] + package-->publish +``` + + +### Single-Job Workflow +This runs the logical phases of the build process as a single job, closely mimicking the local developer build. + +***NOTE**: A consuming build will still require a second job in order to support passing arbitrary environment variables and secrets to this workflow. See the [example](.github/workflows/ci-single-job.yml) for more details.* + +- `scripted-build-single-job-pipeline` - encapsulates our standard CI build process, using a single job + +This diagram shows the default sequence of the build process implemented by the single-job workflow implement (NOTE: This can altered by overriding the `buildTasks` input parameter): + +```mermaid +graph LR + compile["Compile"]-->test["Run Tests"] + test-->analyse["Code Analysis"] + analyse-->package["Build Packages"] + package-->publish["Publish Packages"] + publish-->pubtests["Publish Test Results"] +``` + + ## Composite Actions + +### Orchestration Composite Actions +This are used as alternatives to reusable workflows to encapsulate complete processes. + +- `run-build-process` - provides an alternative to using the reusable workflows and encapsulates the complete build process. This allows the consuming CI build to be run a single job, with the trade-off of requiring somewhat more boilerplate. + +The `run-build-process` action implements the same logical build process as the [Single-Job Workflow](#single-job-workflows) (NOTE: This can altered by overriding the `buildTasks` input parameter) + +```mermaid +graph LR + compile["Compile"]-->test["Run Tests"] + test-->analyse["Code Analysis"] + analyse-->package["Build Packages"] + package-->publish["Publish Packages"] + publish-->pubtests["Publish Test Results"] +``` + + +### Feature Composite Actions +These composite actions are used to encapsulated specific functionality so it can be easily re-used between workflows. + - `prepare-env-vars-and-secrets` - provides a workaround for not natively being able to pass arbitrary environment variables and secrets to a reusable workflow. Based on assembling the required values into 2 well-known variables that act as containers for the variables and secrets that need to be passed. - `run-scripted-build` - encapsulates the steps for executing our [PowerShell-based build tooling](https://www.powershellgallery.com/packages/Endjin.RecommendedPractices.Build) - typically used via one of the above reusable workflows. - `set-env-vars-and-secrets` - the consuming side of the workaround for passing arbitrary environment variables and secrets. Unwraps the bundled environment variables and secrets so they are available to the running workflow. ## Examples -The following serve as examples of using the reusable workflows found in this repo: +The following workflows serve as examples of how to consume the different reusable workflows and composite actions found in this repo: - [ci.yml](.github/workflows/ci.yml) - used for validating changes to the `scripted-build-pipeline` reusable workflow - [ci-matrix.yml](.github/workflows/ci-matrix.yml) - used for validating changes to the `scripted-build-matrix-pipeline` reusable workflow +- [ci-single-job.yml](.github/workflows/ci-single-job.yml) - used for validating changes to the `scripted-build-single-job-pipeline` reusable workflow +- [ci-composite-action](.github/workflows/ci-composite-action.yml) - used for validating change to the `run-build-process` composite action -## CI Build Process Overview -The diagram below illustrates the high-level process that workflows implementing our standard CI build use: - -```mermaid -graph LR - compile["Compile"]-->analyse["Code Analysis"] - analyse-->test["Run Tests"] - test-->pubtests["Publish Test Results"] - analyse-->package["Build Packages"] - pubtests-->publish["Publish Packages"] - package-->publish -``` \ No newline at end of file diff --git a/actions/run-build-process/action.yml b/actions/run-build-process/action.yml new file mode 100644 index 0000000..aa7d194 --- /dev/null +++ b/actions/run-build-process/action.yml @@ -0,0 +1,212 @@ +name: 'Endjin.RecommendedPractices.Build.RunBuildProcess' +description: 'Runs the standardised build process' +inputs: + netSdkVersion: + description: The primary .NET SDK version required for the build process, as per the syntax required by the 'setup-dotnet' action. + required: true + default: '8.0.x' + additionalNetSdkVersion: + description: An additional .NET SDK version required for the build process, as per the syntax required by the 'setup-dotnet' action. + required: false + pythonVersion: + description: Specify an additional Python version required for the build process + required: false + configuration: + description: The target build configuration. + required: false + default: 'Release' + buildEnv: + description: A JSON object representing the environment variables required when running the build script. + required: false + buildArtifactName: + description: If set, during the test phase, uploads a GitHub artifact with the provided name (path must be specified in `artifactPath`) + required: false + buildArtifactPath: + description: If set, during the test phase, uploads a GitHub artifact with the provided path (name must be specified in `artifactName`). The path can be a file, directory or wildcard pattern; multiple paths can be specified using newline demiliter. + required: false + forcePublish: + description: When true, the Publish stage will be run regardless of the current branch or tag. + required: false + default: 'false' + buildScriptPath: + description: The path to the build script to run. + required: false + default: ./build.ps1 + buildTasks: + description: The tasks that need to be run as part of the build process, formatted as a comma-delimited string (e.g. 'FullBuild' or 'Build,Test'). + required: false + default: '' + runsOn: + description: The operating system to run all stages of this workflow. + required: false + default: ubuntu-latest + # Secrets + buildAzureCredentials: + description: A secret containing the Azure credentials required to run the build process. + required: false + buildSecrets: + description: A YAML string representing a dictionary of secrets required when running the 'compile' stage of this workflow. + required: false + token: + description: 'A GitHub token' + required: true + codeCoverageSummaryDir: + description: 'The directory where the code coverage summary file is stored' + required: false + default: '_codeCoverage' + codeCoverageSummaryFile: + description: 'The name of the code coverage summary file' + required: false + default: 'SummaryGithub.md' + sbomOutputStorageAccountName: + description: 'The name of the storage account where the SBOM output will be stored' + required: false + sbomOutputStorageContainerName: + description: 'The name of the storage container where the SBOM output will be stored' + required: false + +outputs: + semver: + description: "The full SemVer version number of the current build" + value: ${{ steps.run_script.outputs.SemVer }} + major: + description: "The major version component of the current build" + value: ${{ steps.run_script.outputs.Major }} + majorMinor: + description: "The major & minor components of the current build" + value: ${{ steps.run_script.outputs.Major }}.${{ steps.run_script.outputs.Minor }} + preReleaseTag: + description: "The pre-release tag, if any, of the current build" + value: ${{ steps.run_script.outputs.PreReleaseTag }} + +runs: + using: "composite" + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1 + with: + fetch-depth: 0 + submodules: true + - uses: endjin/Endjin.RecommendedPractices.GitHubActions/actions/set-env-vars-and-secrets@main + with: + environmentVariablesYamlBase64: ${{ inputs.buildEnv}} + secretsYamlBase64: ${{ inputs.buildSecrets}} + - name: Set defaults + id: set_defaults + run: | + echo "CODE_COVERAGE_SUMMARY_FILE=${{ inputs.codeCoverageSummaryDir || '_codeCoverage' }}" >> $GITHUB_ENV + echo "CODE_COVERAGE_SUMMARY_FILE=${{ inputs.codeCoverageSummaryFile || 'SummaryGithub.md' }}" >> $GITHUB_ENV + echo "DEFAULT_BUILD_TASKS=${{ (inputs.forcePublish == 'true' || startsWith(github.ref, 'refs/tags/')) && 'FullBuildAndPublish' || 'FullBuild' }}" >> $GITHUB_ENV + shell: bash + - name: Debug Variables + if: env.ACTIONS_RUNNER_DEBUG == 'true' + run: | + gci env:/ | fl | out-string | Write-Host + shell: pwsh + - name: Check if buildAzureCredentials secret is set + id: buildAzureCredentials_secret_check + shell: bash + run: | + if [ "${{ inputs.buildAzureCredentials }}" != '' ]; then + echo "available=true" >> $GITHUB_OUTPUT; + else + echo "available=false" >> $GITHUB_OUTPUT; + fi + - name: Azure CLI login + if: ${{ steps.buildAzureCredentials_secret_check.outputs.available == 'true' }} + uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # v2.1.1 + with: + creds: ${{ inputs.buildAzureCredentials }} + enable-AzPSSession: true + - uses: endjin/Endjin.RecommendedPractices.GitHubActions/actions/run-scripted-build@main + id: run_build + with: + displayName: Run Build + buildScriptPath: ${{ inputs.buildScriptPath }} + netSdkVersion: ${{ inputs.netSdkVersion }} + additionalNetSdkVersion: ${{ inputs.additionalNetSdkVersion }} + pythonVersion: ${{ inputs.pythonVersion }} + tasks: ${{ inputs.buildTasks != '' && inputs.buildTasks || steps.set_defaults.outputs.DEFAULT_BUILD_TASKS }} + configuration: ${{ inputs.configuration }} + artifactName: ${{ inputs.buildArtifactName }} + artifactPath: ${{ inputs.buildArtifactPath }} + env: + BUILDVAR_AnalysisOutputStorageAccountName: ${{ inputs.sbomOutputStorageAccountName}} + BUILDVAR_AnalysisOutputContainerName: ${{ inputs.sbomOutputStorageContainerName}} + BUILDVAR_AnalysisOutputBlobPath: ${{ inputs.sbomOutputStorageContainerName }}/src_platform=github/org=${{ github.repository_owner }}/repo=${{ github.event.repository.name }} + BUILDVAR_PublishCovenantOutputToStorage: true + BUILDVAR_CovenantMetadata: > + { + "git_provider": "github", + "git_org": "${{ github.repository_owner }}", + "git_repo": "${{ github.event.repository.name }}", + "git_branch": "${{ github.ref_name }}", + "git_sha": "${{ github.sha }}" + } + BUILDVAR_TestReportTypes: HtmlInline;Cobertura + BUILDVAR_DotNetTestLoggers: > + [ + "trx;LogFilePrefix=test-results_" + ] + GITHUB_TOKEN: ${{ inputs.token }} + NUGET_API_KEY: ${{ env.NUGET_API_KEY }} + - id: check_coverage_summary + name: Check Code Coverage Summary Output + if: always() + run: | + # check if the code coverage summary file exists, but ensure the build doesn't fail if it can't be found + try { + $coverageFile = Join-Path $env:CODE_COVERAGE_SUMMARY_DIR $env:CODE_COVERAGE_SUMMARY_FILE + Write-Host "Checking for code coverage file: $coverageFile" + if (Test-Path $coverageFile) { + Write-Host "Code coverage summary file exists" + echo "EXISTS=true" >> $env:GITHUB_OUTPUT + } + } + catch {} + shell: pwsh + env: + CODE_COVERAGE_SUMMARY_DIR: ${{ steps.set_defaults.outputs.CODE_COVERAGE_SUMMARY_DIR }} + CODE_COVERAGE_SUMMARY_FILE: ${{ steps.set_defaults.outputs.CODE_COVERAGE_SUMMARY_FILE }} + - id: check_os + name: Check Runner OS + if: always() + run: | + # store the runner's operating system (i.e. distinct from the OS version info available via runner image) + if ($IsWindows) { + $RunnerOs = "windows" + } + elseif ($IsLinux) { + $RunnerOs = "linux" + } + elseif ($IsMacOS) { + $RunnerOs = "macos" + } + else { + $RunnerOs = "Unknown" + } + Write-Host "Runner OS: $RunnerOs" + echo "RUNNEROS=$RunnerOs" >> $env:GITHUB_OUTPUT + shell: pwsh + - name: Add Code Coverage PR comment + # TODO: Test whether this works when running from a fork? + if: always() && steps.check_coverage_summary.outputs.EXISTS == 'true' && github.event_name == 'pull_request' + uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2.9.0 + with: + recreate: true + path: ${{ steps.set_defaults.outputs.CODE_COVERAGE_SUMMARY_DIR }}/${{ steps.set_defaults.outputs.CODE_COVERAGE_SUMMARY_FILE }} + header: ${{ inputs.runsOn }} + # Conditional test result publishing as we can't use the docker version of the action on Windows + - name: Publish Test Results (Linux) + uses: EnricoMi/publish-unit-test-result-action@30eadd5010312f995f0d3b3cff7fe2984f69409e # v2.16.1 + if: always() && steps.check_os.outputs.RUNNEROS == 'linux' + with: + nunit_files: "*TestResults.xml" # produced by Pester + trx_files: "**/test-results_*.trx" # produced by dotnet test + junit_files: "**/*-test-results.xml" # produced by PyTest & Behave + - name: Publish Test Results (Windows) + uses: EnricoMi/publish-unit-test-result-action/windows@30eadd5010312f995f0d3b3cff7fe2984f69409e # v2.16.1 + if: always() && steps.check_os.outputs.RUNNEROS == 'windows' + with: + nunit_files: "*TestResults.xml" # produced by Pester + trx_files: "**/test-results_*.trx" # produced by dotnet test + junit_files: "**/*-test-results.xml" # produced by PyTest & Behave \ No newline at end of file diff --git a/actions/run-scripted-build/action.yml b/actions/run-scripted-build/action.yml index 02bc5d5..a8bdb90 100644 --- a/actions/run-scripted-build/action.yml +++ b/actions/run-scripted-build/action.yml @@ -88,6 +88,7 @@ runs: python-version: '${{ inputs.pythonVersion }}' - name: Debug cache paths (before) + if: inputs.inputCachePaths != '' run: | echo "inputCachePaths: ${{ inputs.inputCachePaths }}" echo "outputCachePaths: ${{ inputs.outputCachePaths }}" @@ -103,6 +104,7 @@ runs: enableCrossOsArchive: ${{ inputs.enableCrossOsCaching }} - id: cache_debug + if: inputs.inputCachePaths != '' run: | echo "CacheHit: '${{ steps.cache_inputs_restore.outputs.cache-hit }}'" shell: bash