neondatabase / preview-branches-with-vercel

Example project that shows how you can create a branch for every preview deployment on Vercel using GitHub actions
29 stars 11 forks source link

Questions about Neon branches in your GitHub Actions workflows #6

Closed nicolewhite closed 8 months ago

nicolewhite commented 1 year ago

Hello @m-abdelwahab! I was on the call with you earlier today. Thanks for the link, this is super helpful. I had some questions about the values you're using from the GitHub context in your actions:

Could you help me understand why you're using github.pull_request.base.sha and then github.event.before? My understanding is that for a commit on a pull request, github.pull_request.base.sha is the head sha of the base branch of the pull request at the time of the commit, so I'm wondering why you'd want to name your Neon branch after the head sha of the base branch. Is it perhaps supposed to be github.pull_request.head.sha?

And for github.event.before, doesn't that mean you're only deleting the most recently created Neon branch (the one from the last pushed commit) when merging a pull request? Wouldn't that leave a bunch of Neon branches that won't be deleted?

m-abdelwahab commented 1 year ago

Hey @nicolewhite! Apologies for the super delayed response 🙏 I was OOO

I'll need to look into this further ad get back to you.

m-abdelwahab commented 1 year ago

I think gihub.head_ref is what we should use instead. But I'll need to do more testing. Sorry again for not getting back to you sooner

The head_ref or source branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either pull_request or pull_request_target.

akd-io commented 1 year ago

I think I'll be setting a similar workflow up soon, and can report back with any modifications I end up making.

akd-io commented 1 year ago

I ended up making a Neon branch per pull request until I can afford to jump off the free tier. The dream is to create a Neon branch on every commit and have them persist forever like your app on Vercel.

I use the git branch name as the Neon branch name in my preview deploy workflow:

name: "Deploy Preview"
on: [pull_request]
jobs:
  deploy_preview:
    name: "Deploy Preview"
    permissions: write-all
    runs-on: ubuntu-latest
    environment:
      name: "redacted"
    env:
      VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
      VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
      NEON_API_KEY: ${{secrets.NEON_API_KEY}}
    steps:

      ...

      - name: "Extract branch name" # From: https://stackoverflow.com/questions/58033366/how-to-get-the-current-branch-within-github-actions
        id: extract_branch
        shell: bash
        run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
      - name: "Neon Database Create Branch Action"
        id: create_branch
        uses: neondatabase/create-branch-action@v3
        with:
          project_id: ${{ vars.NEON_PROJECT_ID }}
          branch_name: ${{steps.extract_branch.outputs.branch}}
          api_key: ${{ secrets.NEON_API_KEY }}
          username: ${{ vars.PG_USERNAME }}
          password: ${{ secrets.PG_PASSWORD }}

And then I created this Neon db deletion workflow, that triggers on closed pull requests to extract the branch name:

name: "Delete Neon Branch"
on:
  pull_request:
    types: [closed]
jobs:
  delete_neon_branch:
    name: "Delete Neon Branch"
    runs-on: ubuntu-latest
    environment:
      name: "redacted"
    env:
      NEON_API_KEY: ${{secrets.NEON_API_KEY}}
      NEON_PROJECT_ID: ${{vars.NEON_PROJECT_ID}}
    steps:
      - name: "Checkout repo"
        uses: actions/checkout@v3
      - name: "Extract branch name"
        id: extract_branch_name
        run: echo "branch_name=${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT
      - name: "Search branch by name"
        id: get_branch_id
        if: ${{ steps.extract_branch_name.outputs.branch_name != 'develop' && steps.extract_branch_name.outputs.branch_name != 'main' }}
        # list all branches and filter by name
        run: |
          branch_id=$(curl --silent \
            "https://console.neon.tech/api/v2/projects/${{ vars.NEON_PROJECT_ID }}/branches" \
            --header "Accept: application/json" \
            --header "Content-Type: application/json" \
            --header "Authorization: Bearer ${{ secrets.NEON_API_KEY }}" \
            | jq -r .branches \
            | jq -c '.[] | select(.name == "${{ steps.extract_branch_name.outputs.branch_name }}") .id' \
            | jq -r \
            ) \

          echo "branch_id=${branch_id}" >> $GITHUB_OUTPUT
      - name: Delete Neon Branch
        if: ${{ steps.extract_branch_name.outputs.branch_name != 'develop' && steps.extract_branch_name.outputs.branch_name != 'main' }}
        uses: neondatabase/delete-branch-action@v2
        with:
          project_id: ${{ vars.NEON_PROJECT_ID }}
          branch_id: ${{ steps.get_branch_id.outputs.branch_id }}
          api_key: ${{ secrets.NEON_API_KEY }}

Note that I did the following change in the "Search Branch by name" step:

            | jq -r .branches \
-           | jq -c '.[] | select(.name | contains("'${{ steps.extract_branch_name.outputs.branch_name }}'")) .id' \
+           | jq -c '.[] | select(.name == "${{ steps.extract_branch_name.outputs.branch_name }}") .id' \
            | jq -r \

The official example could use an exact check too.