A read-only clone of the dehub project, for until dehub.dev can be brought back online.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
dehub/docs/tut3.md

8.1 KiB

Tutorial 3: Commit Sign-Off

Commit sign-off is a common pattern in vanilla git projects, where a commit must be approved by one or more people (besides the commit author themselves) in order to be allowed into the primary branch.

dehub is able to accomplish this same pattern using only the access controls which have already been covered in this tutorial series and a command which has not: dehub combine. This tutorial will guide you through using dehub combine to facilitate commit sign-off.

This tutorial assumes you have already completed Tutorial 2, and builds on top of the project which was started there.

Step 0: Loosen the Previous Restrictions

In the previous tutorial you took an existing project, added a new user tot to it, and then restricted tot to only be allowed to make commits in a certain subset of branches which excluded the main branch.

As seen in that tutorial, tot is not able to create commits for the main branch at all. In this tutorial we're going to open main back up to tot, but only with a very important caveat: tot's commits must be approved by someone else.

In the hello-world project which was used for previous tutorials, with the main branch checked out, go ahead and modify .dehub/config.yml to have the following contents:

# contents of .dehub/config.yml
---
accounts:
  - id: tut
    signifiers:
      - type: pgp_public_key_file
        path: ".dehub/tut.asc"
  - id: tot
    signifiers:
      - type: pgp_public_key_file
        path: ".dehub/tot.asc"

access_controls:
  - action: allow
    filters:
      - type: signature
        account_ids:
          - tot
      - type: branch
        pattern: tot/*

  - action: deny
    filters:
      - type: branch
        pattern: main
      - type: not
        filter:
          type: signature
          any_account: true
          count: 2

and commit the changes:

git add .dehub/config.yml
dehub commit --as tut change --descr 'require commit sign-offs in main'

The primary change was to replace the old access control denying tot the ability to commit to anything (outside of tot/* branches) with this one:

- action: deny
  filters:
    - type: branch
      pattern: main
    - type: not
      filter:
        type: signature
        any_account: true
        count: 2

There are two new things here. The first is the new fields on the signature filter: any_account replaces the account_ids field, and refers to any account which is defined in the accounts section; count declares how many accounts must have a signature on the commit for the filter to match (if not specified it defaults to 1).

The second new thing is the not filter: not wraps any other filter, and reverses whether or not it matches. In this case, it's wrapping our signature filter, such that this access control will match only if the commit does not have signature credentials from 2 different accounts.

The total effect of this access control is to deny any commits to main which do not have signature credentials from 2 different accounts. In effect, commit sign-off.

Step 1: Some Changes to Merge

In the previous tutorial tot created a new script, echo.sh, in a new branch called tot/echo-script. Check that branch out, rebase it on main (this will help in later steps), and add another script to it:

git checkout tot/echo-script
git rebase main
echo 'echo "$@" | awk "{ print toupper(\$0) }"' > echo-upper.sh
git add echo-upper.sh
dehub commit --as tot change --descr 'echo-upper.sh'

Now the tot/echo-script branch contains two commits which aren't on main, both of them signed by tot. What will happen next is that the branch's commits will be combined into a single commit, be given accreditation by both tut and tot, and added to the main branch.

Step 2: Accreditation

First, tot will accredit both commits, and unify the two descriptions in the process. To do this, you will create your first credential commit:

dehub commit --as tot credential --start HEAD^^ --descr 'add echo.sh and echo-upper.sh'

A credential commit, at its core, contains nothing except credentials for any arbitrary fingerprint. To view the credential commit you just made do: git show. You should see a commit message like:

Credential of AO3dn4Se61hq6OWy4Lm6m3MxdT2ru6TrIobuHaWJJidt

---
type: credential
commits:
- f085f13fa839ece122476601d970460ac249dc69 # these will be different
- 40a81ffb4f52dc4149570672f7f7fc053f12226a
change_description: add echo.sh and echo-upper.sh
fingerprint: AO3dn4Se61hq6OWy4Lm6m3MxdT2ru6TrIobuHaWJJidt
credentials:
- type: pgp_signature
  pub_key_id: XXX
  body: BIG LONG STRING
  account: tot

You'll notice that the credential commit's fingerprint is different than either of the two commits it accredits. This is the fingerprint is based on the combination of the two commits; it is based on the total of the file changes and the description provided by the user. The two commits are enumerated in the commits field of the payload, and the description provided by the user is stored in the change_description field.

The combined commits have now been accredited by tot, but not tut, and so they still lack a necessary credential. Have tut make a credential now:

dehub commit --as tut credential --rev HEAD

This form of the credential sub-command only accredits a single commit. When a single commit is accredited and it itself is a credential commit then the new commit which is created is merely a copy of the specified credential commit with the caller's own credential appended to the credentials list. You can see this with git show, which should look like:

Credential of AO3dn4Se61hq6OWy4Lm6m3MxdT2ru6TrIobuHaWJJidt

---
type: credential
commits:
- f085f13fa839ece122476601d970460ac249dc69 # these will be different
- 40a81ffb4f52dc4149570672f7f7fc053f12226a
change_description: add echo.sh and echo-upper.sh
fingerprint: AO3dn4Se61hq6OWy4Lm6m3MxdT2ru6TrIobuHaWJJidt
credentials:
- type: pgp_signature
  pub_key_id: XXX
  body: BIG LONG STRING
  account: tot
- type: pgp_signature
  pub_key_id: XXX
  body: BIG LONG STRING
  account: tut

There is now enough credentials to combine both commits in the tot/echo-script branch into a single commit on the main branch.

Step 3: Combination

At this point the tot/echo-script branch has the following elements in place:

  • Two change commits, which we want to combine and bring over to main.
  • A credential commit made by tot for the combined changes.
  • A credential commit made by tut for the combined changes, which includes tot's credentials.

Combining the commits and placing them on main is done with a single command:

dehub combine --start HEAD^^^^ --end HEAD --onto main

This combine command combines all changes made within the given commit range, the last change description found in that range (in this case it will be from tut's credential commit), and all credentials for that set of changes. The command combines them into a single commit which it places on the main branch. You can see the commit you've just created by doing:

git checkout main
git show

The commit should contain both of the new files, and the message should look something like:

    add echo.sh and echo-upper.sh

    ---
    type: change
    description: add echo.sh and echo-upper.sh
    fingerprint: ALOcEuKJkgIdz27z0fjF1NEbK6Y9cEh2RH4/sL3uf3oa
    credentials:
    - type: pgp_signature
      pub_key_id: XXX
      body: BIG LONG BODY
      account: tot
    - type: pgp_signature
      pub_key_id: XXX
      body: BIG LONG BODY
      account: tut

The commit is accredited by two different accounts, and so is allowed to be on the main branch. This can be verified by doing dehub verify.

You now are able to require commit sign-off and create signed-off commits! The access control settings surrounding commit sign-offs are entirely up to you and your project's needs. You can require sign-off from specific accounts, any accounts, only on specific files, only in certain branches, etc... all using the same basic access control building blocks.