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

Not able to deploy Phoenix App #22

Open
slashmili opened this issue Feb 16, 2023 · 28 comments · Fixed by Complear/fly-pr-review-apps#1
Open

Not able to deploy Phoenix App #22

slashmili opened this issue Feb 16, 2023 · 28 comments · Fixed by Complear/fly-pr-review-apps#1

Comments

@slashmili
Copy link

slashmili commented Feb 16, 2023

I'm trying to use this GithubAction in my Phoenix app.

The problem is in this line

flyctl launch --no-deploy --copy-config --name "$app" --image "$image" --region "$region" --org "$org"

flyctl attempts to execute mix but since mix is not installed in the docker container, it fails.

In addition there are multiple problems with the current main which makes this GithubAction unusable at least for my use case .

I forked the repo and move the main code to index.js, you can find it at https://github.com/slashmili/fly-pr-review-apps/blob/nodejs-action/index.js

I'm using it in my project like:

      - name: Set up Elixir
         uses: erlef/setup-beam@e3f6ffe2878180f57318bf13febd3933ee81f664
         with:
           elixir-version: ${{ env.ELIXIR_VERSION }}
           otp-version: ${{ env.ERLANG_VERSION }}
       - name: Deploy
         id: deploy
         uses: slashmili/fly-pr-review-apps@nodejs-action
         with:
           org: myorg
           region: arn
           postgres: my-staging-db

This way by the time that Deploy step is getting executed, already Elixir and mix is installed can flyctl commands can use the mix command.

If you are interested in maintaining the upstream, I'd purpose that take the same approach. I'm not familiar with node so take my changes with grain of salt.

@amos-kibet
Copy link

Substituting flyctl launch ... with flyctl apps create .. seems to solve this issue, but will only work if you have the fly.toml file in the repository.

@brecke
Copy link

brecke commented Jan 16, 2024

hey @slashmili I've tried your solution but I still get the error of mix not being available in PATH. However, it's right there, I can print mix --help and which mix successfully. What am I missing?

Here's the relevant config for my specific case:

jobs:
  preview:
    name: Branch preview app with ${{matrix.otp}} / Elixir ${{matrix.elixir}}
    runs-on: ubuntu-latest
    strategy:
      # Specify the OTP and Elixir versions to use when building
      # and running the workflow steps.
      matrix:
        otp: ["26.0.0"] # Define the OTP version [required]
        elixir: ["1.16.0"] # Define the elixir version [required]
    # Only run one deployment at a time per PR.
    concurrency:
      group: pr-${{ github.event.number }}
    # Create a GitHub deployment environment per staging app so it shows up
    # in the pull request UI.
    environment:
      name: pr-${{ github.event.number }}
      url: ${{ steps.deploy.outputs.url }}
    steps:
      # Step: Setup Elixir + Erlang image as the base.
      - name: Set up Elixir
        uses: erlef/setup-beam@v1
        with:
          otp-version: ${{matrix.otp}}
          elixir-version: ${{matrix.elixir}}
      - uses: actions/checkout@v4
      - name: PR Review Apps on fly.io
        uses: superfly/[email protected]
        with:
          name: branch-preview-pr-${{github.event.number}}
          config: fly.preview.toml

@slashmili
Copy link
Author

@brecke unfortunately I don't have access to the project anymore and it's not possible for me to test.

However just looking at your snippet, I see you are still using

        uses: superfly/[email protected]

While I was using

         uses: slashmili/fly-pr-review-apps@nodejs-action

@type1fool
Copy link

type1fool commented Mar 4, 2024

I stumbled on the same issue and found a bizarre solution. When I start by using superfly/[email protected], this error occurs. If I use superfly/fly-pr-review-apps@v1, the Fly deploy actually triggers a build, but the config is invalid for secrets, etc. When I switch the version back to superfly/[email protected], the app deploys successfully with the required secrets and the PR shows the staging link to the running app.

Why this works is beyond me. I have reproduced the error->success flow twice now, and I'm curious if anyone else can do the same.

@ricksonoliveira
Copy link

@type1fool tried it but it didn't work for me. I'm getting this error Error: Not authorized to deploy this app.

Here's my current file:

name: Staging App
on:
  pull_request:
    types: [opened, reopened, synchronize, closed]

env:
  FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
  FLY_ORG: friendli

jobs:
  staging_app:
    runs-on: ubuntu-latest

    # Only run one deployment at a time per PR.
    concurrency:
      group: pr-${{ github.event.number }}

    # Create a GitHub deployment environment per staging app so it shows up
    # in the pull request UI.
    environment:
      name: pr-${{ github.event.number }}
      url: ${{ steps.deploy.outputs.url }}

    steps:
      - uses: actions/checkout@v4

      - name: Deploy
        id: deploy
        uses: superfly/fly-pr-review-apps@v1
        with:
          postgres: per-pr

Anyone knows how to solve this? Also trying on a Phoenix project

@type1fool
Copy link

@ricksonoliveira If you change the action back to superfly/[email protected], does it deploy successfully? What's weird is that deploys fail unless I start w 1.2.0, change to v1, then change back to 1.2.0.

@ricksonoliveira
Copy link

@type1fool no it doesn't. I get either mix path error in v1 or with v1.2.0 I get "not authorized to deploy". I'm wondering what I'm doing wrong.

@type1fool
Copy link

type1fool commented Mar 5, 2024

@ricksonoliveira I think this is it:

    environment:
      name: pr-${{ github.event.number }}
      url: ${{ steps.deploy.outputs.url }}

You probably don't have a GitHub environment named pr-*. In my repo, I have two environments: staging and production. So, my config uses name: staging and I have a separate FLY_API_TOKEN for that env (as well as staging api keys and other secrets).

If you point to an actual environment and use superfly/[email protected], I bet you'll see progress.

@ricksonoliveira
Copy link

ricksonoliveira commented Mar 7, 2024

Hey @type1fool weird thing is, I checked my environments, and it's creating a new environment dynamically when using superfly 1.2.0.

image

So, I think I don't have to manually create them right? So the question would be, do I create manually a "staging" environment for instance and add a new FLY_API_TOKEN secret in there, and change my script to point to it? Or, is there something missing in the script to insert the FLY_API_TOKEN into these dymanic environments being created?

@type1fool
Copy link

This is where I think the example in the readme is possibly wrong, at least based on my understanding of GH environments. Instead of creating an environment for each PR, I defined one staging environment for my repo, which contains non prod creds including a fly api token.

In the workflow, I use environment: staging instead of environment: pr-${{...}}.

@ricksonoliveira
Copy link

ricksonoliveira commented Mar 7, 2024

@type1fool So you did it like this?

environment:
      name: staging
      url: staging

Because this returns an error saying that staging is not a valid value

@ricksonoliveira
Copy link

Can you please give an example of how your script looks like @type1fool ?

@type1fool
Copy link

type1fool commented Mar 10, 2024

@ricksonoliveira almost!

environment:
      name: staging
      url: ${{ steps.fly-preview.outputs.url }}

Here's my complete elixir.yml (look for the deploy_preview job):

name: Elixir CI

on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]
    types: [labeled, synchronize, opened, reopened, closed]

concurrency:
  group: ${{ github.ref }}
  cancel-in-progress: true

env:
  MIX_ENV: test

permissions:
  contents: read

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - id: build
        uses: ./.github/actions/build

      - name: Save Deps Cache
        id: save-deps-cache
        uses: actions/cache/save@v4
        with:
          key: ${{ runner.os }}-deps-${{ hashFiles('mix.lock') }}
          path: ./deps

      - name: Save Build Cache
        id: save-build-cache
        uses: actions/cache/save@v4
        with:
          path: ./_build
          key: ${{ runner.os }}-build-${{ hashFiles('mix.lock') }}

  code_quality:
    name: Code Quality
    runs-on: ubuntu-latest
    needs: [build]
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/build

      - name: Check Formatting
        run: mix format --check-formatted

      - name: Credo
        run: mix credo

  security:
    name: Security
    runs-on: ubuntu-latest
    needs: [build]
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/build

      - name: Sobelow
        run: mix sobelow --config

      - name: Mix Audit
        run: mix deps.audit

      - name: Hex Audit
        run: mix hex.audit

  test:
    name: Tests
    runs-on: ubuntu-latest
    needs: [build]
    services:
      db:
        image: postgres:15
        ports: ["5432:5432"]
        env:
          POSTGRES_PASSWORD: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
      - uses: actions/checkout@v4
      - uses: ./.github/actions/build

      - name: Run Tests
        run: mix test

  dialyzer:
    name: Dialyzer
    needs: [build]
    runs-on: ubuntu-latest
    env:
      MIX_ENV: dev
    steps:
      - uses: actions/checkout@v4
      - id: build
        uses: ./.github/actions/build

      - name: Restore Dialyzer Cache
        id: restore-plt-cache
        uses: actions/cache/restore@v4
        with:
          path: ./priv/plts
          key: ${{ runner.os }}-plt-${{ hashFiles('mix.lock') }}
          restore-keys: |
            ${{ runner.os }}-plt-

      - name: Build Dialyzer PLTs
        run: mix dialyzer --plt

      - name: Save Dialyzer Cache
        id: save-plt-cache
        uses: actions/cache/save@v4
        with:
          path: ./priv/plts
          key: ${{ runner.os }}-plt-${{ hashFiles('mix.lock') }}

      - name: Dialyzer
        run: mix dialyzer --format github

  deploy_preview:
    if: ${{contains(github.event.pull_request.labels.*.name, 'staging') || github.event.pull_request.merged == true}}
    name: Deploy Preview
    runs-on: ubuntu-latest
    needs: [security, test]
    environment:
      name: staging
      url: ${{ steps.fly-preview.outputs.url }}
    env:
      MIX_ENV: prod
      FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
      FLY_APP: "pr-${{ github.event.pull_request.number }}-${{ github.repository_owner }}-top-secret"
      FLY_REGION: "dfw"
    steps:
      - uses: actions/checkout@v4
      - name: Build
        id: build
        uses: ./.github/actions/build
      - name: Deploy
        uses: superfly/[email protected]
        id: fly-preview
        with:
          name: "pr-${{ github.event.pull_request.number }}-${{ github.repository_owner }}-top-secret"
          config: fly_staging.toml
          vmsize: shared-cpu-1x
          postgres: top-secret-staging
          secrets: |
            STRIPE_SECRET=${{ secrets.STRIPE_SECRET }}
            DATABASE_URL=${{ secrets.DATABASE_URL }}
            SENDGRID_API_KEY=${{ secrets.SENDGRID_API_KEY }}
            PHX_HOST="pr-${{ github.event.pull_request.number }}-${{ github.repository_owner }}-top-secret.fly.dev"
            SENTRY_DSN=${{ secrets.SENTRY_DSN }}

@ricksonoliveira
Copy link

ricksonoliveira commented Mar 11, 2024

Thanks for this @type1fool. The problem with not authorized was actually my fly token not having permission, I already solved that.
But I really don't understand how yours - and anyone using 1.2.0 are making this work as I'm always getting exec: "mix": executable file not found in $PATH and if I use 1.0.0 I'm not able to set up secrets. Is there a way to change the arguments of the fly launch command?

@type1fool
Copy link

type1fool commented Mar 11, 2024

The short answer is that this repo probably needs some attention. PR #48 has some improvements for managing secrets and some other improvements. Hopefully it will get reviewed soon.

Why is 1.2.0 working for me? It's barely working. The config I posted only results in a successful deploy if I:

  1. Open a PR with a staging tag
  2. Use superfly/fly-pr-review-apps@v1
  3. Watch the deploy fail
  4. Push a commit using superfly/[email protected]
  5. Watch the deploy succeed

I've been writing GitHub Actions / Circle CI / Travis CI config off and on for a few years now, and I have no idea why this version flipping trick is necessary or why it works. It's tempting to rewrite this action from first principles using more idiomatic GH action code, but there are higher priorities at the moment.

If one were to write this from scratch, I think the requirements would be something like this:

  1. Use fly-actions to setup the Fly CLI.
  2. Require FLY_API_TOKEN in env.
  3. Accept a Fly config glob, defaulting to ./fly.toml.
  4. Set any additional variables from env.
  5. Require a Dockerfile.
  6. Only run when the Github event is an appropriate PR event (opened, closed, synced, etc).
  7. Accept a label that triggers the action, maybe default to staging.
  8. Check that the provided label exists on the PR.
  9. Accept a custom name, defaulting to staging-[org_name]-[repo_name].
  10. Launch/deploy a Fly app when the PR event is opened/synced.
  11. Delete the Fly app when the PR event is closed.
  12. Make sure it works for any language supported by Fly. 🫥
  13. Handle edge cases. 🤡

This is how I'd approach this if I were going to write a custom action for my org, excluding the last two points. There are surely additional details to consider. It's doable, but it's not going to be easy.

@ricksonoliveira
Copy link

Thanks for the reply @type1fool would be very nice if someone took a look. Whilst that doesn't happen I'm working on my own script but this is being a loooot of work though.
Hey guys big shoutout to PR #48 please consider taking a look, lotta people waiting for this. @jsierles @lubien @brecke @felixxm

@ricksonoliveira
Copy link

ricksonoliveira commented Mar 12, 2024

Just an FYI, I created this topic on fly, maybe someone will take a look https://community.fly.io/t/error-trying-to-use-fly-pr-review-action-exec-mix-executable-file-not-found-in-path-for-phoenix-app/18700

@type1fool
Copy link

Mark Ericksen replied to a thread I had opened, and I've seen some activity on that PR, so it looks like this is getting some attention.

@ricksonoliveira
Copy link

ricksonoliveira commented Mar 12, 2024

Yea, I tried replying to that thread to ask him if he got the time to take a look but it's closed. I didn't notice it was your thread though, neat! Hopefully someone will take a look on this soon, I don't want to reinvent the wheel here but it's sounding like a completely different approach will be needed if no ones fixes this.

@ricksonoliveira
Copy link

Hey Guys! Just passing here to let you all know that I found a way to make this work for Elixir Phoenix Applications! 🎉 I have to say the solution may not be the best but it does work!
What I did was take the PR #48 as base case, to take advantage of it's improvements, and simply added a step to create a postgres app if none is given and add a SECRET_KEY_BASE per application. Feel free to check it out https://github.com/ricksonoliveira/fly-pr-review-apps
I'm not going to open a PR to contribute since this might break everyone's pipelines. But please, let me know of improvements I could add, and feel free to use my solution as a base to create your own fork!

@brecke
Copy link

brecke commented Jun 19, 2024

But I really don't understand how yours - and anyone using 1.2.0 are making this work as I'm always getting exec: "mix": executable file not found in $PATH

I was able to workaround that error adding the image attribute as follows:

        with:
          image: elixir:1.16

I can now deploy the web server as expected. Still lacking the postgres part though, I don't think that works. I'll keep you updated.

EDIT: Everything works, including the database attach part yay! 🥳 What I lack the most right now is having a dockerfile option (to replace the image attribute) so that Fly builds it instead of Github Actions - as I have a custom image, I am building it in a previous step so I can point to it as above. There's a PR for that but currently stale: #52

@jakelacey2012
Copy link

I'm running into issues with my phoenix applications as well, when waiting for the health check it looks like my machine gets stuck at

 2024-08-13T07:35:44.385 app[178154d9a19d89] lhr [info] [ 0.273922] PCI: Fatal: No config space access function found
2024-08-13T07:35:44.545 app[178154d9a19d89] lhr [info] INFO Starting init (commit: 20f21dc5f)...
2024-08-13T07:35:44.616 app[178154d9a19d89] lhr [info] INFO Preparing to run: `/app/bin/migrate` as root
2024-08-13T07:35:44.617 app[178154d9a19d89] lhr [info] ERROR Error: failed to spawn command: /app/bin/migrate: No such file or directory (os error 2)
2024-08-13T07:35:44.618 app[178154d9a19d89] lhr [info] does `/app/bin/migrate` exist and is it executable?
2024-08-13T07:35:44.618 app[178154d9a19d89] lhr [info] [ 0.506405] reboot: Restarting system 

Does anyone know what I might be doing wrong here?

@brecke
Copy link

brecke commented Aug 13, 2024

hi @jakelacey2012

I'm running migrate in my fly.preview.toml as follows:

[deploy]
release_command = "/app/bin/migrate"

And it runs okay. Hard to be of help without more info on your side, but the diagnosis is pretty clear: somehow it ends up in a place where it cannot access /app/bin/migrate. In my case, fly.preview.toml is pretty much the same as fly.production.toml except for a few flags, so maybe your issue is not related to the github action but to fly.io depoyment? The hard part for me was to figure out the yml GA file, not the fly.io toml config file.

Let me know how I can help.

@jakelacey2012
Copy link

Thanks @brecke, I'll provide a bit more information.

So this is my github action

name: Deploy Review App
on:
  # Run this workflow on every PR event. Existing review apps will be updated when the PR is updated.
  pull_request:
    types: [opened, reopened, synchronize, closed]

env:
  FLY_API_TOKEN: ${{ secrets.FLY_AUTH_TOKEN }}
  FLY_REGION: lhr
  FLY_ORG: cuties

jobs:
  review_app:
    runs-on: ubuntu-latest
    outputs:
      url: ${{ steps.deploy.outputs.url }}
    # Only run one deployment at a time per PR.
    concurrency:
      group: pr-${{ github.event.number }}

    # Deploying apps with this "review" environment allows the URL for the app to be displayed in the PR UI.
    # Feel free to change the name of this environment.
    environment:
      name: review
      # The script in the `deploy` sets the URL output for each review app.
      url: ${{ steps.deploy.outputs.url }}

    steps:

      - name: Get code
        uses: actions/checkout@v4

      - name: Deploy PR app to Fly.io

        id: deploy
        uses: superfly/[email protected]
        with:
          image: elixir:1.16 # this is needed otherwise elixir isn't in the PATH.
          postgres: savvychef-preview-db
          secrets: SECRET_KEY_BASE=pr-${{ github.event.number }}-secret-key-base
          config: fly.preview.toml

      - name: Clean up GitHub environment
        uses: strumwolf/delete-deployment-environment@v2
        if: ${{ github.event.action == 'closed' }}
        with:
          # ⚠️ The provided token needs permission for admin write:org
          token: ${{ secrets.GITHUB_TOKEN }}
          environment: pr-${{ github.event.number }}

and this is my fly (I liked the idea of a preview config, so I stole that :P)

app = 'example'
primary_region = 'lhr'
kill_signal = 'SIGTERM'

[build]

[deploy]
  release_command = '/app/bin/migrate'

[env]
  PHX_HOST = 'example.co.uk'
  PORT = '8080'

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 0
  processes = ['app']

  [http_service.concurrency]
    type = 'connections'
    hard_limit = 1000
    soft_limit = 1000

[[vm]]
  memory = '1gb'
  cpu_kind = 'shared'
  cpus = 1

I'll continue to dig and see if I can provide some more information.

@brecke
Copy link

brecke commented Aug 15, 2024

Hi @jakelacey2012

I think it comes down to the container just not having the /app/bin/migrate path. You're using elixir:1.16 right?

So let's find out whether the path exists:

docker run -it --rm elixir:1.16 bin/sh
...
# ls -la /app/bin/migrate
ls: cannot access '/app/bin/migrate': No such file or directory

So there you go.

In my case, I am building my own image on a previous step on the workflow

      - name: Build elixir image
        run: docker build -t custom-image-elixir:1.16 -f Dockerfile .

and then, later, I use it later, just like you did:

          image: custom-image-elixir:1.16

Now you may be wondering what's my Dockerfile like. Well, I stole it too from Fly-apps repo here. You'll notice the /app/bin/migrate does exist in that image.

Building my container in the GA workflow is kind of hacky, but I don't think there's a better way unless publishing it on dockerhub (and then providing the name in the image option). That's also why the #52 PR aiming to add a dockerfile option would come in handy.

Hope this helps.

@jakelacey2012
Copy link

Okay that helped me get a little further 😅 but it seems I need a degree to work with flyio's API HA. I'm getting this error now

 ✖ release_command failed
Error release_command failed running on machine e825147a0d2298 with exit code 1.
Check its logs: here's the last 100 lines below, or run 'fly logs -i e825147a0d2298':
  Pulling container image registry.fly.io/pr-14-jakelacey2012-xxx-web:deployment-01J5BXAR9FC44Q83352J39A9J9
✖ Failed: error release_command machine e825147a0d2298 exited with non-zero status of 1
  Successfully prepared image registry.fly.io/pr-14-jakelacey2012-xxx-web:deployment-01J5BXAR9FC44Q83352J39A9J9 (7.973421452s)
  Configuring firecracker
  2024-08-15T20:59:00.109486513 [01J5BXC22W2RVT6M1Y6JYF1M97:main] Running Firecracker v1.7.0
  [    0.038374] Spectre V2 : WARNING: Unprivileged eBPF is enabled with eIBRS on, data leaks possible via Spectre v2 BHB attacks!
  [    0.278393] PCI: Fatal: No config space access function found

Also the postgres option doesn't seem to work as intended because I need to explicitly pass a DATABASE_URL 😕.

@brecke
Copy link

brecke commented Aug 16, 2024

Regarding the postgres part, I don't pass any DATABASE_URL I just state the name of the cluster in fly.io like this:

          postgres: yourapp-db-preview

As for the release failing, I suggest you check the logs as suggested, but it doesn't seem to be a problem with the GA anymore, I'd say.

jehrhardt added a commit to jehrhardt/cozyauth that referenced this issue Aug 21, 2024
@brecke
Copy link

brecke commented Jan 14, 2025

Hey guys, allow me to share a small update which might be useful to someone:

I had this problem where I'm using a custom image (see above) to build and deploy my app along with postgres.

I found out two things

  • the postgres option wasn't working as expected consistently
  • the image attribute works with public containers, but most people have their custom container private

So I eventually ended up doing this:

  1. create the app beforehand and attach it to my testing postgres cluster
  2. push my image to fly.io docker registry (as it matches the app name, it will be used automatically. I did not know this!)
      - name: Get code
        uses: actions/checkout@v4
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1
      - name: Install flyctl CLI
        uses: superfly/flyctl-actions/setup-flyctl@master
      - name: Authenticate with Fly.io registry
        run: flyctl auth docker
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
      - name: Create Fly App before pushing docker image to registry
        run: |
          flyctl apps create ${{ env.APP_NAME }} --org ${{ env.FLY_ORG }} || true
          flyctl postgres attach mycompany_preview_db_app --app ${{ env.APP_NAME }} || true
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_AUTH_TOKEN }}
      - name: Build and push Docker image
        uses: docker/build-push-action@v6
        with:
          push: true
          tags: registry.fly.io/${{ env.APP_NAME }}:your_version
          context: .
      - name: Deploy PR app to Fly.io
        id: deploy
        uses: superfly/[email protected]
        with:
          name: ${{ env.APP_NAME }}
          config: my_preview_config.toml

I also managed to automatically seed the database and manage Cloudflare DNS records automatically. I asked Claude to summarize it in case someone has questions:

# 1. `deploy` job (runs on opened/reopened/synchronize):
#    - Sets up Elixir/OTP environment
#    - Creates Fly.io app and attaches to existing postgres cluster
#    - Builds and pushes Docker image
#    - Deploys app with necessary environment variables
#
# 2. `setup_networking` job (runs only on opened/reopened):
#    - Runs after deploy job completes
#    - Gets app's IPv4 and IPv6 addresses
#    - Creates DNS records in Cloudflare:
#      * Wildcard A and AAAA records for *.pr-{number}.mycompany.com
#      * ACME challenge CNAME for SSL certificate validation
#    - Sets up SSL certificate via Fly.io
#
# 3. `cleanup` job (runs only on PR close):
#    - Removes Fly.io app
#    - Cleans up all DNS records from Cloudflare
#    - Forces drop of preview database
#    - Removes database role
#
# Result:
# - Each PR gets its own preview environment at *.pr-{number}.mycompany.com
# - Updates are deployed automatically on PR changes
# - All resources are cleaned up when PR is closed

Hope this helps other people.

kgittens89 added a commit to kgittens89/fly_finds that referenced this issue Jan 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
6 participants