如何通过GitOps与GitLab CI实现Heroku应用的测试与多环境部署?
Got it, let's build a command-line-first CI/CD workflow for your GitLab-hosted Rails app that checks all your boxes—and it’s flexible enough to adapt to any tech stack. Here’s a step-by-step solution:
First, create a .gitlab-ci.yml file in your repo root. This defines all your testing and deployment steps. We’ll split it into three stages: test, staging_deploy, and production_deploy.
Step 1: Define Pipeline Stages
Start by outlining the order of operations:
stages: - test - staging_deploy - production_deploy
Step 2: Test Job (Runs on All Pushes & Merge Requests)
This job automatically runs your Rails tests whenever you push code or open a merge request. It’s easy to tweak for other stacks too:
test: stage: test image: ruby:3.2 # Match your Rails app's Ruby version before_script: - apt-get update -qq && apt-get install -y nodejs postgresql-client - gem install bundler - bundle install --jobs $(nproc) --path vendor/bundle - cp config/database.yml.gitlab config/database.yml # Use a GitLab-specific DB config - rails db:create db:schema:load script: - bundle exec rspec # Replace with your test command (e.g., `npm test` for JS apps) only: - pushes - merge_requests
Adaptation Tip:
For non-Rails stacks: Swap the image (e.g., node:20 for JS, python:3.11 for Django), update before_script to install your dependencies, and change script to run your test suite.
Step 3: Staging Deployment Job
This deploys to your Heroku staging environment. We’ll use dpl (a Heroku deployment tool) and make it optionally manual so you can trigger it via CLI:
staging_deploy: stage: staging_deploy image: ruby:3.2 before_script: - gem install dpl script: - dpl --provider=heroku --app=$HEROKU_STAGING_APP_NAME --api-key=$HEROKU_API_KEY - heroku run rails db:migrate --app $HEROKU_STAGING_APP_NAME # Add DB migrations if needed only: - master # Or use a `develop` branch if you follow Git Flow when: manual # Optional: Set to `always` if you want auto-deploy on merge to master
Step 4: Production Deployment Job
Similar to staging, but we’ll add safeguards: it runs only after staging deploys (optional but recommended) and requires manual trigger to avoid accidental production pushes:
production_deploy: stage: production_deploy image: ruby:3.2 before_script: - gem install dpl script: - dpl --provider=heroku --app=$HEROKU_PROD_APP_NAME --api-key=$HEROKU_API_KEY - heroku run rails db:migrate --app $HEROKU_PROD_APP_NAME only: - master # Or a dedicated `production` branch when: manual needs: ["staging_deploy"] # Ensures staging is deployed first
All operations can be handled via the terminal using the GitLab CLI (glab)—install it first if you haven’t.
Trigger Tests
Tests run automatically on pushes/MRs, but if you need to re-run them manually:
glab ci run test -b your-feature-branch
Deploy to Staging
If you set staging_deploy to manual, trigger it with:
glab ci run staging_deploy -b master
Or, if you set it to auto-deploy, just merge your code to the staging branch and push:
git checkout develop git merge your-feature-branch git push origin develop
Deploy to Production
Trigger the manual production job:
glab ci run production_deploy -b master
The pipeline is modular—here’s how to adjust for common stacks:
- Node.js/React/Vue: Use
image: node:20, setbefore_script: npm install,script: npm test, and deploy withdpl(for Heroku) or your platform’s CLI (e.g., Vercel/Netlify). - Python/Django: Use
image: python:3.11,before_script: pip install -r requirements.txt,script: pytest, and deploy via Heroku’s Python buildpack or AWS CLI. - Go: Use
image: golang:1.21,script: go test ./..., and deploy with Docker or Heroku’s Go buildpack.
Avoid the browser by setting sensitive variables (like Heroku API keys) directly in the terminal:
# Set masked Heroku API key (won't show in CI logs) glab variable set HEROKU_API_KEY --masked --value "your-heroku-api-key" # Set staging app name glab variable set HEROKU_STAGING_APP_NAME --value "your-staging-app-name" # Set production app name glab variable set HEROKU_PROD_APP_NAME --value "your-production-app-name"
内容的提问来源于stack exchange,提问作者Amin Shah Gilani

