From df3f2859858efd1fde41753d090cdb7227ed3872 Mon Sep 17 00:00:00 2001 From: Stefan Reichel Date: Tue, 5 May 2020 22:55:59 +0200 Subject: [PATCH 1/2] feat: add basic support for GitHub Actions --- Fake.sln | 20 ++++-- help/templates/template.cshtml | 1 + .../AssemblyInfo.fs | 29 +++++++++ .../Fake.BuildServer.GitHubActions.fsproj | 23 +++++++ .../GitHubActions.fs | 61 +++++++++++++++++++ .../paket.references | 4 ++ src/app/Fake.Core.Environment/BuildServer.fs | 16 +++++ 7 files changed, 149 insertions(+), 5 deletions(-) create mode 100644 src/app/Fake.BuildServer.GitHubActions/AssemblyInfo.fs create mode 100644 src/app/Fake.BuildServer.GitHubActions/Fake.BuildServer.GitHubActions.fsproj create mode 100644 src/app/Fake.BuildServer.GitHubActions/GitHubActions.fs create mode 100644 src/app/Fake.BuildServer.GitHubActions/paket.references diff --git a/Fake.sln b/Fake.sln index 7224773de1e..9417579ac44 100644 --- a/Fake.sln +++ b/Fake.sln @@ -185,12 +185,10 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fake.Tools.SignTool", "src\ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestTools", "TestTools", "{9200793A-8B59-4242-A5C8-F37CE08DE801}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{092B9791-915B-43BC-A2FD-1EA62BF5DF15}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{0141CA13-3E9C-4DB7-9BAE-0920F5B7A12D}" -EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Fake.Core.DependencyManager.Paket", "src\app\Fake.Core.DependencyManager.Paket\Fake.Core.DependencyManager.Paket.fsproj", "{F4D3249D-F4EC-4B86-BEA8-3F2314ED9B65}" EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Fake.BuildServer.GitHubActions", "src\app\Fake.BuildServer.GitHubActions\Fake.BuildServer.GitHubActions.fsproj", "{AB09E8EB-A66E-4D60-B47C-4F35F439D020}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1172,6 +1170,18 @@ Global {F4D3249D-F4EC-4B86-BEA8-3F2314ED9B65}.Release|x64.Build.0 = Release|Any CPU {F4D3249D-F4EC-4B86-BEA8-3F2314ED9B65}.Release|x86.ActiveCfg = Release|Any CPU {F4D3249D-F4EC-4B86-BEA8-3F2314ED9B65}.Release|x86.Build.0 = Release|Any CPU + {AB09E8EB-A66E-4D60-B47C-4F35F439D020}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB09E8EB-A66E-4D60-B47C-4F35F439D020}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB09E8EB-A66E-4D60-B47C-4F35F439D020}.Debug|x64.ActiveCfg = Debug|Any CPU + {AB09E8EB-A66E-4D60-B47C-4F35F439D020}.Debug|x64.Build.0 = Debug|Any CPU + {AB09E8EB-A66E-4D60-B47C-4F35F439D020}.Debug|x86.ActiveCfg = Debug|Any CPU + {AB09E8EB-A66E-4D60-B47C-4F35F439D020}.Debug|x86.Build.0 = Debug|Any CPU + {AB09E8EB-A66E-4D60-B47C-4F35F439D020}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB09E8EB-A66E-4D60-B47C-4F35F439D020}.Release|Any CPU.Build.0 = Release|Any CPU + {AB09E8EB-A66E-4D60-B47C-4F35F439D020}.Release|x64.ActiveCfg = Release|Any CPU + {AB09E8EB-A66E-4D60-B47C-4F35F439D020}.Release|x64.Build.0 = Release|Any CPU + {AB09E8EB-A66E-4D60-B47C-4F35F439D020}.Release|x86.ActiveCfg = Release|Any CPU + {AB09E8EB-A66E-4D60-B47C-4F35F439D020}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1258,8 +1268,8 @@ Global {43B8BB3C-9BE7-466D-BF15-18842AF1A4B8} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A} {3AC9D697-54FA-44CC-B69D-25BA5B656181} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A} {9200793A-8B59-4242-A5C8-F37CE08DE801} = {CCAC5CAB-03C8-4C11-ADBE-A0D05F6A4F18} - {0141CA13-3E9C-4DB7-9BAE-0920F5B7A12D} = {092B9791-915B-43BC-A2FD-1EA62BF5DF15} {F4D3249D-F4EC-4B86-BEA8-3F2314ED9B65} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A} + {AB09E8EB-A66E-4D60-B47C-4F35F439D020} = {7BFFAE76-DEE9-417A-A79B-6A6644C4553A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {058A0C5E-2216-4306-8AFB-0AE28320C26A} diff --git a/help/templates/template.cshtml b/help/templates/template.cshtml index 4b07390a37a..823f2747a6b 100644 --- a/help/templates/template.cshtml +++ b/help/templates/template.cshtml @@ -101,6 +101,7 @@ Azure DevOps GitLab + GitHub Actions TeamCity Travis diff --git a/src/app/Fake.BuildServer.GitHubActions/AssemblyInfo.fs b/src/app/Fake.BuildServer.GitHubActions/AssemblyInfo.fs new file mode 100644 index 00000000000..e7c0ace020b --- /dev/null +++ b/src/app/Fake.BuildServer.GitHubActions/AssemblyInfo.fs @@ -0,0 +1,29 @@ +// Auto-Generated by FAKE; do not edit +namespace System + +open System.Reflection + +[][][][][][] + +do () + +module internal AssemblyVersionInformation = + [] + let AssemblyTitle = + "FAKE - F# Make Integration into GitHub Actions buildserver" + + [] + let AssemblyProduct = "FAKE - F# Make" + + [] + let AssemblyVersion = "5.19.1" + + [] + let AssemblyInformationalVersion = "5.19.1" + + [] + let AssemblyFileVersion = "5.19.1" + + [] + let AssemblyMetadata_BuildDate = "2020-05-04" diff --git a/src/app/Fake.BuildServer.GitHubActions/Fake.BuildServer.GitHubActions.fsproj b/src/app/Fake.BuildServer.GitHubActions/Fake.BuildServer.GitHubActions.fsproj new file mode 100644 index 00000000000..f53f51eb8d9 --- /dev/null +++ b/src/app/Fake.BuildServer.GitHubActions/Fake.BuildServer.GitHubActions.fsproj @@ -0,0 +1,23 @@ + + + netstandard2.0;net462 + Fake.BuildServer.GitHubActions + Library + + + $(DefineConstants);NETSTANDARD;USE_HTTPCLIENT + + + $(DefineConstants);RELEASE + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/Fake.BuildServer.GitHubActions/GitHubActions.fs b/src/app/Fake.BuildServer.GitHubActions/GitHubActions.fs new file mode 100644 index 00000000000..8b0a68ed105 --- /dev/null +++ b/src/app/Fake.BuildServer.GitHubActions/GitHubActions.fs @@ -0,0 +1,61 @@ +/// Contains support for various build servers +namespace Fake.BuildServer + +open Fake.Core +open Fake.IO + +/// native support for GitHub Actions specific APIs. +/// The general documentation on how to use CI server integration can be found [here](/buildserver.html). +/// This module does not provide any special APIs please use FAKE APIs and they should integrate into this CI server. +/// If some integration is not working as expected or you have features you would like to use directly please open an issue. +[] +module GitHubActions = + + /// Exported environment variables during build. + /// See the [official documentation](https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables) for details. + type Environment = + + /// Always set to true, if present. + static member CI = Environment.environVarAsBoolOrDefault "CI" + /// The path to the GitHub home directory used to store user data. + /// For example, /github/home. + static member Home = Environment.environVar "HOME" + /// The name of the workflow. + static member Workflow = Environment.environVar "GITHUB_WORKFLOW" + /// A unique number for each run within a repository. + /// This number does not change if you re-run the workflow run. + static member RunId = Environment.environVar "GITHUB_RUN_ID" + /// A unique number for each run of a particular workflow in a repository. + /// This number begins at 1 for the workflow's first run, and increments with each new run. + /// This number does not change if you re-run the workflow run. + static member RunNumber = Environment.environVar "GITHUB_RUN_NUMBER" + /// The unique identifier (id) of the action. + static member Action = Environment.environVar "GITHUB_ACTION" + /// Always set to true when GitHub Actions is running the workflow. + /// You can use this variable to differentiate when tests are being run locally or by GitHub Actions. + static member Actions = Environment.environVarAsBoolOrDefault "GITHUB_ACTIONS" + /// The name of the person or app that initiated the workflow. For example, octocat. + static member Actor = Environment.environVar "GITHUB_ACTOR" + /// The owner and repository name. For example, octocat/Hello-World. + static member Repository = Environment.environVar "GITHUB_REPOSITORY" + /// The name of the webhook event that triggered the workflow. + static member EventName = Environment.environVar "GITHUB_EVENT_NAME" + /// The path of the file with the complete webhook event payload. + /// For example, /github/workflow/event.json. + static member EventPath = Environment.environVar "GITHUB_EVENT_PATH" + /// The GitHub workspace directory path. + /// The workspace directory contains a subdirectory with a copy of your repository if your workflow uses the actions/checkout action. + /// If you don't use the actions/checkout action, the directory will be empty. + /// For example, /home/runner/work/my-repo-name/my-repo-name. + static member Workspace = Environment.environVar "GITHUB_WORKSPACE" + /// The commit SHA that triggered the workflow. + /// For example, ffac537e6cbbf934b08745a378932722df287a53. + static member Sha = Environment.environVar "GITHUB_SHA" + /// The branch or tag ref that triggered the workflow. + /// For example, refs/heads/feature-branch-1. + /// If neither a branch or tag is available for the event type, the variable will not exist. + static member Ref = Environment.environVar "GITHUB_REF" + /// Only set for forked repositories. The branch of the head repository. + static member HeadRef = Environment.environVar "GITHUB_HEAD_REF" + /// Only set for forked repositories. The branch of the base repository. + static member BaseRef = Environment.environVar "GITHUB_BASE_REF" diff --git a/src/app/Fake.BuildServer.GitHubActions/paket.references b/src/app/Fake.BuildServer.GitHubActions/paket.references new file mode 100644 index 00000000000..edc34b53625 --- /dev/null +++ b/src/app/Fake.BuildServer.GitHubActions/paket.references @@ -0,0 +1,4 @@ +group netcore + +FSharp.Core +NETStandard.Library diff --git a/src/app/Fake.Core.Environment/BuildServer.fs b/src/app/Fake.Core.Environment/BuildServer.fs index f4f2e2402be..a1ad3c16cec 100644 --- a/src/app/Fake.Core.Environment/BuildServer.fs +++ b/src/app/Fake.Core.Environment/BuildServer.fs @@ -12,6 +12,7 @@ type BuildServer = | Travis | AppVeyor | GitLabCI + | GitHubActions | Bamboo | BitbucketPipelines | LocalBuild @@ -84,6 +85,18 @@ module BuildServer = else s else "" + // Checks if we are on GitHub Actions + /// [omit] + let isGitHubActionsBuild = + Environment.environVarAsBoolOrDefault "GITHUB_ACTIONS" false + + /// Build number retrieved from GitHub Actions + /// [omit] + let gitHubActionsBuildNumber = + if isGitHubActionsBuild + then Environment.environVar "GITHUB_RUN_NUMBER" + else "" + /// Build number retrieved from Jenkins /// [omit] let jenkinsBuildNumber = tcBuildNumber @@ -104,6 +117,7 @@ module BuildServer = elif not (String.IsNullOrEmpty travisBuildNumber) then Travis elif not (String.IsNullOrEmpty appVeyorBuildVersion) then AppVeyor elif isGitlabCI then GitLabCI + elif isGitHubActionsBuild then GitHubActions elif isTFBuild then TeamFoundation elif isBambooBuild then Bamboo elif Environment.hasEnvironVar "BITBUCKET_COMMIT" then BitbucketPipelines @@ -119,6 +133,7 @@ module BuildServer = | Travis -> getVersion travisBuildNumber | AppVeyor -> getVersion appVeyorBuildVersion | GitLabCI -> getVersion gitlabCIBuildNumber + | GitHubActions -> getVersion gitHubActionsBuildNumber | TeamFoundation -> getVersion tfBuildNumber | Bamboo -> getVersion bambooBuildNumber | LocalBuild -> getVersion localBuildLabel @@ -135,6 +150,7 @@ module BuildServer = | Travis -> true | AppVeyor -> true | GitLabCI -> true + | GitHubActions -> true | TeamFoundation -> false | Bamboo -> false | BitbucketPipelines -> false From 5d8282f49ced9f7b220716e506cfee34fccaa765 Mon Sep 17 00:00:00 2001 From: Stefan Reichel Date: Thu, 7 May 2020 13:57:40 +0200 Subject: [PATCH 2/2] feat: add build server installer for GitHub Actions --- .../GitHubActions.fs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/app/Fake.BuildServer.GitHubActions/GitHubActions.fs b/src/app/Fake.BuildServer.GitHubActions/GitHubActions.fs index 8b0a68ed105..a0f58d0a41c 100644 --- a/src/app/Fake.BuildServer.GitHubActions/GitHubActions.fs +++ b/src/app/Fake.BuildServer.GitHubActions/GitHubActions.fs @@ -59,3 +59,47 @@ module GitHubActions = static member HeadRef = Environment.environVar "GITHUB_HEAD_REF" /// Only set for forked repositories. The branch of the base repository. static member BaseRef = Environment.environVar "GITHUB_BASE_REF" + + /// Implements a TraceListener for GitHub Actions. + type internal GitHubActionsTraceListener() = + interface ITraceListener with + /// Writes the given message to the Console. + member __.Write msg = + let color = ConsoleWriter.colorMap msg + let write = ConsoleWriter.writeAnsiColor + + match msg with + | TraceData.ImportantMessage text + | TraceData.ErrorMessage text -> write true color true text + | TraceData.LogMessage (text, newLine) + | TraceData.TraceMessage (text, newLine) -> write false color newLine text + | TraceData.OpenTag (tag, descr) -> + match descr with + | Some d -> write false color true (sprintf "Starting %s '%s': %s" tag.Type tag.Name d) + | _ -> write false color true (sprintf "Starting %s '%s'" tag.Type tag.Name) + | TraceData.CloseTag (tag, time, state) -> + write false color true (sprintf "Finished (%A) '%s' in %O" state tag.Name time) + | TraceData.ImportData (typ, path) -> write false color true (sprintf "Import data '%O': %s" typ path) + | TraceData.TestOutput (test, out, err) -> + write false color true (sprintf "Test '%s' output:\n\tOutput: %s\n\tError: %s" test out err) + | TraceData.BuildNumber number -> write false color true (sprintf "Build Number: %s" number) + | TraceData.TestStatus (test, status) -> + write false color true (sprintf "Test '%s' status: %A" test status) + | TraceData.BuildState (state, _) -> write false color true (sprintf "Build State: %A" state) + + let defaultTraceListener = + GitHubActionsTraceListener() :> ITraceListener + + let detect () = BuildServer.buildServer = GitHubActions + + let install (force: bool) = + if not (detect ()) + then failwithf "Cannot run 'install()' on a non-GitHub Actions environment" + if force || not (CoreTracing.areListenersSet ()) + then CoreTracing.setTraceListeners [ defaultTraceListener ] + () + + let Installer = + { new BuildServerInstaller() with + member __.Install() = install (false) + member __.Detect() = detect () }