Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add options to create a deploy-key #111

Merged
merged 23 commits into from
Oct 27, 2024
Merged

Conversation

RobertBoes
Copy link
Contributor

@RobertBoes RobertBoes commented Jul 24, 2024

Forge only allows github (or other providers) to be deployed using a personal connection, however the custom option also allows deploying with deploy-keys.

The strategy here is to first create a deploy-key on the Forge site, then install that key on the GitHub repo.

This adds two new env variables:

  • FORGE_GITHUB_DEPLOY_KEY which is a boolean, indicating if deploy-keys should be used
  • FORGE_GIT_REPOSITORY_URL the custom URL used when deploying using deploy-keys

One downside is that the GitHub actions token does not have Administration permissions, so it cannot create a deploy key. The easiest solution I found was to use a github app. How to create an app is explained here: https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/making-authenticated-api-requests-with-a-github-app-in-a-github-actions-workflow.

When creating the app you'd need to give it the "Administration" repository permissions (write) permission as mentioned here: https://docs.github.com/en/rest/deploy-keys/deploy-keys?apiVersion=2022-11-28#create-a-deploy-key

If you also set GIT_COMMENT_ENABLED you'd need to grant either "Issues" repository permissions (write) or "Pull requests" repository permissions (write), as mentioned here: https://docs.github.com/en/rest/issues/comments?apiVersion=2022-11-28#create-an-issue-comment

The provisioning script would then look like the following:

name: preview-provision
on:
  pull_request:
    types: [opened, edited, synchronize, reopened, ready_for_review]
jobs:
  harbor-provision:
    if: |
      github.event.pull_request.draft == false
    runs-on: ubuntu-latest
    container:
      image: kirschbaumdevelopment/laravel-test-runner:8.2
    steps:
      # We first need to generate a token
      - name: Generate a token
        id: generate-token
        uses: actions/create-github-app-token@v1
        with:
          app-id: ${{ vars.APP_ID }}
          private-key: ${{ secrets.APP_PRIVATE_KEY }}
      - name: Install Harbor via Composer
        run: composer global require mehrancodes/laravel-harbor -q
      - name: Start Provisioning
        env:
            FORGE_TOKEN: ${{ secrets.FORGE_API_TOKEN }}
            FORGE_SERVER: ${{ secrets.FORGE_SERVER_ID }}
            FORGE_GIT_REPOSITORY: ${{ github.repository }}
            FORGE_GIT_BRANCH: ${{ github.head_ref }}
            FORGE_DOMAIN: harbor.com

            # Indicates we want to deploy using deploy keys
            FORGE_GITHUB_DEPLOY_KEY: true

            # The git URL to be used in Forge
            FORGE_GIT_REPOSITORY_URL: "[email protected]:${{ github.repository }}.git"

            # We have to set the provider to 'custom', since Forge otherwise wouldn't use the deploy-key
            FORGE_GIT_PROVIDER: custom

            # We set the token we got from our app, instead of the default token
            # As the default actions token does not have permissions to create a deploy key
            GIT_TOKEN: ${{ steps.generate-token.outputs.token }}
        run: harbor provision

ToDo:

@RobertBoes
Copy link
Contributor Author

Going to look for a different strategy to implement this. The GIT_TOKEN (GitHub actions token) doesn't have administration (write) permissions, so using that token wouldn't be possible. Going to look at an app integration for this. Fine grained tokens would work too, but those have a limited lifetime, requiring updating those tokens every 30 days (or whatever lifetime one picks for the token)

Github only gives an error message, the error code is "custom" for all validation errors, the response status is also just 422. So easiest is to check the message, unfortunately
Copy link

@jotaesteves jotaesteves left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, I dont know about using the github service instead of a github action, so @mehrancodes do give it a full review and final approval

@RobertBoes RobertBoes marked this pull request as ready for review August 2, 2024 13:31
@mehrancodes mehrancodes added the enhancement New feature or request label Aug 24, 2024
@mehrancodes
Copy link
Owner

mehrancodes commented Aug 24, 2024

Hi @RobertBoes, I tested this PR on a sample repository. The GitHub token is generated successfully, and everything works fine, but I’m running into a timeout after about a minute when it tries to create the deploy key (App\Services\Forge\Pipeline\InstallGitRepository::52).

I created the GitHub App with the given permissions, installed it on my account, and added the API private key with the App ID.

Just a heads up, there might be an issue with how I set up the GitHub App. However, creating the deploy key directly with a GitHub fine-grained token worked fine.

@mehrancodes
Copy link
Owner

Don't need to worry about this right now, but I think it would be helpful to have a rollback strategy for the provisioning process in case the GitHub createDeployKey (or anything) fails. Right now, it skips that step (createDeployKey) if we retry the provision, which could cause issues.

@mehrancodes
Copy link
Owner

@RobertBoes, thanks a ton for putting this together! It really helps the project. Had a lot of fun using deploy keys to set up repositories instead of doing it manually, 😅 Setting up the GitHub App took me a bit to get right, though. I might need to add some more guides or link to an article on how to do that.

I went with finding the deploy key using the same formatted title you add when creating it. This way, it removes all deploy keys with that title. Do you think that’s safe?

Anyway, here’s the final result. Let's merge this pull request!
Screenshot 2024-10-27 at 21 23 38

@mehrancodes mehrancodes merged commit 8ce26e8 into mehrancodes:main Oct 27, 2024
1 check passed
@RobertBoes
Copy link
Contributor Author

@mehrancodes that's awesome! Thanks for the hard work! Had some unsaved changes, but couldn't really continue working on it lately. I see you've taken pretty much the same approach as me, just too bad the API doesn't work with IDs or something that can easily be matched. Was thinking about comparing the key's fingerprint, but that was another rabbit hole. I think comparing the name should be fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants