|
|
|
# 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](tut2.html), and
|
|
|
|
builds on top of the project which was started there.
|
|
|
|
|
|
|
|
## Step 0: Loosen the Previous Restrictions
|
|
|
|
|
|
|
|
In the [previous tutorial](tut2.html) 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
|
|
|
|
have not been signed-off by 2 different accounts.
|
|
|
|
|
|
|
|
## 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 are now enough credentials to combine the 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.
|