Migrations and Seeds
A Preview Environment is only as good as the data loaded into it. It is best practice to have a fresh set of data loaded for each environment in order to produce predictable results. In some cases, this might be a static set of data defined in a seeds file. For other use cases, you might want to fetch some production data and scrub it before loading it into your Preview Environment. No matter what data you want to load, you will always want to make sure that the database schema is up-to-date.
Best Practices
When setting up database migrations and seeds, be sure to keep the following best practices in mind to avoid issues.
- Each database should have an owner who is responsible for maintaining the database schema and seeds. If more than one application is making changes to a database, it can cause conflicts or unpredictable results.
- If possible, use a tool that can run migrations or seeds in an idempotent manner. It should execute each update in a transaction and block any competing updates until it has finished. You don't want to have more than one process trying to update the database schema at the same time.
Automation Options
Nullstone provides a few different ways to run database migrations and load data into your Preview Environment. Each option along with their benefits and drawbacks are described below.
On Boot
If your application is a container application, you can add an entrypoint that runs before your application boots up.
When To Use
- If you want to run migrations and seeds each time your application deploys, for each code commit and deploy.
- This is not the best option if you want to load a set of data a single time when the Preview Environment is launched.
Benefits
- If the migrations or seeds fail, the application will not start; and the previous version of your application will remain running.
- It is guaranteed to run before your application starts up each time.
Drawbacks
- It runs for every instance of your container. If you have more than one instance, the migrations and seeds scripts will attempt to run at the same time. You will need to make sure that these are idempotent and can run in parallel.
Configuration
To use this option, first add an entrypoint to your Dockerfile. Below is an example of this for a Rails application.
FROM ruby:3.1.0
WORKDIR /root
COPY . .
RUN chmod +x ./entrypoint.sh
ENV PORT 80
ENV RAILS_ENV production
ENV RAILS_LOG_TO_STDOUT true
RUN gem install bundler && bundle install
EXPOSE 80
ENTRYPOINT ["./entrypoint.sh"]
CMD ["bundle", "exec", "rails", "server"]
The key line is line 13, which specifies the entrypoint script to run. ENTRYPOINT ["./entrypoint.sh"]
Next, create the entrypoint script.
#!/bin/sh
set -e
if [ -f tmp/pids/server.pid ]; then
rm tmp/pids/server.pid
fi
echo "Running migrations..."
rails db:migrate
echo "Running seeds..."
rails db:seed
exec "$@"
Triggered Job
Coming soon!