diff --git a/.github/workflows/build-and-pack.yml b/.github/workflows/build-and-pack.yml index 48c3f8d..a18dc1a 100644 --- a/.github/workflows/build-and-pack.yml +++ b/.github/workflows/build-and-pack.yml @@ -4,7 +4,7 @@ name: Build, test & pack on: - workflow_call: + workflow_call: # Called by other workflows only. inputs: configuration: description: 'Define whether this is a debug or a release build.' @@ -15,6 +15,7 @@ on: required: true type: boolean is_prerelease: + # Decides whether a pre-release suffix is needed. description: 'Define if this is a prerelease.' required: true type: boolean @@ -29,9 +30,11 @@ on: defaults: run: + # Set the default working directory. working-directory: src jobs: + # Computes version with gitversion.yml. compute-version: uses: ./.github/workflows/gitversion.yml with: @@ -44,7 +47,7 @@ jobs: needs: compute-version runs-on: windows-latest - steps: + steps: - uses: actions/checkout@v3 - name: Setup .NET @@ -56,16 +59,19 @@ jobs: run: dotnet restore - name: Build + # Build. Don't run restore again. run: dotnet build --no-restore -c ${{ inputs.configuration }} - name: Test run: dotnet test --no-build --verbosity normal -c ${{ inputs.configuration }} - name: Pack + # Put the nugets into the folder "package_output". Use the calculated version from the step "compute-version". if: inputs.do_pack run: dotnet pack --no-restore --no-build -o package_output -c ${{ inputs.configuration }} -p:PackageVersion=${{ needs.compute-version.outputs.package_version }} - name: Upload artifacts + # Upload all NuGet packages to GitHub. Artifact name "packages". if: inputs.do_pack uses: actions/upload-artifact@v3 with: @@ -74,6 +80,7 @@ jobs: publish: needs: build-and-pack + # Publish NuGet packages only on "push" events (merge of PR into develop) or on manual run (on release). if: ${{ inputs.do_pack && ( github.event_name == 'push' || github.event_name == 'workflow_dispatch' ) }} uses: ./.github/workflows/publish.yml with: diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 372f442..87cec44 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -1,8 +1,7 @@ -# Create a stable NuGet release. This workflow is manually triggered. +# Create a stable NuGet release. name: Create release -# Run on manual trigger only on: workflow_call: @@ -21,26 +20,29 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 0 - token: ${{ secrets.ADMIN_TOKEN }} + # Invoking workflow has to pass a personal access token with permission to pull/push on the target repo. + token: ${{ secrets.PUSH_TO_GITHUB_REPO_PAT }} - - name: Output nuget version to variable + - name: Save NuGet version to a variable for easy access. run: | echo "NUGET_VERSION=${{ needs.compute-version.outputs.package_version }}" >> $GITHUB_ENV - name: Setup git config run: | - # setup the username and email. We use the 'GitHub Actions Bot' + # Setup bot user who will own the commits. We use the 'GitHub Actions Bot'. git config user.name github-actions git config user.email github-actions@github.com - name: Start release branch run: | git checkout develop + echo Create release branch release/X.X.X git checkout -b release/${{ env.NUGET_VERSION }} - name: Commit and merge changes run: | - echo Change version number, commit and push + # Change version number in all *.csproj files. + echo Change version number, commit and push. find . -type f -name "*.csproj" -exec sed -i 's#[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]#${{ env.NUGET_VERSION }}#g' '{}' \; find . -type f -name "*.csproj" -exec sed -i 's#[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]#${{ env.NUGET_VERSION }}#g' '{}' \; @@ -70,14 +72,17 @@ jobs: - name: Push all branches run: | git checkout main + # We push branch "main" with all tags so nothing gets lost. git push origin main --tags git checkout develop git push origin develop + # We keep the support branch for bug and security fixes. git checkout support/${{ env.NUGET_VERSION }} git push origin support/${{ env.NUGET_VERSION }} build-and-publish: needs: release-flow + # Last but not least, run, package and publish from "main" to upload stable NuGet. uses: ./.github/workflows/build-and-pack.yml with: configuration: "Release" diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index 3115a09..fe525f0 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -3,6 +3,7 @@ name: Build on develop on: + # Will only be called from other workflows. workflow_call: inputs: do_pack: @@ -12,6 +13,7 @@ on: jobs: develop: + # Run build-and-pack.yml uses: ./.github/workflows/build-and-pack.yml with: configuration: "Debug" @@ -19,4 +21,5 @@ jobs: is_prerelease: true suffix: "beta" publish_target: "nuget.org" + # Pass on secrets to the next workflow. secrets: inherit diff --git a/.github/workflows/feature-branch.yml b/.github/workflows/feature-branch.yml index 97a40c0..681cd51 100644 --- a/.github/workflows/feature-branch.yml +++ b/.github/workflows/feature-branch.yml @@ -2,8 +2,8 @@ name: Build on feature/fix branch -# Run on manual trigger only on: + # Called by other workflows only. workflow_call: inputs: do_pack: @@ -12,32 +12,42 @@ on: type: boolean jobs: + # Determines the feature branch name. get-feature-branch: runs-on: ubuntu-latest + # Set the output for this job to make it accessible in the whole workflow. outputs: + # Use the step with ID "normalize" and from the ouput with name "branch_name". branch_name: ${{ steps.normalize.outputs.branch_name }} steps: - uses: actions/checkout@v3 - - # Remove feature/fix branch prefix, hyphens etc. and trim to 20 characters - name: Normalize branch name run: | + # Take the branch name by GitHub variable "ref_name". branch="${{ github.ref_name }}" + # Remove special characters. noSlashes=`echo $branch | sed "s/[^[:alnum:]]//g"` + # Remove "/feature". noFeature="${noSlashes/feature/}" + # Remove "/fix". noFix="${noFeature/fix/}" + # Shorten name to 20 characters. Set it as output of the name "branch_name". echo "::set-output name=branch_name::$( echo $noFix | cut -c 1-20 )" id: normalize feature-branch: + # Requires the step above. needs: get-feature-branch + # Run build-and-pack.yml. uses: ./.github/workflows/build-and-pack.yml with: configuration: "Debug" is_prerelease: true do_pack: ${{ inputs.do_pack }} + # Needs. gives access to the prior job's output. suffix: "alpha-${{ needs.get-feature-branch.outputs.branch_name }}" publish_target: "None" + # Pass on secrets to the next workflow. secrets: inherit diff --git a/.github/workflows/gitversion.yml b/.github/workflows/gitversion.yml index 7c5877a..336c8cd 100644 --- a/.github/workflows/gitversion.yml +++ b/.github/workflows/gitversion.yml @@ -3,7 +3,7 @@ name: GitVersion on: - workflow_call: + workflow_call: # Called by other workflows only. inputs: is_prerelease: description: 'Define if this is a prerelease.' @@ -12,44 +12,46 @@ on: suffix: description: 'Define the prerelease suffix, e.g. alpha.' required: false - type: string + type: string # Use alpha, beta, anything else or leave empty. default: "" - outputs: + outputs: # Make this workflow's output accessible to the whole workflow. package_version: description: "Computed version for the package (SemVer)" - value: ${{ jobs.nuget-version.outputs.version_output }} + value: ${{ jobs.nuget-version.outputs.version_output }} # From the job "nuget-version" get the output "version_output". defaults: run: - working-directory: src + working-directory: src # Set the default working directory. jobs: - nuget-version: + nuget-version: # Calculate the nuget version. runs-on: ubuntu-latest - outputs: - version_output: ${{ steps.nuget_version.outputs.final_version }} + outputs: # Make this workflow's output accessible to the whole workflow. + version_output: ${{ steps.nuget_version.outputs.final_version }} # From the step "nuget_version" get the output "final_version". steps: - uses: actions/checkout@v3 with: - fetch-depth: 0 + fetch-depth: 0 # Checkout the full repo. - name: Git Versioning id: gitversion - uses: paulhatch/semantic-version@v4.0.2 + uses: paulhatch/semantic-version@v4.0.2 # Run a custom action from there. with: tag_prefix: "release/" - format: "${major}.${minor}.${patch}" - - # Format is X.X.X-alpha000X-X, e.g. 8.1.0-alpha0008-42, where 0008 means 8 commits since last tag and 42 is the github run number. + format: "${major}.${minor}.${patch}" # Define the format for assembling the version number. + - name: Append prerelease suffix if: inputs.is_prerelease + # prerelease_version: {suffix from inputs}{commit count since last release tag}-{run-count, not raised by re-run} + # Example: -alpha0008-42 run: | echo "::set-output name=prerelease_suffix::-${{ inputs.suffix }}$(printf %4s ${{ steps.gitversion.outputs.increment }} | tr ' ' 0)-${{ github.run_number }}" id: prerelease_version - name: Output version + # If input "prerelease" == false, then steps.prerelease_version.outputs.prerelease_suffix will be empty. run: | echo "::set-output name=final_version::${{ steps.gitversion.outputs.version }}${{ steps.prerelease_version.outputs.prerelease_suffix }}" - id: nuget_version + id: nuget_version # Output name. diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ac48f44..83cec4b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -6,7 +6,7 @@ on: workflow_call: inputs: target: - description: 'Define the target feed to push the artifact.' + description: 'Define the target feed to push the artifact (e.g. nuget.org).' required: true type: string @@ -27,4 +27,5 @@ jobs: name: packages path: package_output - name: Push to nuget.org + # Publish all packages in "package_output". Skip if already published. Don't upload symbol packages. Get API key from secret "NUGET_FEED_PAT". run: dotnet nuget push package_output/*.nupkg --skip-duplicate --no-symbols --api-key ${{ secrets.NUGET_FEED_PAT }} --source https://api.nuget.org/v3/index.json diff --git a/README.md b/README.md index 1782123..ed165a7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ # github-actions Repository for re-usable GitHub actions. -License will be decided on soon. +Two of the workflows require secrets to be passed on to work as intended: + +* `publish.yml` pushes NuGet packages to nuget.org and needs a personal access token named `NUGET_FEED_PAT` with proper permissions +* `create-release.yml` creates commits, merges and creates branches and pushes to the target repository and need a GitHub personal access token name `PUSH_TO_GITHUB_REPO_PAT` with proper permissions