From afbdadb6a97e0e22590196474c99e1049ab36a72 Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Wed, 13 Dec 2023 00:25:00 +0800 Subject: [PATCH 1/4] CI: move 'publish' workflow inside the 'build' one This way the 'publish' workflow is tested in every build, to make sure it doesn't break (before this, we would only notice of any breakages at the moment we create the tag). To prevent a release and a nuget upload to happen at every commit, we just append an 'if' (see [1] for the syntax) element to these steps. [1] https://github.community/t/if-not-startswith-mutually-exclusive-steps/141841/2 --- .../{publish.yml => build+test+publish.yml} | 45 ++++++++++++++++--- .github/workflows/buildAndTest.yml | 30 ------------- 2 files changed, 39 insertions(+), 36 deletions(-) rename .github/workflows/{publish.yml => build+test+publish.yml} (58%) delete mode 100644 .github/workflows/buildAndTest.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/build+test+publish.yml similarity index 58% rename from .github/workflows/publish.yml rename to .github/workflows/build+test+publish.yml index 33964b4f8..52d568f1c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/build+test+publish.yml @@ -1,12 +1,42 @@ -name: Publish +name: .NET 5.0 on: + pull_request: push: tags: - - 'v*' # Publish on any new tag + - 'v*' + branches: + - '*' jobs: - build: + buildAndTest: + + strategy: + matrix: + os: + - ubuntu-latest + - windows-latest + - macOS-latest + dotnet: [5.0.202] + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v1 + - name: Setup .NET 5 + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ matrix.dotnet }} + - name: Restore tools + run: dotnet tool restore + - name: Restore dependencies + run: dotnet restore + - name: Build and run tests + run: dotnet fake build -t Test + - name: Run FSharpLint on itself + run: dotnet fake build -t SelfCheck + + publish: + needs: buildAndTest strategy: matrix: @@ -32,12 +62,14 @@ jobs: with: version: ${{ github.ref }} path: ./CHANGELOG.md - - name: Upload binaries to nuget + - name: Upload binaries to nuget (if tag) + if: startsWith(github.ref, 'refs/tags/') env: nuget-key: ${{ secrets.NUGET_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: dotnet fake build -t Push - - name: Create Release + - name: Create Release (if tag) + if: startsWith(github.ref, 'refs/tags/') id: create_release uses: actions/create-release@latest env: @@ -48,7 +80,8 @@ jobs: body: ${{ steps.changelog_reader.outputs.log_entry }} draft: false prerelease: false - - name: Upload binaries to release + - name: Upload binaries to release (if tag) + if: startsWith(github.ref, 'refs/tags/') uses: svenstaro/upload-release-action@v1-release with: repo_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml deleted file mode 100644 index 48003da66..000000000 --- a/.github/workflows/buildAndTest.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: .NET 5.0 - -on: [push, pull_request] - -jobs: - buildAndTest: - - strategy: - matrix: - os: - - ubuntu-latest - - windows-latest - - macOS-latest - dotnet: [5.0.202] - runs-on: ${{ matrix.os }} - - steps: - - uses: actions/checkout@v1 - - name: Setup .NET 5 - uses: actions/setup-dotnet@v3 - with: - dotnet-version: ${{ matrix.dotnet }} - - name: Restore tools - run: dotnet tool restore - - name: Restore dependencies - run: dotnet restore - - name: Build and run tests - run: dotnet fake build -t Test - - name: Run FSharpLint on itself - run: dotnet fake build -t SelfCheck From 752c1dea65e95878ad0c1262f47aa8eb4d6ca621 Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Wed, 13 Dec 2023 00:48:27 +0800 Subject: [PATCH 2/4] CI,build.fsx: publish prerelease nuget version for each commit For this, the "alpha01" prerelease name is replaced by a dynamic one that contains the date and the git hash. We've had to move the Helpers before the Variables in order to use them in this new part of the script. As a side-node, these are nice FAKE docs about process handling here: https://fake.build/reference/fake-core-process.html --- .github/workflows/build+test+publish.yml | 4 +- build.fsx | 90 ++++++++++++++++-------- 2 files changed, 64 insertions(+), 30 deletions(-) diff --git a/.github/workflows/build+test+publish.yml b/.github/workflows/build+test+publish.yml index 52d568f1c..9c9dc020e 100644 --- a/.github/workflows/build+test+publish.yml +++ b/.github/workflows/build+test+publish.yml @@ -62,11 +62,11 @@ jobs: with: version: ${{ github.ref }} path: ./CHANGELOG.md - - name: Upload binaries to nuget (if tag) - if: startsWith(github.ref, 'refs/tags/') + - name: Upload binaries to nuget (if nugetKey present) env: nuget-key: ${{ secrets.NUGET_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + if: github.event_name == 'push' && env.nuget-key != null run: dotnet fake build -t Push - name: Create Release (if tag) if: startsWith(github.ref, 'refs/tags/') diff --git a/build.fsx b/build.fsx index 4d95f1a59..13fe36904 100644 --- a/build.fsx +++ b/build.fsx @@ -13,6 +13,7 @@ open Fake.IO.Globbing.Operators open Fake.Core.TargetOperators open Fake.Api +open System open System.IO Target.initEnvironment() @@ -30,6 +31,23 @@ let gitName = "FSharpLint" let gitHome = "https://github.com/" + gitOwner let gitUrl = gitHome + "/" + gitName +// -------------------------------------------------------------------------------------- +// Helpers +// -------------------------------------------------------------------------------------- +let isNullOrWhiteSpace = System.String.IsNullOrWhiteSpace + +let exec cmd args dir = + let proc = + CreateProcess.fromRawCommandLine cmd args + |> CreateProcess.ensureExitCodeWithMessage (sprintf "Error while running '%s' with args: %s" cmd args) + (if isNullOrWhiteSpace dir then proc + else proc |> CreateProcess.withWorkingDirectory dir) + |> Proc.run + |> ignore + +let getBuildParam = Environment.environVar +let DoNothing = ignore + // -------------------------------------------------------------------------------------- // Build variables // -------------------------------------------------------------------------------------- @@ -41,37 +59,52 @@ let nugetDir = "./out/" System.Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ let changelogFilename = "CHANGELOG.md" let changelog = Changelog.load changelogFilename + +let githubRef = Environment.GetEnvironmentVariable "GITHUB_REF" +let tagPrefix = "refs/tags/" +let isTag = + if isNull githubRef then + false + else + githubRef.StartsWith tagPrefix + let nugetVersion = - match changelog.Unreleased with - | None -> + match (changelog.Unreleased, isTag) with + | (Some _unreleased, true) -> failwith "Shouldn't publish a git tag for changes outside a real release" + | (None, true) -> changelog.LatestEntry.NuGetVersion - | Some _unreleased -> + | (_, false) -> let current = changelog.LatestEntry.NuGetVersion |> SemVer.parse let bumped = { current with Minor = current.Minor + 1u Patch = 0u Original = None - PreRelease = PreRelease.TryParse "alpha01" } - string bumped - -let packageReleaseNotes = sprintf "%s/blob/v%s/CHANGELOG.md" gitUrl nugetVersion + PreRelease = None } + let bumpedBaseVersion = string bumped + + let nugetPush = System.IO.Path.Combine("fsx", "Tools", "nugetPush.fsx") + if not(System.IO.File.Exists nugetPush) then + exec "git" "clone https://github.com/nblockchain/fsx.git" "." + let procResult = + CreateProcess.fromRawCommand + "dotnet" + [ + "fsi" + nugetPush + "--output-version" + bumpedBaseVersion + ] + |> CreateProcess.redirectOutput + |> CreateProcess.ensureExitCode + |> Proc.run + procResult.Result.Output.Trim() + +let PackageReleaseNotes baseProps = + if isTag then + ("PackageReleaseNotes", sprintf "%s/blob/v%s/CHANGELOG.md" gitUrl nugetVersion)::baseProps + else + baseProps -// -------------------------------------------------------------------------------------- -// Helpers -// -------------------------------------------------------------------------------------- -let isNullOrWhiteSpace = System.String.IsNullOrWhiteSpace - -let exec cmd args dir = - let proc = - CreateProcess.fromRawCommandLine cmd args - |> CreateProcess.ensureExitCodeWithMessage (sprintf "Error while running '%s' with args: %s" cmd args) - (if isNullOrWhiteSpace dir then proc - else proc |> CreateProcess.withWorkingDirectory dir) - |> Proc.run - |> ignore - -let getBuildParam = Environment.environVar -let DoNothing = ignore // -------------------------------------------------------------------------------------- // Build Targets // -------------------------------------------------------------------------------------- @@ -100,28 +133,29 @@ Target.create "Docs" (fun _ -> // -------------------------------------------------------------------------------------- // Release Targets // -------------------------------------------------------------------------------------- + Target.create "BuildRelease" (fun _ -> + let properties = ("Version", nugetVersion) |> List.singleton |> PackageReleaseNotes + DotNet.build (fun p -> { p with Configuration = DotNet.BuildConfiguration.Release OutputPath = Some buildDir - MSBuildParams = { p.MSBuildParams with Properties = [("Version", nugetVersion); ("PackageReleaseNotes", packageReleaseNotes)]} + MSBuildParams = { p.MSBuildParams with Properties = properties } } ) "FSharpLint.sln" ) Target.create "Pack" (fun _ -> - let properties = [ + let properties = PackageReleaseNotes ([ ("Version", nugetVersion); ("Authors", authors) ("PackageProjectUrl", gitUrl) ("RepositoryType", "git") ("RepositoryUrl", gitUrl) ("PackageLicenseExpression", "MIT") - ("PackageReleaseNotes", packageReleaseNotes) - ] - + ]) DotNet.pack (fun p -> { p with From 9233ab255d56ebea8a0ed278faabbcdd1504c466 Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Wed, 13 Dec 2023 18:12:34 +0800 Subject: [PATCH 3/4] build.fsx: remove dependency on external repo Rather depend on new nuget package to get the prerelease version. --- build.fsx | 12 ++++-------- nugetPreRelease.fsx | 6 ++++++ 2 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 nugetPreRelease.fsx diff --git a/build.fsx b/build.fsx index 13fe36904..090779ba3 100644 --- a/build.fsx +++ b/build.fsx @@ -54,9 +54,9 @@ let DoNothing = ignore let buildDir = "./build/" let nugetDir = "./out/" +let rootDir = __SOURCE_DIRECTORY__ |> DirectoryInfo - -System.Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ +System.Environment.CurrentDirectory <- rootDir.FullName let changelogFilename = "CHANGELOG.md" let changelog = Changelog.load changelogFilename @@ -82,16 +82,13 @@ let nugetVersion = PreRelease = None } let bumpedBaseVersion = string bumped - let nugetPush = System.IO.Path.Combine("fsx", "Tools", "nugetPush.fsx") - if not(System.IO.File.Exists nugetPush) then - exec "git" "clone https://github.com/nblockchain/fsx.git" "." + let nugetPreRelease = Path.Combine(rootDir.FullName, "nugetPreRelease.fsx") let procResult = CreateProcess.fromRawCommand "dotnet" [ "fsi" - nugetPush - "--output-version" + nugetPreRelease bumpedBaseVersion ] |> CreateProcess.redirectOutput @@ -176,7 +173,6 @@ Target.create "Push" (fun _ -> Target.create "SelfCheck" (fun _ -> let frameworkVersion = "net5.0" - let rootDir = __SOURCE_DIRECTORY__ |> DirectoryInfo let srcDir = Path.Combine(rootDir.FullName, "src") |> DirectoryInfo let consoleProj = Path.Combine(srcDir.FullName, "FSharpLint.Console", "FSharpLint.Console.fsproj") |> FileInfo diff --git a/nugetPreRelease.fsx b/nugetPreRelease.fsx new file mode 100644 index 000000000..71cadf764 --- /dev/null +++ b/nugetPreRelease.fsx @@ -0,0 +1,6 @@ +#r "nuget: Fsdk, Version=0.6.0--date20231213-0703.git-d7a5962" + +let args = fsi.CommandLineArgs + +Fsdk.Network.GetNugetPrereleaseVersionFromBaseVersion args.[1] +|> System.Console.WriteLine From 199b7ce45de23903fe69d4069e083268e07d66f8 Mon Sep 17 00:00:00 2001 From: "Andres G. Aragoneses" Date: Thu, 14 Dec 2023 12:34:59 +0800 Subject: [PATCH 4/4] sln: add build.fsx for easy IDE access --- FSharpLint.sln | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/FSharpLint.sln b/FSharpLint.sln index dc7a34f1b..99b625527 100644 --- a/FSharpLint.sln +++ b/FSharpLint.sln @@ -19,6 +19,11 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "FSharpLint.Console.Tests", EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpLint.Benchmarks", "tests\FSharpLint.Benchmarks\FSharpLint.Benchmarks.fsproj", "{B4A92AC6-F74A-4709-B2F7-6C5BABBFDEB0}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{270E691D-ECA1-4BC5-B851-C5431A64E9FA}" + ProjectSection(SolutionItems) = preProject + build.fsx = build.fsx + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU