Report this

What is the reason for this report?

Idea of Development, Staging and Production environments and steps with Github Actions

Posted on March 18, 2021

I would like prepare my old project to work wiith separate environments, e.g. for Development, Staging and Productions. I would like hear about your experience or listen your suggestion.

Project is hosted on Github and CI/CD will be running by Github Actions.

I would like prepare 3 stages:

  • development: used by developers on own local machines based on docker, with flat structure, with debug = true, with API keys for sandboxes, database migrations, database seeds and unit, integration and e2e tests;
  • staging: used for showing progress of project for clients on public server, based on docker, with flat structure, with debug = false, with API keys for sandboxes, database seeds and unit, integration and e2e tests;
  • production: as target project, on public server, optionaly based on docker, with release directories and symlink to the newest, with the possiblity of rollback, with debug = false, with target API keys and database migrations.

I prepare sepearate workflows on Github: staging.yaml and production.yaml.
Of course, it’s not necessary for works on development stage. Also I use Deployer for running commands, but it’s not that relevant for this thread.

staging.yaml:

step: build
- build docker environment (or pull and push)
- run docker
- build app (e.g. install vendors)
- unit tests
- integration tests
- export build app as artifacts
step: prepare server (e.g. droplet on DigitalOcean)
- unzpi artifacts
- build docker enviroment with e.g. database
- run docker
- install vendors
- database seeds
step: tests
- run e2e tests
step: publish
- set subdomain (or domain) to docker environment

production.yaml:

step: build
- build docker environment (or pull and push)
- run docker
- build app
- export build app as artifacts
step: connect to existing server (e.g. droplet on DigitalOcean)
- make new dir in releases/ directory 
- unzpi artifacts to newest directory in releases/ directory
- run docker (or no)
- database migrations
- symlink direcotry (used as DOCUMENT_ROOT) do newest directory in releases/ directory
step: publish
- just set success message
  1. Firstly, it’s descrbed stages like these will be good?
  2. It’s good to run production and staging stages as separate or rather should be run as pipeline, production stage only after staging stage (as dependent)?
  3. In Github Action can’t sharing artifacts between jobs, so steps for building docker (pulling/pushing), running docker and building app are duplicated. This increases the duration of the CI/CD process, it’s okay?
  4. Maybe better will be build app once and saving on docker image, then can be shared between other jobs or even stages?


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Hi there,

This is indeed an interesting and broad topic! Overall, your plan for implementing a CI/CD pipeline with separate environments for development, staging, and production is well-designed.

Here are some specific comments and recommendations:

  • Stages and Environments

    • Development: Everything seems to be in order. Developers can quickly spin up their local environment with Docker, utilize sandbox API keys, and run a complete suite of tests.
    • Staging: This is a useful environment for QA and client previews. Your steps, including using sandbox keys and database seeds, are well-considered.
    • Production: The use of symlinks for releases with the ability to rollback is a good strategy.
  • Staging and Production Workflows

    • It is generally a good practice to keep staging and production workflows separate. This allows you to deploy to staging without necessarily deploying to production immediately. However, automating the pipeline such that production deployment is dependent on staging passing all checks is also a good approach, especially for more mature applications where staging is merely a sanity check before production.

    • One thing to consider is that while running tests on staging is essential, running a full suite of unit tests may be overkill, especially if they have already been run during the development phase and again in the CI pipeline.

  • Docker Image Building and Reusability

    • To speed up the CI/CD process and avoid duplicating efforts, build your Docker image once, push it to a Docker registry (e.g., Docker Hub, GitHub Packages, or any other Docker registry), and then pull the same image in subsequent steps or jobs. This way, you avoid rebuilding the application multiple times.

    • A word of caution: Ensure that sensitive information (like API keys) is not baked into the Docker image. Instead, use environment variables to inject them when running the container.

  • Artifacts

    • If you are looking to optimize the speed of your CI/CD process, consider the size of your artifacts. If they are large, transferring them can be time-consuming. Pushing a Docker image with your application pre-installed can be a more efficient way to share the built application across different jobs.
  • Database Migrations and Seeds

    • Ensure that database migrations are idempotent. This means that if a migration fails and you rerun it, you will not end up with corrupted data.
    • Be cautious with database seeds on staging. They are useful for initializing a staging environment, but be wary of accidentally running them in production.
  • Rollbacks

    • Since you have mentioned the possibility of rollbacks in the production environment, make sure your database migrations are reversible. In case of a rollback, you may need to undo a migration.
  • Notifications

    • Consider adding notifications (e.g., email, Slack) on job failures. This can be crucial to quickly address issues when a deployment fails.

Best,

Bobby

Heya,

I like your plan for setting up separate environments for your project using GitHub Actions and Docker. It seems solid, but here are a few suggestions and considerations:

  • Development Environment: It’s good to have a dev env that’s close to prod. Docker is great for this, as it provides isolation and consistency.
  • Staging Environment: Docker is also a good choice for staging, as it helps ensure consistency between staging and prod.
  • Sharing artifacts between jobs: You can use workflow- or job-level workspace to share artifacts between jobs. This lets you persist data between jobs, reducing duplication and speeding up the process.
  • Production Environment: Your deployment process seems reasonable, especially if you need to roll back to previous releases.

Here are some answers to your specific questions:

  • Running production and staging as separate workflows: This is valid. You can trigger the prod workflow manually or automatically based on the success of the staging workflow. It’s a matter of preference and requirements. Running them in parallel can be useful if they don’t have strict dependencies.
  • Sharing artifacts between jobs in the same workflow: GitHub Actions lets you share artifacts between jobs in the same workflow using the workspace. You can save build artifacts in one job and use them in subsequent jobs. You can also use caching for dependencies that don’t change frequently. This can significantly reduce the duration of your CI/CD process.
  • Building the app once and saving it in a Docker image: Good idea, especially if the application doesn’t change frequently. It can reduce redundancy and speed up the process. Make sure to version your Docker images so you can easily roll back if necessary.

Here are some additional considerations:

  • Environment-specific configuration files: Use environment-specific configuration files to manage API keys, database connections, and other environment-specific settings for each stage (dev, staging, prod). Docker Compose can help manage these environment variables.
  • Branching strategy: Implement a branching strategy. For example, trigger your staging and prod workflows when changes are pushed to specific branches (e.g., main for staging and release for prod).
  • Secrets and API keys: Secure your secrets and API keys in GitHub Actions. Use GitHub Secrets for sensitive data and avoid exposing them in your workflow files.
  • Monitoring and logging: Implement a monitoring and logging system for your prod environment to track the performance and troubleshoot issues effectively.

Overall, your approach seems reasonable, but there are ways to optimize and streamline the process to reduce duplication and improve efficiency in your CI/CD pipeline. It’s important to strike a balance between automation and flexibility to meet your project’s specific needs.

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.