diff --git a/.github/workflows/_docker.yml b/.github/workflows/_docker.yml index da84dd67c1..141e9d3f21 100644 --- a/.github/workflows/_docker.yml +++ b/.github/workflows/_docker.yml @@ -60,3 +60,12 @@ jobs: docker_registry_password: ${{ secrets.DOCKER_PASSWORD }} github_registry_username: ${{ github.repository_owner }} github_registry_password: ${{ secrets.DOCKER_GITHUB_TOKEN }} + - + name: DockerHub Publish Readme + if: success() && github.event_name != 'pull_request' && github.repository_owner == 'GitTools' && github.ref_name == 'main' + shell: pwsh + run: dotnet run/docker.dll --target=DockerHubReadmePublish + env: + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} + diff --git a/.gitignore b/.gitignore index 0c2dc08616..b10134d7da 100644 --- a/.gitignore +++ b/.gitignore @@ -117,7 +117,7 @@ releaseArtifacts .dotnet artifacts !build/artifacts -src/Docker/**/content +build/docker/content src/PublicAPI.empty.txt !**/*.cake diff --git a/build/.run/DockerHub Readme Publish.run.xml b/build/.run/DockerHub Readme Publish.run.xml new file mode 100644 index 0000000000..01b628faf7 --- /dev/null +++ b/build/.run/DockerHub Readme Publish.run.xml @@ -0,0 +1,24 @@ + + + + \ No newline at end of file diff --git a/build/Directory.Packages.props b/build/Directory.Packages.props index 48111f2e8f..d91d774b51 100644 --- a/build/Directory.Packages.props +++ b/build/Directory.Packages.props @@ -7,6 +7,7 @@ + @@ -14,4 +15,4 @@ - + \ No newline at end of file diff --git a/build/artifacts/BuildContext.cs b/build/artifacts/BuildContext.cs index 833b05b7ed..73b3b1a4ef 100644 --- a/build/artifacts/BuildContext.cs +++ b/build/artifacts/BuildContext.cs @@ -4,7 +4,7 @@ namespace Artifacts; public class BuildContext : BuildContextBase { - public string MsBuildConfiguration { get; set; } = Constants.DefaultConfiguration; + public string MsBuildConfiguration { get; } = Constants.DefaultConfiguration; public bool IsDockerOnLinux { get; set; } diff --git a/build/build/Utilities/Credentials.cs b/build/build/Utilities/Credentials.cs index 9735ef2e63..94057dd729 100644 --- a/build/build/Utilities/Credentials.cs +++ b/build/build/Utilities/Credentials.cs @@ -4,7 +4,7 @@ namespace Build.Utilities; public class Credentials { - public CodeCovCredentials? CodeCov { get; private set; } + public CodeCovCredentials? CodeCov { get; private init; } public static Credentials GetCredentials(ICakeContext context) => new() { diff --git a/build/common/Utilities/DockerContextExtensions.cs b/build/common/Utilities/DockerContextExtensions.cs index 0e33bf1eae..5b826de4be 100644 --- a/build/common/Utilities/DockerContextExtensions.cs +++ b/build/common/Utilities/DockerContextExtensions.cs @@ -39,7 +39,7 @@ public static void DockerBuildImage(this BuildContextBase context, DockerImage d context.Information($"Building image: {dockerImage}"); - var workDir = Paths.Src.Combine("Docker"); + var workDir = Paths.Build.Combine("docker"); var tags = context.GetDockerTags(dockerImage, arch); var suffix = arch.ToSuffix(); diff --git a/build/common/Utilities/Models.cs b/build/common/Utilities/Models.cs index dae1ee1d7f..d36317d0a9 100644 --- a/build/common/Utilities/Models.cs +++ b/build/common/Utilities/Models.cs @@ -11,6 +11,8 @@ public record GitHubCredentials(string Token, string? UserName = null); public record NugetCredentials(string ApiKey); +public record DockerHubCredentials(string Username, string Password); + public record ChocolateyCredentials(string ApiKey); public record BuildVersion(GitVersion GitVersion, string? Version, string? Milestone, string? SemVersion, string? NugetVersion, string? ChocolateyVersion, bool IsPreRelease) diff --git a/build/common/Utilities/TaskArgumentsAttribute.cs b/build/common/Utilities/TaskArgumentsAttribute.cs index 97da6a2c9c..d93561884c 100644 --- a/build/common/Utilities/TaskArgumentsAttribute.cs +++ b/build/common/Utilities/TaskArgumentsAttribute.cs @@ -7,8 +7,8 @@ namespace Common.Utilities; [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] public class TaskArgumentAttribute : Attribute { - public string Name { get; set; } - public string[] PossibleValues { get; set; } + public string Name { get; } + public string[] PossibleValues { get; } public TaskArgumentAttribute(string name, params string[] possibleValues) { Name = name; diff --git a/build/docker/BuildContext.cs b/build/docker/BuildContext.cs index df8ba0067a..82e040ab6c 100644 --- a/build/docker/BuildContext.cs +++ b/build/docker/BuildContext.cs @@ -1,9 +1,11 @@ using Common.Utilities; +using Docker.Utilities; namespace Docker; public class BuildContext : BuildContextBase { + public Credentials? Credentials { get; set; } public bool IsDockerOnLinux { get; set; } public IEnumerable Images { get; set; } = new List(); diff --git a/build/docker/BuildLifetime.cs b/build/docker/BuildLifetime.cs index 7333f27bfa..292ed121b6 100644 --- a/build/docker/BuildLifetime.cs +++ b/build/docker/BuildLifetime.cs @@ -1,5 +1,6 @@ using Common.Lifetime; using Common.Utilities; +using Docker.Utilities; namespace Docker; @@ -9,6 +10,8 @@ public override void Setup(BuildContext context, ISetupContext info) { base.Setup(context, info); + context.Credentials = Credentials.GetCredentials(context); + context.IsDockerOnLinux = context.DockerCustomCommand("info --format '{{.OSType}}'").First().Replace("'", "") == "linux"; var architecture = context.HasArgument(Arguments.Architecture) ? context.Argument(Arguments.Architecture) : (Architecture?)null; diff --git a/src/Docker/Dockerfile b/build/docker/Dockerfile similarity index 85% rename from src/Docker/Dockerfile rename to build/docker/Dockerfile index ab0b41c847..3aad2f600a 100644 --- a/src/Docker/Dockerfile +++ b/build/docker/Dockerfile @@ -1,7 +1,7 @@ ARG REGISTRY='docker.io' -ARG DISTRO='debian-9' -ARG DOTNET_VERSION='3.1' -ARG VERSION='5.5.1' +ARG DISTRO='debian-11' +ARG DOTNET_VERSION='6.0' +ARG VERSION='5.12.0' FROM $REGISTRY/gittools/build-images:$DISTRO-sdk-$DOTNET_VERSION as installer ARG contentFolder diff --git a/build/docker/Tasks/DockerBuild.cs b/build/docker/Tasks/DockerBuild.cs index cd4736052f..7060273157 100644 --- a/build/docker/Tasks/DockerBuild.cs +++ b/build/docker/Tasks/DockerBuild.cs @@ -21,7 +21,7 @@ public override bool ShouldRun(BuildContext context) public override void Run(BuildContext context) { var tool = Paths.Nuget.CombineWithFilePath("GitVersion.Tool*"); - var dest = Paths.Src.Combine("Docker").Combine("content"); + var dest = Paths.Build.Combine("docker").Combine("content"); context.EnsureDirectoryExists(dest); context.CopyFiles(tool.FullPath, dest); diff --git a/build/docker/Tasks/DockerHubReadmePublish.cs b/build/docker/Tasks/DockerHubReadmePublish.cs new file mode 100644 index 0000000000..eff730dceb --- /dev/null +++ b/build/docker/Tasks/DockerHubReadmePublish.cs @@ -0,0 +1,82 @@ +using Cake.Http; +using Cake.Json; +using Common.Utilities; + +namespace Docker.Tasks; + +[TaskName(nameof(DockerHubReadmePublish))] +[TaskDescription("Publish the DockerHub updated README.md")] +public class DockerHubReadmePublish : FrostingTask +{ + public override bool ShouldRun(BuildContext context) + { + var shouldRun = false; + if (context.DockerRegistry == DockerRegistry.DockerHub) + { + shouldRun &= context.ShouldRun(context.IsStableRelease, $"{nameof(DockerHubReadmePublish)} works only for tagged releases."); + } + + return shouldRun; + } + + public override void Run(BuildContext context) + { + var readme = GetReadmeContent(context); + + var response = context.HttpPost("https://hub.docker.com/v2/users/login", settings => + { + var credentials = context.Credentials!.DockerHub!; + settings + .SetContentType("application/json") + .SetJsonRequestBody(new { username = credentials.Username, password = credentials.Password }); + }); + + + context.HttpPatch("https://hub.docker.com/v2/repositories/gittools/gitversion", settings => + { + var token = context.ParseJson(response).Value("token"); + settings + .SetContentType("application/json") + .SetAuthorization($"JWT", token) + .SetJsonRequestBody(new { full_description = readme }); + }); + } + + private static string GetReadmeContent(BuildContextBase context) + { + var version = context.Version!.GitVersion.MajorMinorPatch; + const string distro = Constants.AlpineLatest; + const string dotnetVersion = Constants.VersionLatest; + var tag = $"{version}-{distro}-{dotnetVersion}"; + // language=markdown + var readme = $""" +# GitVersion + +This repository contains the Docker images for [GitVersion](https://gitversion.net). + +## Usage + +The recommended image to run is `alpine`, as they are the smallest Docker images we provide (83 MB). This will execute GitVersion for the current working directory (`$(pwd)`) on Linux and Unix or powershell on Windows: + +```sh +docker run --rm -v "$(pwd):/repo" gittools/gitversion:{tag} /repo +``` +The following command will execute GitVersion for the current working directory (`%CD%`) on Windows with CMD: + +```sh +docker run --rm -v "%CD%:/repo" gittools/gitversion:{tag} /repo +``` +Note that the path `/repo` needs to be passed as an argument since the `gitversion` executable within the container is not aware of the fact that it's running inside a container. + +### Tags + +Most of the tags we provide have both arm64 and amd64 variants. If you need to pull a architecture specific tag you can do that like: + +```sh +docker run --rm -v "$(pwd):/repo" gittools/gitversion:{tag}-amd64 /repo +docker run --rm -v "$(pwd):/repo" gittools/gitversion:{tag}-arm64 /repo +``` +"""; + return readme; + } +} diff --git a/build/docker/Utilities/Credentials.cs b/build/docker/Utilities/Credentials.cs new file mode 100644 index 0000000000..75f45b5928 --- /dev/null +++ b/build/docker/Utilities/Credentials.cs @@ -0,0 +1,15 @@ +using Common.Utilities; + +namespace Docker.Utilities; + +public class Credentials +{ + public DockerHubCredentials? DockerHub { get; private init; } + + public static Credentials GetCredentials(ICakeContext context) => new() + { + DockerHub = new DockerHubCredentials( + context.EnvironmentVariable("DOCKER_USERNAME"), + context.EnvironmentVariable("DOCKER_PASSWORD")), + }; +} diff --git a/build/docker/docker.csproj b/build/docker/docker.csproj index 4b1cccd25e..c7f9a603c9 100644 --- a/build/docker/docker.csproj +++ b/build/docker/docker.csproj @@ -6,4 +6,13 @@ + + + + + + + + + diff --git a/build/docs/Utilities/Credentials.cs b/build/docs/Utilities/Credentials.cs index 1726315379..c221d8dd9f 100644 --- a/build/docs/Utilities/Credentials.cs +++ b/build/docs/Utilities/Credentials.cs @@ -4,7 +4,7 @@ namespace Docs.Utilities; public class Credentials { - public GitHubCredentials? GitHub { get; private set; } + public GitHubCredentials? GitHub { get; private init; } public static Credentials GetCredentials(ICakeContext context) => new() { GitHub = new GitHubCredentials( diff --git a/build/publish/BuildContext.cs b/build/publish/BuildContext.cs index 5ad09ee4fa..3033e3705a 100644 --- a/build/publish/BuildContext.cs +++ b/build/publish/BuildContext.cs @@ -7,7 +7,7 @@ public class BuildContext : BuildContextBase { public Credentials? Credentials { get; set; } - public List Packages { get; set; } = new(); + public List Packages { get; } = new(); public BuildContext(ICakeContext context) : base(context) { } diff --git a/build/publish/Utilities/Credentials.cs b/build/publish/Utilities/Credentials.cs index e8cf943c20..e14c628c2e 100644 --- a/build/publish/Utilities/Credentials.cs +++ b/build/publish/Utilities/Credentials.cs @@ -4,9 +4,9 @@ namespace Publish.Utilities; public class Credentials { - public GitHubCredentials? GitHub { get; private set; } - public NugetCredentials? Nuget { get; private set; } - public ChocolateyCredentials? Chocolatey { get; private set; } + public GitHubCredentials? GitHub { get; private init; } + public NugetCredentials? Nuget { get; private init; } + public ChocolateyCredentials? Chocolatey { get; private init; } public static Credentials GetCredentials(ICakeContext context) => new() { diff --git a/build/release/Utilities/Credentials.cs b/build/release/Utilities/Credentials.cs index c71f6cf92f..94501bb5b7 100644 --- a/build/release/Utilities/Credentials.cs +++ b/build/release/Utilities/Credentials.cs @@ -4,7 +4,7 @@ namespace Release.Utilities; public class Credentials { - public GitHubCredentials? GitHub { get; private set; } + public GitHubCredentials? GitHub { get; private init; } public static Credentials GetCredentials(ICakeContext context) => new() { GitHub = new GitHubCredentials(context.EnvironmentVariable("GITHUB_TOKEN")),