Regenerating the interop wrapper now records itself in the manifest #377
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: CodeQL | |
| # Static analysis for both languages in this repository. | |
| # | |
| # C# (the Control Panel) runs on every push and pull request. It builds on a | |
| # GitHub-hosted runner in a couple of minutes, so it is cheap enough to gate | |
| # changes on. | |
| # | |
| # C++ (the mail server - every protocol parser, and the whole surface that faces | |
| # the internet) runs weekly and on demand, and deliberately NOT on push or pull | |
| # request. That trade-off costs something, so the reasoning is recorded here | |
| # rather than left to be rediscovered: | |
| # | |
| # * The server cannot be built on a GitHub-hosted runner at all. It needs the | |
| # v145 toolset from Visual Studio 2026 and the prebuilt native dependencies | |
| # (boost_1_91_0, openssl-4.0.1, postgresql-18.3) that $(hMailServerLibs) | |
| # points at. See .github/workflows/server-build.yml, which carries the same | |
| # requirement and the same [self-hosted, windows] label. There is one such | |
| # machine, and it is also the machine that runs the regression suite. | |
| # * CodeQL builds its database by tracing the compiler, so it needs a FULL | |
| # build every time. An incremental build that skips up-to-date files | |
| # produces an empty database and the analysis fails outright with "No source | |
| # code was seen during the build". That means 516 translation units from | |
| # cold, on every run, with the extractor inside every cl.exe invocation. | |
| # | |
| # Putting that on every push would queue pull requests behind a multi-hour job | |
| # on a single machine, and would collide with the regression suite that shares | |
| # it. Weekly plus on-demand is the honest answer. | |
| # | |
| # The cost of that choice, stated plainly: an alert introduced by a pull request | |
| # is not seen until the next weekly run on master, and is then attributed to | |
| # master rather than to the change that introduced it. When a change touches the | |
| # protocol parsers, run this workflow by hand against the branch | |
| # (workflow_dispatch) before merging rather than waiting for the schedule. | |
| on: | |
| push: | |
| branches: [ master ] | |
| pull_request: | |
| branches: [ master ] | |
| schedule: | |
| - cron: '32 4 * * 1' # weekly, Monday 04:32 UTC | |
| workflow_dispatch: | |
| inputs: | |
| configuration: | |
| description: 'Build configuration for the C++ server analysis' | |
| type: choice | |
| options: [Release, Debug] | |
| default: Release | |
| permissions: | |
| contents: read | |
| jobs: | |
| csharp: | |
| name: Analyze (csharp) | |
| runs-on: windows-latest | |
| permissions: | |
| security-events: write | |
| actions: read | |
| contents: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Set up .NET 10 | |
| uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 | |
| with: | |
| dotnet-version: '10.0.x' | |
| # security-and-quality adds the quality-tagged queries to the security | |
| # suite; their findings surface as code-scanning alerts alongside the | |
| # security ones. (Not, as this comment once claimed, on the Code quality | |
| # page - that page was fed by a separate GitHub-managed buildless scan, | |
| # which ignored this repository's config entirely and was switched off | |
| # deliberately: it re-reported, without type information, the exact | |
| # rules excluded below with measured reasoning.) The six rules that fire | |
| # in bulk here on deliberate design rather than on defects are filtered | |
| # in the config file, each with its measured count and the reasoning. | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 | |
| with: | |
| languages: csharp | |
| build-mode: manual | |
| config-file: ./.github/codeql/codeql-config.yml | |
| queries: security-and-quality | |
| # Both solutions, deliberately: for a traced build, CodeQL analyses only | |
| # what the compiler compiles, so a project left out of this step is a | |
| # project that has never been scanned. That was DBUpdater, DBSetup, | |
| # DBSetupQuick, DataDirectorySynchronizer, ImportTool and Shared until | |
| # the managed quality scan's findings revealed the gap - the only scanner | |
| # covering those tools was the one being switched off for ignoring the | |
| # config. The test projects are not built here and stay unscanned: | |
| # fixtures, not shipped code. | |
| - name: Build Control Panel | |
| run: dotnet build hmailserver/source/Tools/ControlPanel/ControlPanel.csproj -c Release | |
| - name: Build the setup and migration tools | |
| run: dotnet build "hmailserver/source/Tools/hMailServer Tools.sln" -c Release | |
| - name: Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 | |
| with: | |
| category: "/language:csharp" | |
| upload: never | |
| output: sarif-results | |
| # paths-ignore in codeql-config.yml cannot drop these results: for a | |
| # compiled language analysed with build-mode: manual, CodeQL extracts | |
| # whatever the compiler compiles - including the WPF XAML compiler's | |
| # *.g.cs under obj/ - and a config file's path filters only restrict | |
| # extraction for interpreted languages or for build-mode: none. So the | |
| # build output is dropped from the SARIF here, between analyse and upload. | |
| - name: Drop build-output results from the SARIF | |
| shell: python | |
| run: | | |
| import json | |
| def in_build_output(result): | |
| locations = result.get("locations") or [] | |
| if not locations: | |
| return False | |
| uri = locations[0].get("physicalLocation", {}).get("artifactLocation", {}).get("uri", "") | |
| return any(part in ("obj", "bin") for part in uri.split("/")) | |
| path = "sarif-results/csharp.sarif" | |
| with open(path, encoding="utf-8") as f: | |
| sarif = json.load(f) | |
| for run in sarif["runs"]: | |
| before = len(run["results"]) | |
| run["results"] = [r for r in run["results"] if not in_build_output(r)] | |
| print(f"Dropped {before - len(run['results'])} build-output result(s); {len(run['results'])} remain.") | |
| with open(path, "w", encoding="utf-8") as f: | |
| json.dump(sarif, f) | |
| - name: Upload results | |
| uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 | |
| with: | |
| sarif_file: sarif-results/csharp.sarif | |
| category: "/language:csharp" | |
| cpp: | |
| name: Analyze (c-cpp) | |
| # Schedule and manual dispatch only - see the header. A push or pull_request | |
| # run of this job would sit on the one self-hosted machine for hours. | |
| if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| runs-on: [self-hosted, windows] | |
| # A cold traced build of 516 translation units plus query evaluation over | |
| # 6.1 MB of C++. Bounded so a wedged run cannot hold the runner for a day. | |
| timeout-minutes: 360 | |
| permissions: | |
| security-events: write | |
| actions: read | |
| contents: read | |
| env: | |
| # inputs.configuration is empty on a scheduled run, and build.ps1 defaults | |
| # to Debug when handed an empty string - which would quietly analyse the | |
| # _DEBUG preprocessor path instead of the one that ships. | |
| BUILD_CONFIGURATION: ${{ inputs.configuration || 'Release' }} | |
| # MSBuild keeps its worker nodes alive between invocations by default. A | |
| # node left over from an earlier job on this runner was started outside | |
| # CodeQL's tracer, so anything it compiles is invisible to the extractor - | |
| # which shows up as a partial database rather than as an error. | |
| MSBUILDDISABLENODEREUSE: '1' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| # Fail here with a legible message rather than 500 lines into MSBuild. | |
| # server-build.yml also warns about each individual dependency folder; | |
| # this checks only the condition that makes the build impossible rather | |
| # than merely likely to fail at link time. | |
| - name: Verify native dependencies | |
| shell: powershell | |
| run: | | |
| if (-not $env:hMailServerLibs) { throw "hMailServerLibs is not set on this runner. See .github/workflows/server-build.yml for what this runner needs." } | |
| if (-not (Test-Path $env:hMailServerLibs)) { throw "hMailServerLibs path '$($env:hMailServerLibs)' does not exist." } | |
| Write-Host "hMailServerLibs = $($env:hMailServerLibs)" | |
| # The service on this runner runs from this checkout's build output, so | |
| # the linker cannot replace hMailServer.exe while it is running. The | |
| # project's own pre-build event does a NET STOP for exactly this reason, | |
| # but build.ps1 suppresses pre- and post-build events, so it happens here | |
| # instead - the same way server-build.yml handles it. | |
| - name: Stop hMailServer service (free the executable) | |
| shell: powershell | |
| run: Stop-Service hMailServer -ErrorAction SilentlyContinue | |
| # security-extended rather than security-and-quality, deliberately, and | |
| # this is the one place the two languages are configured differently: | |
| # | |
| # * CodeQL ships no quality-tagged queries for C++ at all (measured | |
| # in d1c35ec: 108 for C#, zero for C++), so security-and-quality | |
| # would add nothing but the generic maintainability set. | |
| # * What it would buy is roughly a hundred maintainability and | |
| # reliability queries let loose on 6.1 MB of twenty-year-old ATL/COM | |
| # C++, on a codebase that has never been scanned once. d1c35ec was | |
| # written because 733 undifferentiated findings are "not a signal | |
| # anyone can act on"; burying the first ever security scan of the | |
| # protocol parsers under style alerts repeats that mistake. | |
| # | |
| # security-extended is strictly more security coverage with no quality | |
| # queries, which is what this analysis is for. Once the security backlog | |
| # is triaged, moving this to security-and-quality is a one-word change - | |
| # but do it from a measured count, not on principle. | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 | |
| with: | |
| languages: c-cpp | |
| build-mode: manual | |
| config-file: ./.github/codeql/codeql-config.yml | |
| queries: security-extended | |
| # -Clean is not optional. This runner reuses its workspace between runs, | |
| # so without it MSBuild skips every up-to-date translation unit, the | |
| # extractor sees nothing, and the analyze step below fails with "No source | |
| # code was seen during the build" - the classic CodeQL C++ failure on a | |
| # self-hosted runner, and one that reads like a CodeQL bug rather than an | |
| # incremental build. | |
| - name: Build server under CodeQL tracing | |
| shell: powershell | |
| run: ./build/build.ps1 -Configuration $env:BUILD_CONFIGURATION -Clean | |
| - name: Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 | |
| with: | |
| category: "/language:c-cpp" | |
| - name: Restart hMailServer service | |
| if: ${{ always() }} | |
| shell: powershell | |
| run: | | |
| Start-Service hMailServer -ErrorAction SilentlyContinue | |
| $service = Get-Service hMailServer -ErrorAction SilentlyContinue | |
| if (-not $service -or $service.Status -ne 'Running') { | |
| Write-Warning "hMailServer is not running. A build that failed after the clean step leaves the output directory empty, so the service binary may be missing - rerun server-build.yml to restore it." | |
| } |