Skip to content

CI Host GitHub Actions

Scott Singleton edited this page May 10, 2026 · 1 revision

CI Host: GitHub Actions

GitHubActionsHost resolves automatically when GITHUB_ACTIONS=true. Inherits the common CiHost surface (CI Host Integrations) and adds GitHub-specific properties and commands.

Detection

if (CiHost is GitHubActionsHost gh)
{
    // GitHub Actions specifics
}

Read-only properties

All map to standard GitHub Actions environment variables:

Property Env var
Workflow GITHUB_WORKFLOW
RunId GITHUB_RUN_ID
RunNumber GITHUB_RUN_NUMBER
Job GITHUB_JOB
Actor GITHUB_ACTOR
Repository GITHUB_REPOSITORY
Sha GITHUB_SHA
Ref GITHUB_REF
RefName GITHUB_REF_NAME
HeadRef GITHUB_HEAD_REF (PR head)
BaseRef GITHUB_BASE_REF (PR base)
EventName GITHUB_EVENT_NAME
Workspace GITHUB_WORKSPACE
RunnerOs RUNNER_OS

Plus a derived helper:

gh.IsPullRequest    // true when EventName is "pull_request" or "pull_request_target"

Emit commands

Standard CiHost surface, GitHub workflow-command syntax:

gh.OpenGroup("Build");                // ::group::Build
gh.CloseGroup();                      // ::endgroup::
gh.LogWarning("deprecation noted");   // ::warning::deprecation noted
gh.LogError("compile failed");        // ::error::compile failed
gh.SetVariable("MY_VAR", "value");    // writes to GITHUB_ENV file (heredoc-safe)

Errors and warnings use the workflow-command escape rules (%%25, \n%0A, \r%0D) so multi-line messages render correctly in the Actions UI.

SetVariable writes to the GITHUB_ENV file when present (modern runners always set it), using a heredoc-style format that handles multi-line values cleanly. Falls back to the legacy ::set-env:: command if GITHUB_ENV is unset.

GitHub-specific extras

// Append to the job's run summary (renders as markdown)
gh.AppendStepSummary("## Build summary\n\n- Version: `1.2.3`\n- Commit: `abc1234`");

// Tell GH Actions to mask a value in subsequent log lines
gh.MaskValue(secretValue);

AppendStepSummary writes to the GITHUB_STEP_SUMMARY file — its content shows on the Actions run page, after the job log. Useful for producing a structured "what happened" summary alongside the human-readable log.

MaskValue emits ::add-mask::<value>. After this command, GitHub will redact the value from subsequent log lines server-side. Note that secrets registered with the executor's RedactionTable are already redacted client-side before reaching GH; MaskValue is for cases where a value reaches GH outside Tamp's writer (rare).

Recipes

Wrap a noisy step in a collapsible group

Target IntegrationTests => _ => _.Executes(() =>
{
    if (CiHost is GitHubActionsHost gh) gh.OpenGroup("Integration tests");
    DotNet.Test(s => s.SetFilter("Category=Integration").SetVerbosity(DotNetVerbosity.Detailed));
    if (CiHost is GitHubActionsHost gh2) gh2.CloseGroup();
});

Render the build summary as markdown on the run page

Target SummarizeBuild => _ => _
    .AssuredAfterFailure()
    .Executes(() =>
    {
        if (CiHost is not GitHubActionsHost gh) return;
        gh.AppendStepSummary($"""
            ## {(LastBuildOk ? "✅" : "❌")} Build {Version}

            | Target | Status | Duration |
            | --- | --- | --- |
            {string.Join('\n', BuildResults.Select(r => $"| {r.Name} | {r.Status} | {r.Duration} |"))}
            """);
    });

Pass a value through to subsequent steps

Target ResolveVersion => _ => _.Executes(() =>
{
    var version = $"1.0.0-{Git.Commit[..7]}";
    if (CiHost is GitHubActionsHost gh)
        gh.SetVariable("PACKAGE_VERSION", version);
    PackageVersion = version;
});

Subsequent steps in the same job can read $PACKAGE_VERSION from their shell.

Trusted publishing

Tamp's own release workflow uses GitHub Actions OIDC to authenticate to nuget.org without long-lived API keys. That's a workflow-author concern, not a build-script one — CiHost doesn't expose the OIDC token. See the main repo's .github/workflows/release.yml for the worked example.

See also

Clone this wiki locally