Skip to content

Commit

Permalink
feat: ✨ (#204) gpg sign (#436)
Browse files Browse the repository at this point in the history
* feat: ✨ (#204) add gnupg to docker image

* feat: ✨ (#204) add option to sign commits

* fix: 🐛 (#204) issue with tty

* fix: 🐛 (#204) fix issue with no tty

* fix: 🐛 (#204) fix issue with no passphrase

* fix: 🐛 (#204) trial

* fix: 🐛 (#204) trial for fix

* fix: 🐛 (#204) fix

* fix: 🐛 (#204) trial

* fix: 🐛 (#204) add pinentry mode loopback

* fix: 🐛 (#204)

* feat: ✨ (#204) add signoff and tig

* fix: 🐛 (#204) fix commit

* fix: 🐛 (#204)

* fix: 🐛 (#204) trial

* fix: 🐛 (#204)

* fix: 🐛 trial for gpg sign

* fix: 🚧 wip

* fix: 🚧 WIP

* fix: 🚧 WIP

* fix: 🐛 disable gpg with passphrase
  • Loading branch information
AndreasAugustin authored Feb 22, 2024
1 parent a3f502d commit 99aefe5
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 9 deletions.
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ FROM alpine:3.19.1 as dev
ARG GH_CLI_VER=2.34.0

# install packages
RUN apk add --update --no-cache bash make git zsh curl tmux musl openssh git-lfs vim yq
RUN apk add --update --no-cache bash make git zsh curl tmux musl openssh git-lfs vim yq gnupg tig

RUN wget https://github.com/cli/cli/releases/download/v${GH_CLI_VER}/gh_${GH_CLI_VER}_linux_386.tar.gz -O ghcli.tar.gz
RUN tar --strip-components=1 -xf ghcli.tar.gz
Expand All @@ -20,7 +20,8 @@ RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh
ADD src/*.sh /bin/
RUN chmod +x /bin/entrypoint.sh \
&& chmod +x /bin/sync_template.sh \
&& chmod +x /bin/sync_common.sh
&& chmod +x /bin/sync_common.sh \
&& chmod +x /bin/gpg_no_tty.sh

RUN mkdir -p /root/.ssh \
&& ssh-keyscan -t rsa github.com >> /root/.ssh/known_hosts
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ markdownlint: ## Validate markdown files
zsh: ## open dev container with build environment
docker-compose run --service-ports dev /bin/zsh

.PHONY: prod
prod: ## run the prod docker image with bash
docker-compose run prod

.PHONY: prune
prune: ## delete the whole environment
docker-compose down -v --rmi all --remove-orphans
Expand Down
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ jobs:
| git_user_name | `[optional]` set the committer git user.name | `false` | `${GITHUB_ACTOR}` |
| git_user_email | `[optional]` set the committer git user.email | `false` | `github-action@actions-template-sync.noreply.${SOURCE_REPO_HOSTNAME}` |
| git_remote_pull_params | `[optional]` set remote pull parameters | `false` | `--allow-unrelated-histories --squash --strategy=recursive -X theirs` |
| gpg_private_key | `[optional]` set if you want to sign commits | `false` | |

### Docker

Expand Down Expand Up @@ -293,6 +294,65 @@ E.g. when you like to disable the sync for all files with exceptions, you need t
*
```

## Sign commits

It is recommended to [sign your commits][devto-sign-commits]. This action is able to sign commits.

First, [generate a GPG key][github-create-gpg-key] and export the GPG private key as an ASCII armored version to your clipboard:

```bash
# macOS
gpg --armor --export-secret-key jon@doe.example | pbcopy
# Ubuntu (assuming GNU base64)
gpg --armor --export-secret-key jon@doe.example -w0 | xclip
# Arch
gpg --armor --export-secret-key jon@doe.example | xclip -selection clipboard -i
# FreeBSD (assuming BSD base64)
gpg --armor --export-secret-key jon@doe.example | xclip
```

:warning: the gpg username and email must match the `git_user_name` and `git_user_email` parameters.
Paste your clipboard as a [secret][github-create-secret] named `GPG_PRIVATE_KEY` for example.
:warning: currently a pgp key with passphrase is not supported (yet).

```yaml
# File: .github/workflows/template-sync.yml
on:
# cronjob trigger
schedule:
- cron: "0 0 1 * *"
# manual trigger
workflow_dispatch:
jobs:
repo-sync:
runs-on: ubuntu-latest
# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs
permissions:
contents: write
pull-requests: write
steps:
# To use this repository's private action, you must check out the repository
- name: Checkout
uses: actions/checkout@v4
- name: actions-template-sync
uses: AndreasAugustin/actions-template-sync@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
source_repo_path: <owner/repo>
git_user_name: # add the gpg username
git_user_email: # add the gpg email
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
# uncomment if your key has a passpharse
# gpg_passpharse: ${{ secrets.GPG_PASSPHRASE }}
```

## Lifecycle hooks

Different lifecycle hooks are supported. You need to enable the functionality with the option `is_allow_hooks` and set it to `true`
Expand Down Expand Up @@ -443,6 +503,7 @@ There are other great tools available within GitHub. Here you can find a compari
| dry run | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: |
| ignore files | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: |
| creates a PR | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: |
| sign commits | :heavy_check_mark: | :x: | :x: | :x: |
| remarks | The action is placed within the target repositories | The action is placed within the target repositories | CLI meant for local use | The action will be based within the base repository with a list of dependent repositories |

## DEV
Expand Down Expand Up @@ -516,6 +577,7 @@ specification. Contributions of any kind are welcome!
[self-usage]: https://github.com/AndreasAugustin/actions-template-sync/blob/main/.github/workflows/actions_template_sync.yml
[pr-labels]: https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/managing-labels
[devto-example]: https://dev.to/andreasaugustin/github-actions-template-sync-1g9k
[devto-sign-commits]: https://dev.to/andreasaugustin/git-how-and-why-to-sign-commits-35dn
[github-example]: https://github.com/AndreasAugustin/teaching/blob/main/docs/git/git_action_sync.md
[github-app]: https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-github-apps
[glob-pattern]: https://en.wikipedia.org/wiki/Glob_(programming)
Expand All @@ -530,3 +592,4 @@ specification. Contributions of any kind are welcome!
[dotdc-blog]: https://0xdc.me/blog/github-templates-and-repository-sync/
[github-create-pat]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token
[github-create-secret]: https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository
[github-create-gpg-key]: https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ inputs:
description: "[optional] set the committer git user.email for the merge commit"
git_remote_pull_params:
description: "[optional] set the pull parameters for the remote repository"
gpg_private_key:
description: "[optional] set the gpg private key if you want to sign your commits"
runs:
using: "docker"
image: "src/Dockerfile"
Expand All @@ -74,3 +76,4 @@ runs:
GIT_USER_NAME: ${{ inputs.git_user_name }}
GIT_USER_EMAIL: ${{ inputs.git_user_email }}
GIT_REMOTE_PULL_PARAMS: ${{ inputs.git_remote_pull_params }}
GPG_PRIVATE_KEY: ${{ inputs.gpg_private_key }}
6 changes: 6 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ services:
volumes:
- .:/app/
working_dir: /app/

prod:
build:
context: ./src/
tty: true
entrypoint: ["/bin/bash"]
7 changes: 4 additions & 3 deletions src/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@ LABEL org.opencontainers.image.title="actions-template-sync image"
LABEL org.opencontainers.image.description="contains actions-template-sync"

# install packages
RUN apk add --update --no-cache bash git curl musl openssh git-lfs yq
RUN apk add --update --no-cache bash git curl musl openssh git-lfs yq gnupg tig

RUN wget https://github.com/cli/cli/releases/download/v${GH_CLI_VER}/gh_${GH_CLI_VER}_linux_386.tar.gz -O ghcli.tar.gz
RUN tar --strip-components=1 -xf ghcli.tar.gz

ADD *.sh /bin/
RUN chmod +x /bin/entrypoint.sh \
&& chmod +x /bin/sync_template.sh \
&& chmod +x /bin/sync_common.sh
&& chmod +x /bin/sync_common.sh \
&& chmod +x /bin/gpg_no_tty.sh

RUN mkdir -p /root/.ssh \
&& ssh-keyscan -t rsa github.com >> /root/.ssh/known_hosts

ENTRYPOINT ["/bin/entrypoint.sh"]
ENTRYPOINT ["/bin/bash", "/bin/entrypoint.sh"]
21 changes: 20 additions & 1 deletion src/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
#!/usr/bin/env bash
set -e
# set -u
# set -x
Expand Down Expand Up @@ -41,6 +41,21 @@ function ssh_setup() {
echo "::endgroup::"
}

function gpg_setup() {
echo "::group::gpg setup"
info "start prepare gpg"
echo -e "$GPG_PRIVATE_KEY" | gpg --import --batch
for fpr in $(gpg --list-key --with-colons "${GIT_USER_EMAIL}" | awk -F: '/fpr:/ {print $10}' | sort -u); do echo -e "5\ny\n" | gpg --no-tty --command-fd 0 --expert --edit-key "$fpr" trust; done

KEY_ID="$(gpg --list-secret-key --with-colons "${GIT_USER_EMAIL}" | awk -F: '/sec:/ {print $5}')"
git config --global user.signingkey "${KEY_ID}"
git config --global commit.gpgsign true
git config --global gpg.program /bin/gpg_no_tty.sh

info "done prepare gpg"
echo "::endgroup::"for fpr in
}

# Forward to /dev/null to swallow the output of the private key
if [[ -n "${SSH_PRIVATE_KEY_SRC}" ]] &>/dev/null; then
ssh_setup
Expand Down Expand Up @@ -73,5 +88,9 @@ function git_init() {

git_init

if [[ -n "${GPG_PRIVATE_KEY}" ]] &>/dev/null; then
gpg_setup
fi

# shellcheck source=src/sync_template.sh
source sync_template.sh
11 changes: 11 additions & 0 deletions src/gpg_no_tty.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env bash

if [[ -n "${GPG_PASSPHRASE}" ]] &>/dev/null; then
# echo -e "${GPG_PASSPHRASE}" | gpg --pinentry-mode loopback --batch --yes --passphrase-fd 0 "$@" <&0
echo "::error::currently gpg with passphrase is not supported"
exit 1
else
gpg --pinentry-mode loopback --yes --batch "$@" <&0
fi

exit $?
2 changes: 1 addition & 1 deletion src/sync_common.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
#!/usr/bin/env bash

set -e
# set -u
Expand Down
4 changes: 2 additions & 2 deletions src/sync_template.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#! /usr/bin/env bash
#!/usr/bin/env bash

set -e
# set -u
Expand Down Expand Up @@ -139,7 +139,7 @@ if git diff --quiet && git diff --staged --quiet; then
exit 0
fi

git commit -m "${PR_COMMIT_MSG}"
git commit --signoff -m "${PR_COMMIT_MSG}"

echo "::endgroup::"

Expand Down

0 comments on commit 99aefe5

Please sign in to comment.