Not yet! I’ve started just having fly.kurt.yml
file variants, but I still have to -f <file>
on every command.
I have two environments, dev and prod. They both share the same yml file, but I have removed the name from the toml file.
I have setup a github workflow, where pushes to development branch get deployed with fly deploy -a dev
and pushes to master branch get deployed with fly deploy -a prod
What is the long-term goal here? Because it can’t be uncommon to want to have multiple deployments for one app?
I could see something like having one app but with multiple “channels” for deployment, where you can override specifics for that given channel. Also, untangling domains and such from a specific app would be nice as well but it may already be so I’ll have to investigate this further soon. I have an API and a separate Angular app which would have to be deployed as separate apps so as to not have to merge these projects into one app, but they will use the same domain and same wildcard certificate, I am hoping.
The long term goal is to figure out a good UX for one app config → multiple apps.
We haven’t quite decided how to route one domain to multiple apps yet, and I expect it’ll be a while before we do. But we do have a neat statics
feature you can use for backend/static app deployment. It should be pretty easy to build statics into an API image, and you wouldn’t need to add any other webservers (since we handle that).
I’m just wondering why an app must only have one deployment, as that seems to be the core idea of fly.io? In my experience that’s rarely the case with medium-bigger projects so I’m wondering.
It’s not really the core idea, just the simplest thing to build from scratch. I actually create multiple versions of most of my apps.
Our goal, so far, has been to make fly deploy
just work for most apps. Things like deploy pipelines and multiple environment support are really useful for people who already like Fly, but somewhat complex for tire kickers. The good news is, there are a lot of people who really like using us now, so it makes sense to start building more powerful features.
Could you share your yml file that configures the github action?
This seems like a good time to pitch environment-specific binstubs:
bin/production
contains FLY_APP=app exec flycli $@
while bin/staging
contains FLY_APP=app-staging exec flycli $@
. instead of calling fly directly, you call the environment specific binaries that are checked in to your repo. imo, it’s still more ergonomic than Heroku’s pipelines, and it’s usable with far less server side rolling around it.
I liked how heroku did pipelines when managing dev → staging → prod.
Configure 3 apps, each with their own configurations (vn size, dyno counts, env, etc)
Setup branches per app, and then also allow for manual propagation.
I just got started with Fly and have multiple environments for my app. Here how I do it…
I have a separate config file for each environment. E.g. fly.staging.toml
, fly.prod.toml
.
In my CI I just declare the config file to use when deploying.
e.g. fly deploy -c fly.staging.toml -i <image-name>
This is how I currently achieve this as well.
I don’t have the app name in fly.toml
# fly.toml file generated for indiepaper-dev on 2021-09-02T14:43:54+05:30
kill_signal = "SIGTERM"
kill_timeout = 5
[env]
[deploy]
...
I specify that in Github Workflow that is separate for Development and Production.
.github/workflows/development.yaml
name: Deploy develop branch to indiepaper-development on fly
on:
push:
branches:
- develop
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
jobs:
deploy:
name: Deploy Development App
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: superfly/flyctl-actions@master
with:
args: "deploy -a indiepaper-development --remote-only"
For production change the name to indiepaper-production
This way you only need to maintain one fly.toml, but whenever you are running locally you need to specify the app with fly status -a indiepaper-development
.
Makes sense. I have this setup with several apps now and it works great.
One way i’ve done in the past is to generate the fly.toml
on the fly (pun or no pun intended… never understood which one to choose) on the CI/CD pipeline.
You can do an echo "config template" > fly.toml
and generate/populate the config with the data u need, and then call fly deploy -c fly.toml
this way you never have to worry about stage or prod envs on your local environment.
And if you actually want to do it properly just use https://www.doppler.com/, and you never have to worry about .envs anymore in your life.
There’s great content here. I will leave here also how we do it (similar to @aswinmohanme):
build-and-deploy:
name: Build and deploy
runs-on: ubuntu-latest
needs:
# (...)
steps:
- uses: actions/checkout@v2
- uses: superfly/flyctl-actions/setup-flyctl@master
- run: flyctl -a our-app-staging deploy --remote-only
if: github.ref == 'refs/heads/develop'
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
- run: flyctl -a our-app-production deploy --remote-only
if: github.ref == 'refs/heads/main'
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
Locally there’s a handy env var FLY_APP
(ex: export FLY_APP=our-app-name
) , you could also pass -a our-app-name
on every fly command or
I like the idea of having the two scripts. But I was also thinking having something akin to the Heroku piplines could be nice.
A caveat: This -a <staging-or-prod>
trick doesn’t work with Machine apps (yet): Preview: Deploying applications on Machines with flyctl - #6 by ignoramous
Well, “pipelines” seems to be on Fly’s roadmap anti-roadmap: Rough edges for multi-app services - #2 by kurt
I keep the app name in the fly toml the staging app, and when I want to deploy production I promote the latest staging image to production, so I never build a new image for production, simply deploy one of staging’s images:
#!/usr/bin/env ruby
require "json"
js = JSON.parse(`flyctl image show --json`)
registry = js["Registry"]
tag = js["Tag"]
repo = js["Repository"]
production_app = "app-production"
cmd = "flyctl deploy -i #{registry}/#{repo}@#{tag} -a #{production_app}"
puts "----> Running #{cmd}"
system(cmd)
Ah, similar to: Deploy fly apps using custom made bot - #3 by kurt
This works because I guess you must have already deployed the required config
(aka fly.toml
) to prod
at least once?
Sharing my solution here.
I have two apps deployed: foo.fly.dev and foo-dev.fly.dev.
Make sure you create them running: flyctl deploy -a <appn_ame>
.
The toml file does not have an app name and my gh workflow is this:
➜ cat .github/workflows/fly.yml
name: Fly Deploy Prod
on:
push:
branches:
- main
- dev
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
jobs:
deploy:
name: Deploy app
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: superfly/flyctl-actions/setup-flyctl@master
- name: run_flyctl
run: |
echo "github.ref is: ${{github.ref}}"
if [[ "${{github.ref}}" == "refs/heads/main" ]]; then
echo "deploying to PROD"
flyctl deploy --remote-only -a drio-fly
fi
if [[ "${{github.ref}}" == "refs/heads/dev" ]]; then
echo "deploying to DEV"
flyctl deploy --remote-only -a drio-fly-dev
fi