From 7a33121add81c181094cdb290a4cc9bf654c918d Mon Sep 17 00:00:00 2001 From: Marc Siebeneicher Date: Tue, 3 Jan 2023 12:25:34 +0100 Subject: [PATCH] feat(gh-auth): add gh auth login and credential helper (#239) * feat(gh-auth): add gh auth login and credential helper * feat(gh-auth): add own source_repo_github_token handling for template repo * chore(): add test for PAT :rocket: fix(): small fix for private repos :bug: * chore(gh-cli): update gh cli version to latest :rocket: * # This is a combination of 6 commits. # This is the 1st commit message: parent 9b742247ad7218490f30978af7abf4d6fc4ed9ad author Andy Augustin 1672219390 +0100 committer Andy Augustin 1672592292 +0100 gpgsig -----BEGIN PGP SIGNATURE----- iQGzBAABCAAdFiEEApgnwt2TStNZl6Y9UpE0XzZ/UkgFAmOxu6QACgkQUpE0XzZ/ UkjAzgv/cWh9hE7VLkLM1nVmra945WUkOfWXHnCUnrsOWsxxSOkH1r2mLxZdnWtg BlFc4RciJAB39Nv1WBUt+hGBGOdYWcV1lxgSIpn+vNXd9/5xciEThRk9T1piHj+x xnZU2rW0dLlnEnFlIX1qkKeD+rjclXw46umjMgqwIF0vQSx5cR9y8sDCiqRGg2Fv G/k/xLoQwah0Ve8nwqd6dLwNYXl8cFBfvuZaGV/dt1+5BDl4J5mPYg4trxKx5xnB fTxTQ0G/qOa1OInW04EReJWZwQaGvyx5PqEFk0ESk8MuzFytfVVRCnHwdP/QvLO7 S7Y79wUBAQfHvSlwOgBtlQc5eFOiKoxahUhJIcCMLw1r2+nRjuPAA0j07v6nmjDM sfxyVSpnYnKGAfGrYGboOHuEjqKegKdY3oIQFL/Ivln7kmLxGrFcpQ+QMTEJUsLw 2AB+Yf+tJyQXnx8AiGQRnVlXW3FRCOQhCxK2zXMUpzwAsKcKYNnaKoM6jDN7EzRQ fZrB76EK =yGb3 -----END PGP SIGNATURE----- feat(): make gh auth login conditional for separate source repo token :rocket: style(lint): fix lint issues :bug: feat(): add PAT :rocket: doc(): update docs :pencil: feat(): add option for PAT :rocket: feat(): add option for PAT :rocket: * parent 9b742247ad7218490f30978af7abf4d6fc4ed9ad author Andy Augustin 1672219390 +0100 committer Andy Augustin 1672592292 +0100 gpgsig -----BEGIN PGP SIGNATURE----- iQGzBAABCAAdFiEEApgnwt2TStNZl6Y9UpE0XzZ/UkgFAmOxu6QACgkQUpE0XzZ/ UkjAzgv/cWh9hE7VLkLM1nVmra945WUkOfWXHnCUnrsOWsxxSOkH1r2mLxZdnWtg BlFc4RciJAB39Nv1WBUt+hGBGOdYWcV1lxgSIpn+vNXd9/5xciEThRk9T1piHj+x xnZU2rW0dLlnEnFlIX1qkKeD+rjclXw46umjMgqwIF0vQSx5cR9y8sDCiqRGg2Fv G/k/xLoQwah0Ve8nwqd6dLwNYXl8cFBfvuZaGV/dt1+5BDl4J5mPYg4trxKx5xnB fTxTQ0G/qOa1OInW04EReJWZwQaGvyx5PqEFk0ESk8MuzFytfVVRCnHwdP/QvLO7 S7Y79wUBAQfHvSlwOgBtlQc5eFOiKoxahUhJIcCMLw1r2+nRjuPAA0j07v6nmjDM sfxyVSpnYnKGAfGrYGboOHuEjqKegKdY3oIQFL/Ivln7kmLxGrFcpQ+QMTEJUsLw 2AB+Yf+tJyQXnx8AiGQRnVlXW3FRCOQhCxK2zXMUpzwAsKcKYNnaKoM6jDN7EzRQ fZrB76EK =yGb3 -----END PGP SIGNATURE----- feat(): make gh auth login conditional for separate source repo token :rocket: style(lint): fix lint issues :bug: doc(): update docs :pencil: feat(): add option for PAT :rocket: trial(): add permissions :bug: trial(): new trial for accessing private repo with PAT :up: * feat(gh-auth): add gh auth login and credential helper * feat(gh-auth): add own source_repo_github_token handling for template repo * fix(merge): fix merge conflicts * fix(): small logic fix in script Signed-off-by: andy Augustin * fix(): small logic fix in script Signed-off-by: andy Augustin * Update test_ssh.yml Signed-off-by: andy Augustin * Update test.yml Signed-off-by: andy Augustin * Update entrypoint.sh Signed-off-by: andy Augustin * fix(): fix for GITHUB_TOKEN env variable :bug: * chore: code clean up Signed-off-by: andy Augustin Co-authored-by: Andy Augustin Co-authored-by: andy Augustin --- .github/workflows/test.yml | 6 ++++-- .github/workflows/test_pat.yml | 25 +++++++++++++++++++++++++ .github/workflows/test_ssh.yml | 6 ++++-- Dockerfile | 9 +++++++-- README.md | 32 +++++++++++++++++++++++++++++++- src/Dockerfile | 2 +- src/entrypoint.sh | 19 ++++++++++++------- src/sync_template.sh | 4 +++- 8 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/test_pat.yml mode change 100755 => 100644 src/entrypoint.sh mode change 100755 => 100644 src/sync_template.sh diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6dd457d..a7973e9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,9 +14,11 @@ jobs: steps: # To use this repository's private action, you must check out the repository - - name: Checkout + - + name: Checkout uses: actions/checkout@v3 - - name: Test action step + - + name: Test action step uses: ./ # Uses an action in the root directory with: github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test_pat.yml b/.github/workflows/test_pat.yml new file mode 100644 index 0000000..74ae5d2 --- /dev/null +++ b/.github/workflows/test_pat.yml @@ -0,0 +1,25 @@ +name: test-pat + +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 PAT + uses: ./ # Uses an action in the root directory + with: + github_token: ${{ secrets.SOURCE_REPO_PAT }} + source_repo_path: ${{ secrets.SOURCE_REPO_PATH_TEST }} # , should be within secrets + is_dry_run: true diff --git a/.github/workflows/test_ssh.yml b/.github/workflows/test_ssh.yml index bf098a2..6a87ed8 100644 --- a/.github/workflows/test_ssh.yml +++ b/.github/workflows/test_ssh.yml @@ -13,9 +13,11 @@ jobs: steps: # To use this repository's private action, you must check out the repository - - name: Checkout + - + name: Checkout uses: actions/checkout@v3 - - name: Test action step ssh + - + name: Test action step ssh uses: ./ # Uses an action in the root directory with: github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/Dockerfile b/Dockerfile index edac259..ea67642 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,10 +3,10 @@ ###################################### FROM alpine:3.17.0 as dev -ARG GH_CLI_VER=2.15.0 +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 +RUN apk add --update --no-cache bash make git zsh curl tmux musl openssh git-lfs vim 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 @@ -17,6 +17,11 @@ RUN echo "set-option -g default-shell /bin/zsh" >> /root/.tmux.conf # install oh-my-zsh RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" +ADD src/*.sh /bin/ +RUN chmod +x /bin/entrypoint.sh \ + && chmod +x /bin/sync_template.sh \ + && chmod +x /bin/sync_common.sh + RUN mkdir -p /root/.ssh \ && ssh-keyscan -t rsa github.com >> /root/.ssh/known_hosts diff --git a/README.md b/README.md index 5435b8a..96b5b12 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,33 @@ You can use all [triggers][action-triggers] which are supported for GitHub actio If you have a private template repository. +#### Using github app + +You can create and use a [GitHub App][github-app] to handle the access to your private repository. +To generate a token for your app you can use a separate action like [tibdex/github-app-token][github-app-token]. + +```yaml +jobs: + repo-sync: + runs-on: ubuntu-latest + + steps: + - name: Generate token to read from source repo # see: https://github.com/tibdex/github-app-token + id: generate_token + uses: tibdex/github-app-token@v1 + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.PRIVATE_KEY }} + + - name: actions-template-sync + uses: AndreasAugustin/actions-template-sync@v0.5.5-draft + with: + github_token: ${{ steps.generate_token.outputs.token }} + source_repo_path: + upstream_branch: # defaults to main + pr_labels: ,[,...] # optional, no default +``` + #### SSH You have various options to use ssh keys with GitHub. @@ -115,7 +142,7 @@ jobs: ## Ignore Files -Create a `.templatesyncignore` file. Just like writing a `.gitignore` file, follow the [glob pattern](https://en.wikipedia.org/wiki/Glob_(programming)) +Create a `.templatesyncignore` file. Just like writing a `.gitignore` file, follow the [glob pattern][glob-pattern] in defining the files and folders that should be excluded from syncing with the template repository. It can also be stored inside `.github` folder. @@ -184,3 +211,6 @@ specification. Contributions of any kind welcome! [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 [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) +[github-app-token]: https://github.com/tibdex/github-app-token diff --git a/src/Dockerfile b/src/Dockerfile index c5771a4..40e8693 100644 --- a/src/Dockerfile +++ b/src/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:3.17.0 -ARG GH_CLI_VER=2.15.0 +ARG GH_CLI_VER=2.21.1 # TODO(anau) change user ARG GITHUB_URL="https://github.com/AndreasAugustin/actions-template-sync" diff --git a/src/entrypoint.sh b/src/entrypoint.sh old mode 100755 new mode 100644 index b0bb01d..0716e03 --- a/src/entrypoint.sh +++ b/src/entrypoint.sh @@ -6,20 +6,21 @@ set -x # shellcheck source=src/sync_common.sh source sync_common.sh -[ -z "${GITHUB_TOKEN}" ] && { - err "Missing input 'github_token: \${{ secrets.GITHUB_TOKEN }}'."; - exit 1; -}; +if [[ -z "${GITHUB_TOKEN}" ]]; then + err "Missing input 'github_token: \${{ secrets.GITHUB_TOKEN }}'."; + exit 1; +fi if [[ -z "${SOURCE_REPO_PATH}" ]]; then err "Missing input 'source_repo_path: \${{ input.source_repo_path }}'."; exit 1 fi -SOURCE_REPO_HOSTNAME="${HOSTNAME:-github.com}" +DEFAULT_REPO_HOSTNAME="github.com" +SOURCE_REPO_HOSTNAME="${HOSTNAME:-${DEFAULT_REPO_HOSTNAME}}" -# In case of private template repository this will be overwritten -SOURCE_REPO_PREFIX="https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@${SOURCE_REPO_HOSTNAME}/" +# In case of ssh template repository this will be overwritten +SOURCE_REPO_PREFIX="https://${SOURCE_REPO_HOSTNAME}/" function ssh_setup() { echo "::group::ssh setup" @@ -41,6 +42,8 @@ function ssh_setup() { # Forward to /dev/null to swallow the output of the private key if [[ -n "${SSH_PRIVATE_KEY_SRC}" ]] &>/dev/null; then ssh_setup +elif [[ "${SOURCE_REPO_HOSTNAME}" != "${DEFAULT_REPO_HOSTNAME}" ]]; then + gh auth login --git-protocol "https" --hostname "${SOURCE_REPO_HOSTNAME}" --with-token <<< "${GITHUB_TOKEN}" fi export SOURCE_REPO="${SOURCE_REPO_PREFIX}${SOURCE_REPO_PATH}" @@ -55,6 +58,8 @@ function git_init() { git config --global --add safe.directory /github/workspace git lfs install + gh auth setup-git --hostname "${SOURCE_REPO_HOSTNAME}" + gh auth status --hostname "${SOURCE_REPO_HOSTNAME}" echo "::endgroup::" } diff --git a/src/sync_template.sh b/src/sync_template.sh old mode 100755 new mode 100644 index cf49299..68f6294 --- a/src/sync_template.sh +++ b/src/sync_template.sh @@ -63,6 +63,7 @@ echo "::group::Pull template" debug "create new branch from default branch with name ${NEW_BRANCH}" git checkout -b "${NEW_BRANCH}" debug "pull changes from template" + # TODO(anau) eventually make squash optional git pull "${SOURCE_REPO}" --allow-unrelated-histories --squash --strategy=recursive -X theirs echo "::endgroup::" @@ -103,7 +104,8 @@ echo "::endgroup::" push_and_create_pr () { if [ "$IS_DRY_RUN" != "true" ]; then - echo "::group::push changes and create PR" + + echo "::group::push changes and create PR" debug "push changes" git push --set-upstream origin "${NEW_BRANCH}"