cbcrouse / Versioning.NET

A dotnet tool that automatically increments versions in csproj files based on git commit hints.
MIT License
19 stars 3 forks source link

Add support for GPG key commit signing #34

Open 0nary opened 1 year ago

0nary commented 1 year ago

Describe the bug When I use this tool on some repository, I can see the commit for the versioning. And when I check the commit of the tag I have this message display : "This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository."

To Reproduce Steps to reproduce the behavior: Don't know. Can be see at :

JBBianchi commented 1 year ago

To give more details, the executed command was: dotnet-version increment-version-with-git -g "." --branch-name main --author-email actions@github.com

See https://github.com/neuroglia-io/framework/actions/runs/3135533373/jobs/5091322057 for instance

From what I understood from the IncrementVersionWithGitIntegrationCommand handling https://github.com/cbcrouse/Versioning.NET/blob/4f37fb0fc8b68ce610e9e5ac5ba4e054c8d260eb/src/Application/GitVersioning/Handlers/IncrementVersionWithGitIntegrationHandler.cs#L90

The commit should have been pushed to main.

JBBianchi commented 1 year ago

Both main branches of the said projects are "protected", not allowing unsigned commit. The GitHub action bot doesn't sign the commits so they are not attached to main I guess.

JBBianchi commented 1 year ago

Trying to sign commits/tags/pushes with crazy-max/ghaction-import-gpg@v4 doesn't seem to work so far.

Here is a sample (secret BOT_GPG_PRIVATE_KEY is required for the pipeline to "work"):

name: auto-version

on:
  push:
    branches: [ main ]    

jobs:
  build:
    runs-on: ubuntu-18.04
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Import GPG key
        id: import-gpg
        uses: crazy-max/ghaction-import-gpg@v4
        with:
          gpg_private_key: ${{ secrets.BOT_GPG_PRIVATE_KEY }}
          git_config_global: true
          git_user_signingkey: true
          git_commit_gpgsign: true
          git_tag_gpgsign: true

      - name: Reset Origin
        run: |
          git remote set-url origin "https://${{ steps.import-gpg.outputs.name }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git"
          git checkout ${{ github.ref_name }}

      - name: Install Versioning.NET
        run: |
          dotnet tool install --global Versioning.NET

      - name: Increment Version
        run: |
          dotnet-version increment-version-with-git -g "." --branch-name ${{ github.ref_name }} --author-email ${{ steps.import-gpg.outputs.email }}
JBBianchi commented 1 year ago

I had to work around, attach my personal repo to an organisation, set the bot as admin and allow the admins to bypass the protected branch restrictions (signed commits & approved PRs only).

Here is the resulting pipeline:

# IMPORTANT NOTES:
# For a repo using "protected branches" strategies (approved PR & signed commits or other checks),
# it is mandatory to use a "power" account PAT because the default git action bot/token
# doesn't have the required permissions to bypass the aforementioned conditions.
# To bypass those conditions, "Do not allow bypassing the above settings" must be unchecked
# in the repo > Settings > Branches > main .
#
# In the case of a personal repo, the repo owner will have to give a PAT of its own account
# as there is no other "admin" possible for the repo, only "collaborators."
#
# In the case of an organization repo, an other account can be used. If the org have a free plan, that
# account will have to be given the "admin" role. If the org have a paid plan, a more restrictive
# "custom role" could be forged and assigned to that user.
#
# In any case, 3 secrets will have to be added to the repo > Settings > Secrets > Actions
# - BOT_USERNAME : the GitHub username of the "power account"
# - BOT_EMAIL : the GitHub email address of the "power account"
# - BOT_PAT : the personal access token of the "power account" with enough permissions associated
#
# For now, `dotnet-version` doesn't seem to support signing commits/tags but, in the future
# `BOT_USERNAME` and `BOT_EMAIL` could be replaced by `BOT_GPG_PRIVATE_KEY` instead.
# In that case, when generating the GPG key, use the bot username and email when asked
# for a name and email (https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key)
# After exporting the public key and associating it to the GH account, export the private key using (and set the repo's secret):
# `gpg --armor --export-secret-key bot@email.com`
# where `bot@email.com` is the email configured in the previous step. (you might need to add `-w0` to the command).

name: Auto versioning .NET

on:
  push:
    branches: [ main ]

jobs:
  version:
    runs-on: ubuntu-18.04
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
          token: ${{ secrets.BOT_PAT }}

      - name: Reset Origin
        run: |
          git remote set-url origin "https://${{ secrets.BOT_USERNAME }}:${{ secrets.BOT_PAT }}@github.com/${{ github.repository }}.git"
          git checkout ${{ github.ref_name }}

      - name: Install Versioning.NET
        run: |
          dotnet tool install --global Versioning.NET

      - name: Increment Version
        run: |
          dotnet-version increment-version-with-git -g "." --branch-name ${{ github.ref_name }} --author-email ${{ secrets.BOT_EMAIL }}

      # The following could be used to sign the commit/tag but `dotnet-version` doesn't seem to sign the said commit.
      # It could also be used to infer the bot user name (${{ steps.import-gpg.outputs.name }}) and 
      # email address (${{ steps.import-gpg.outputs.email }}) from the private key ${{ secrets.BOT_GPG_PRIVATE_KEY }}.
      # For now, instead of the private key, two secrets will be used, ${{ secrets.BOT_USERNAME }} and ${{ secrets.BOT_EMAIL }}
      # In the future, if `dotnet-version` support signing commits/tags, it would be better to use the following.

      # - name: Import GPG key
      #   id: import-gpg
      #   uses: crazy-max/ghaction-import-gpg@v4
      #   with:
      #     gpg_private_key: ${{ secrets.BOT_GPG_PRIVATE_KEY }}
      #     git_config_global: true
      #     git_user_signingkey: true
      #     git_commit_gpgsign: true
      #     git_tag_gpgsign: true

      # - name: Reset Origin
      #   run: |
      #     git remote set-url origin "https://${{ steps.import-gpg.outputs.name }}:${{ secrets.BOT_PAT }}@github.com/${{ github.repository }}.git"
      #     git checkout ${{ github.ref_name }}
      ##  + git config user/email/signkey ???

      # - name: Install Versioning.NET
      #   run: |
      #     dotnet tool install --global Versioning.NET

      # - name: Increment Version
      #   run: |
      #     dotnet-version increment-version-with-git -g "." --branch-name ${{ github.ref_name }} --author-email ${{ steps.import-gpg.outputs.email }}

@cbcrouse I still didn't figure out why I wasn't able to sign the commit/tag after importing the GPG key and enabling it "globally". If you could investigate, that would be great.

cbcrouse commented 1 year ago

@JBBianchi Sorry to get back to you so late on this, I have been quite busy. It looks like there may be a couple reasons for this not working.

  1. It's possible that the author mail needs to be associated with the GPG key based on this documentation.
  2. It also looks like signing commits must be enabled in the git config and then -S must be supplied with the git commit command to actually sign the commit.

I will work on getting commit signing supported which will start showing up as Verified in the commit history for validation. image

I will also write up some documentation in the Wiki regarding signing after I do the investigation and get it working so you'll know exactly what you need to do.

cbcrouse commented 1 year ago

This will be nice once GitHub supports something like what is suggested here: https://github.com/actions/runner/issues/667

cbcrouse commented 1 year ago

I had to work around, attach my personal repo to an organisation, set the bot as admin and allow the admins to bypass the protected branch restrictions (signed commits & approved PRs only).

Signing commits appears to not be supported by LibGit2Sharp in any convenient way. Someone did add a contribution that shows how it can read a signed commit, but no explicit instruction on how to utilize those APIs within the library to create a GPG signed commit. Unfortunately, this may take some time to support, so you will have to continue using your workaround.