diff --git a/.github/actions/purview-build/action.yml b/.github/actions/purview-build/action.yml index c18b813..361f81b 100644 --- a/.github/actions/purview-build/action.yml +++ b/.github/actions/purview-build/action.yml @@ -1,14 +1,17 @@ name: Purview Build description: >- - Installs the pinned Purview.Build dotnet tool from nuget.org and runs it against the repository. + Installs the Purview.Build dotnet tool from nuget.org (pinned via `build-version`, or the + latest stable when omitted) and runs it against the repository. Configuration flows through job environment variables (Build__*, Release__*, NuGet__*, PublishLocalNuGet__*) and secrets (NUGET_APIKEY, GITHUB_TOKEN, LOCAL_NUGET_FEED_PATH). inputs: build-version: - description: Exact Purview.Build package version to run. - required: true + description: >- + Exact Purview.Build package version to run. When omitted, the latest stable version + from nuget.org is installed. + required: false dotnet-version: description: .NET SDK used by the consuming repository. required: false @@ -22,12 +25,14 @@ runs: with: dotnet-version: ${{ inputs.dotnet-version }} - - name: Install pinned shared build + - name: Install shared build shell: bash - run: >- - dotnet tool install Purview.Build - --tool-path "${{ runner.temp }}/purview-build" - --version "${{ inputs.build-version }}" + run: | + VERSION_ARGS="" + if [ -n "${{ inputs.build-version }}" ]; then + VERSION_ARGS="--version ${{ inputs.build-version }}" + fi + dotnet tool install Purview.Build --tool-path "${{ runner.temp }}/purview-build" $VERSION_ARGS - name: Run shared build shell: bash diff --git a/.github/workflows/purview-build.yml b/.github/workflows/purview-build.yml index aa466a5..1875150 100644 --- a/.github/workflows/purview-build.yml +++ b/.github/workflows/purview-build.yml @@ -4,8 +4,10 @@ on: workflow_call: inputs: build-version: - description: Exact Purview.Build package version to run. - required: true + description: >- + Exact Purview.Build package version to run. When omitted, the latest stable version + from nuget.org is installed. + required: false type: string dotnet-version: description: .NET SDK used by the consuming repository. @@ -68,11 +70,14 @@ jobs: with: dotnet-version: ${{ inputs.dotnet-version }} - - name: Install pinned shared build - run: >- - dotnet tool install Purview.Build - --tool-path "${{ runner.temp }}/purview-build" - --version "${{ inputs.build-version }}" + - name: Install shared build + shell: bash + run: | + VERSION_ARGS="" + if [ -n "${{ inputs.build-version }}" ]; then + VERSION_ARGS="--version ${{ inputs.build-version }}" + fi + dotnet tool install Purview.Build --tool-path "${{ runner.temp }}/purview-build" $VERSION_ARGS - name: Run shared build env: diff --git a/.github/workflows/purview-release.yml b/.github/workflows/purview-release.yml index 3c80223..bb44b35 100644 --- a/.github/workflows/purview-release.yml +++ b/.github/workflows/purview-release.yml @@ -4,8 +4,10 @@ on: workflow_call: inputs: build-version: - description: Exact Purview.Build package version to run. - required: true + description: >- + Exact Purview.Build package version to run. When omitted, the latest stable version + from nuget.org is installed. + required: false type: string dotnet-version: description: .NET SDK used by the consuming repository. @@ -100,12 +102,15 @@ jobs: echo "tag=$TAG" >> "$GITHUB_OUTPUT" fi - - name: Install pinned shared build + - name: Install shared build if: steps.version.outputs.should_release == 'true' - run: >- - dotnet tool install Purview.Build - --tool-path "${{ runner.temp }}/purview-build" - --version "${{ inputs.build-version }}" + shell: bash + run: | + VERSION_ARGS="" + if [ -n "${{ inputs.build-version }}" ]; then + VERSION_ARGS="--version ${{ inputs.build-version }}" + fi + dotnet tool install Purview.Build --tool-path "${{ runner.temp }}/purview-build" $VERSION_ARGS - name: Run release pipeline if: steps.version.outputs.should_release == 'true' diff --git a/README.md b/README.md index be5965d..fd8fb92 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,9 @@ on: jobs: build: uses: purview-dev/build/.github/workflows/purview-build.yml@v0.2.0 - with: - build-version: 0.2.0 + # `build-version` is optional; when omitted, the latest stable Purview.Build + # from nuget.org is installed. Pin it (e.g. `build-version: 0.2.0`) for + # reproducible builds. secrets: inherit ``` @@ -38,7 +39,6 @@ jobs: release: uses: purview-dev/build/.github/workflows/purview-release.yml@v0.2.0 with: - build-version: 0.2.0 release-mode: NuGet secrets: inherit ``` @@ -53,7 +53,7 @@ on: The reusable workflow checks whether `v{version}` (read from `package.json`) is already tagged and skips if so, so merging `main` into `release` releases exactly once. -The reusable workflows install the exact CLI version from nuget.org; the consuming repository adds `purview-build.json` and a root `package.json` version. It does not need a copied pipeline project or package-source credentials. +The reusable workflows install the pinned CLI version (or the latest stable when `build-version` is omitted) from nuget.org; the consuming repository adds `purview-build.json` and a root `package.json` version. It does not need a copied pipeline project or package-source credentials. ### Minimal repository setup (composite action) @@ -64,12 +64,12 @@ jobs: steps: - uses: actions/checkout@v7 - uses: purview-dev/build/.github/actions/purview-build@v0.2.0 - with: - build-version: 0.2.0 env: Build__TestFilter: "/*/*/*/*[Category=Unit]" ``` +The action's `build-version` input is optional. When omitted, `dotnet tool install` resolves the latest stable `Purview.Build` from nuget.org; pass an exact version to pin the build. + ### Local use ```shell diff --git a/docs/releasing.md b/docs/releasing.md index 9f9c588..5da729c 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -6,7 +6,7 @@ - Minor: additive options or modules with backward-compatible defaults. - Major: renamed/removed keys, changed defaults with material effects, or a required runtime upgrade. -Consumers pin an exact version in the reusable-workflow `build-version` input (and, for local use, `.config/dotnet-tools.json`); never use a floating range. Automated dependency updates should open a pull request, where the consumer's normal build validates the new tool before merge. Keep the previous major supported while migrations are in progress. +The reusable workflows and composite action default `build-version` to the latest stable `Purview.Build` release from nuget.org; omit the input to always run the newest version. Consumers that need reproducibility pin an exact version via the `build-version` input (and, for local use, `.config/dotnet-tools.json`). Automated dependency updates should open a pull request, where the consumer's normal build validates the new tool before merge. Keep the previous major supported while migrations are in progress. The version is declared by the `version` field in the repository's root `package.json`. Releasing consists of bumping that field and merging the validated pull request into the release head. diff --git a/package.json b/package.json index e06d370..b196cec 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { "name": "purview-build", - "version": "0.2.1", + "version": "0.2.2", "private": true } \ No newline at end of file diff --git a/src/Purview.Build/Modules/LintModule.cs b/src/Purview.Build/Modules/LintModule.cs index 13841ba..139210a 100644 --- a/src/Purview.Build/Modules/LintModule.cs +++ b/src/Purview.Build/Modules/LintModule.cs @@ -27,11 +27,28 @@ CancellationToken cancellationToken { var repositoryRoot = PathHelpers.FindRepositoryRoot(); var dotnet = context.DotNet(); - var restoreResult = await dotnet.Tool.Restore( - new() { Interactive = false, ToolManifest = Path.Combine(repositoryRoot, ".config", "dotnet-tools.json") }, - new() { WorkingDirectory = repositoryRoot }, - cancellationToken - ); + + const int maxAttempts = 3; + Task Restore() => + dotnet.Tool.Restore( + new() { Interactive = false, ToolManifest = Path.Combine(repositoryRoot, ".config", "dotnet-tools.json") }, + new() { WorkingDirectory = repositoryRoot }, + cancellationToken + ); + + var restoreResult = await Restore(); + for (var attempt = 1; restoreResult.ExitCode != 0 && attempt < maxAttempts; attempt++) + { + context.Logger.LogWarning( + "dotnet tool restore failed (attempt {Attempt} of {MaxAttempts}). Retrying...", + attempt, + maxAttempts + ); + + await Task.Delay(TimeSpan.FromSeconds(2), cancellationToken); + + restoreResult = await Restore(); + } if (restoreResult.ExitCode != 0) return restoreResult;