diff --git a/.github/workflows/actions_template_sync.yml b/.github/workflows/actions_template_sync.yml index 0788a62e..e69b9d05 100644 --- a/.github/workflows/actions_template_sync.yml +++ b/.github/workflows/actions_template_sync.yml @@ -16,7 +16,7 @@ jobs: - name: Checkout uses: actions/checkout@v3 - name: actions-template-sync - uses: AndreasAugustin/actions-template-sync@v0.6.0-draft + uses: AndreasAugustin/actions-template-sync@v0.7.0-draft with: github_token: ${{ secrets.GITHUB_TOKEN }} source_repo_path: AndreasAugustin/template diff --git a/.github/workflows/test_hooks.yml b/.github/workflows/test_hooks.yml new file mode 100644 index 00000000..a0b0895e --- /dev/null +++ b/.github/workflows/test_hooks.yml @@ -0,0 +1,28 @@ +name: test-hooks + +on: + pull_request: + push: + # manual trigger + workflow_dispatch: + +jobs: + + test-implementation-job: + + runs-on: ubuntu-latest + + steps: + # To use this repository's private action, you must check out the repository + - + name: Checkout + uses: actions/checkout@v3 + - + name: Test action step + uses: ./ # Uses an action in the root directory + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + source_repo_path: AndreasAugustin/template.git + upstream_branch: main + is_dry_run: true + is_allow_hooks: true diff --git a/Dockerfile b/Dockerfile index 2830bbf2..c5923b49 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ FROM alpine:3.17.1 as dev ARG GH_CLI_VER=2.21.1 # install packages -RUN apk add --update --no-cache bash make git zsh curl tmux musl openssh git-lfs vim +RUN apk add --update --no-cache bash make git zsh curl tmux musl openssh git-lfs vim yq 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 diff --git a/README.md b/README.md index 7a2f8971..1ce270f5 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ This GitHub action will help you to keep track of the template changes. * Sync other public or private repository (e.q. template repositories) with the current repository * Ignore files and folders from syncing using a `.templatesyncignore` file * many configuration options +* different lifecycle hooks are supported ## Usage @@ -46,7 +47,7 @@ jobs: - name: Checkout uses: actions/checkout@v3 - name: actions-template-sync - uses: AndreasAugustin/actions-template-sync@v0.6.0-draft + uses: AndreasAugustin/actions-template-sync@v0.7.0-draft with: github_token: ${{ secrets.GITHUB_TOKEN }} source_repo_path: @@ -70,6 +71,7 @@ You will receive a pull request within your repository if there are some changes | pr_commit_msg | `[optional]` commit message in the created pull request | `false` | `chore(template): merge template changes :up:` | | hostname | `[optional]` the hostname of the repository | `false` | `github.com` | | is_dry_run | `[optional]` set to `true` if you do not want to push the changes and not want to create a PR | `false` | | +| is_allow_hooks | `[optional]` set to `true` if you want to enable lifecycle hooks. Use this with caution! | `false` | `false` | ### Example @@ -105,7 +107,7 @@ jobs: private_key: ${{ secrets.PRIVATE_KEY }} - name: actions-template-sync - uses: AndreasAugustin/actions-template-sync@v0.6.0-draft + uses: AndreasAugustin/actions-template-sync@v0.7.0-draft with: github_token: ${{ steps.generate_token.outputs.token }} source_repo_path: @@ -131,7 +133,7 @@ jobs: - name: Checkout uses: actions/checkout@v3 - name: actions-template-sync - uses: AndreasAugustin/actions-template-sync@v0.6.0-draft + uses: AndreasAugustin/actions-template-sync@v0.7.0-draft with: github_token: ${{ secrets.GITHUB_TOKEN }} source_repo_path: ${{ secrets.SOURCE_REPO_PATH }} # , should be within secrets @@ -149,6 +151,48 @@ It can also be stored inside `.github` folder. _Note: It is not possible to sync also the `.templatesyncignore` itself. Any changes from the template repository will be restored automatically._ +## Lifecycle hooks + +Different lifecycle hooks are supported. You need enable the functionality with the option `is_allow_hooks` and set it to `true` +:warning: use this functionality with caution. You can use one of the available docker images to test it out. **With great power comes great responsibility**. + +* [dockerhub andyaugustin/actions-template-sync][dockerhub-repo] +* [github andreasaugustin/actions-template-sync][github-repo] + +In addition you need a configuration file with the name `templatesync.yml` within the root of the target repository. + +Following hooks are supported (please check [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for a better understanding of the lifecycles). + +* `install` is executed after the container has started and after reading and setting up the environment. +* `prepull` is executed before the code is pulled from the source repository +* `prepush` is executed before the push is executed, right after the commit +* `prepr` is executed before the PR is done + +**Remark** The underlying OS is defined by an alpine container. +E.q. for the installation phase you need to use commands like `apk add --update --no-cache python3` + +Schema and example for the `temlatesync.yml` + +```yml +hooks: + install: + commands: + - apk add --update --no-cache python3 + - python3 --version + prepull: + commands: + - echo 'hi, we are within the prepull phase' + - echo 'maybe you want to do adjustments on the local code' + prepush: + commands: + - echo 'hi, we are within the prepush phase' + - echo 'maybe you want to add further changes and commits' + prepr: + commands: + - echo 'hi, we are within the prepr phase' + - echo 'maybe you want to change the code a bit and do another push before creating the pr' +``` + ## Debug You must create a secret named `ACTIONS_STEP_DEBUG` with the value `true` to see the debug messages set by this command in the log. @@ -214,3 +258,5 @@ specification. Contributions of any kind welcome! [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) [github-app-token]: https://github.com/tibdex/github-app-token +[dockerhub-repo]: https://hub.docker.com/r/andyaugustin/actions-template-sync +[github-repo]: https://github.com/AndreasAugustin/actions-template-sync/pkgs/container/actions-template-sync diff --git a/action.yml b/action.yml index 99520439..f3beecfe 100644 --- a/action.yml +++ b/action.yml @@ -33,6 +33,9 @@ inputs: default: 'github.com' is_dry_run: description: '[optional] set to true if you do not want to push the changes and not want to create a PR' + is_allow_hooks: + description: '[optional] set to true if you want to allow hooks. Use this functionality with caution!' + default: 'false' runs: using: 'docker' image: 'src/Dockerfile' @@ -47,3 +50,4 @@ runs: PR_COMMIT_MSG: ${{ inputs.pr_commit_msg }} HOSTNAME: ${{ inputs.hostname }} IS_DRY_RUN: ${{ inputs.is_dry_run }} + IS_ALLOW_HOOKS: ${{ inputs.is_allow_hooks }} diff --git a/src/Dockerfile b/src/Dockerfile index a6c373a4..60df6234 100644 --- a/src/Dockerfile +++ b/src/Dockerfile @@ -15,7 +15,7 @@ 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 +RUN apk add --update --no-cache bash git curl musl openssh git-lfs yq 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 diff --git a/src/sync_common.sh b/src/sync_common.sh index 246b56f8..926df766 100755 --- a/src/sync_common.sh +++ b/src/sync_common.sh @@ -39,3 +39,29 @@ warn() { info() { echo "::info::$*"; } + +####################################### +# Executes commands defined within yml file +# Arguments: +# hook -> the hook to use +# +####################################3# +cmd_from_yml_file() { + local FILE_NAME="templatesync.yml" + local HOOK=$1 + local YML_PATH=".hooks.${HOOK}.commands" + + if [ "$IS_ALLOW_HOOKS" != "true" ]; then + debug "execute cmd hooks not enabled" + else + info "execute cmd hooks enabled" + + if ! [ -x "$(command -v yq)" ]; then + err "yaml query yq is not installed. 'https://mikefarah.gitbook.io/yq/'"; + exit 1; + fi + readarray cmd_Arr < <(yq "${YML_PATH} | .[]" "${FILE_NAME}") + + for key in "${cmd_Arr[@]}"; do printf '%s\n' "$(${key})"; done + fi +} diff --git a/src/sync_template.sh b/src/sync_template.sh index b1bae122..1e2f2234 100644 --- a/src/sync_template.sh +++ b/src/sync_template.sh @@ -32,6 +32,8 @@ if [[ -n "${SRC_SSH_PRIVATEKEY_ABS_PATH}" ]]; then export GIT_SSH_COMMAND="ssh -i ${SRC_SSH_PRIVATEKEY_ABS_PATH}" fi +cmd_from_yml_file "install" + TEMPLATE_SYNC_IGNORE_FILE_PATH=".templatesyncignore" TEMPLATE_REMOTE_GIT_HASH=$(git ls-remote "${SOURCE_REPO}" HEAD | awk '{print $1}') NEW_TEMPLATE_GIT_HASH=$(git rev-parse --short "${TEMPLATE_REMOTE_GIT_HASH}") @@ -59,6 +61,8 @@ fi echo "::endgroup::" +cmd_from_yml_file "prepull" + echo "::group::Pull template" debug "create new branch from default branch with name ${NEW_BRANCH}" git checkout -b "${NEW_BRANCH}" @@ -108,12 +112,15 @@ git commit -m "${PR_COMMIT_MSG}" echo "::endgroup::" push_and_create_pr () { + cmd_from_yml_file "prepush" if [ "$IS_DRY_RUN" != "true" ]; then echo "::group::push changes and create PR" debug "push changes" git push --set-upstream origin "${NEW_BRANCH}" + cmd_from_yml_file "prepr" + gh pr create \ --title "${PR_TITLE}" \ --body "Merge ${SOURCE_REPO_PATH} ${NEW_TEMPLATE_GIT_HASH}" \ diff --git a/templatesync.yml b/templatesync.yml new file mode 100644 index 00000000..ae3409d5 --- /dev/null +++ b/templatesync.yml @@ -0,0 +1,11 @@ +# validate + +hooks: + install: + commands: + - echo 'hi, we are within the prepush phase' + + prepush: + commands: + - echo 'hi, we are within the prepush phase' + - echo 'maybe you want to add further changes and commits'