This directory contains the CI/CD pipeline configuration for the Rose the Healer Shaman application.
Comprehensive CI/CD pipeline that runs on push and pull requests to main and develop branches.
Jobs:
- code-quality: Runs ruff linting, formatting checks, and mypy type checking
- unit-tests: Runs unit tests with coverage reporting (70% threshold)
- Uploads coverage to Codecov
- Generates HTML coverage reports as artifacts
- Comments on PRs with failure details
- integration-tests: Runs integration tests with real API calls (non-blocking)
- Only runs on develop branch or PRs
- Uses real API credentials from GitHub Secrets
- smoke-tests: Pre-deployment validation tests
- Builds Docker image
- Tests container startup
- Verifies health endpoint
- Only runs for main branch or PRs to main
- deploy-production: Deploys to Railway production
- Installs Railway CLI
- Deploys to production service
- Waits for deployment to stabilize (30 seconds)
- Verifies deployment health with retries
- Runs post-deployment smoke tests
- Creates GitHub issue on failure
- Only runs on push to main
- workflow-summary: Generates workflow summary with job results
Error Handling:
- Uploads test results as artifacts on failure
- Comments on PRs with failure details
- Creates GitHub issues for deployment failures
- Provides detailed error logs for troubleshooting
PR validation workflow that checks:
- PR title follows conventional commits format
- Required files are present
- No large files are committed
Configure these secrets in your GitHub repository settings (Settings → Secrets and variables → Actions):
| Secret Name | Description | Required | Rotation Period |
|---|---|---|---|
GROQ_API_KEY |
Groq API key for LLM inference and speech-to-text | Yes | 90 days |
ELEVENLABS_API_KEY |
ElevenLabs API key for text-to-speech | Yes | 90 days |
ELEVENLABS_VOICE_ID |
ElevenLabs voice ID (e.g., 21m00Tcm4TlvDq8ikWAM) |
Yes | N/A |
QDRANT_URL |
Qdrant Cloud URL (e.g., https://xyz.qdrant.io) |
Yes | N/A |
QDRANT_API_KEY |
Qdrant API key for vector database access | Yes | 90 days |
TOGETHER_API_KEY |
Together AI API key for image generation (optional) | No | 90 days |
| Secret Name | Description | Required | Rotation Period |
|---|---|---|---|
RAILWAY_TOKEN |
Railway CLI authentication token | Yes | 180 days |
RAILWAY_PRODUCTION_URL |
Production application URL (e.g., https://rose-production.railway.app) |
Yes | N/A |
RAILWAY_STAGING_URL |
Staging application URL (future use) | No | N/A |
| Secret Name | Description | Required | Rotation Period |
|---|---|---|---|
CODECOV_TOKEN |
Codecov upload token for coverage reports | No | 365 days |
| Secret Name | Description | Required | Rotation Period |
|---|---|---|---|
SLACK_WEBHOOK_URL |
Slack webhook URL for deployment notifications | No | 180 days |
DISCORD_WEBHOOK_URL |
Discord webhook URL for deployment notifications | No | 180 days |
Use this checklist to ensure all required secrets are configured:
-
API Keys
-
GROQ_API_KEY- Obtained from Groq Console -
ELEVENLABS_API_KEY- Obtained from ElevenLabs Dashboard -
ELEVENLABS_VOICE_ID- Voice ID from ElevenLabs -
QDRANT_URL- Qdrant Cloud cluster URL -
QDRANT_API_KEY- Qdrant API key -
TOGETHER_API_KEY- (Optional) Together AI API key
-
-
Deployment
-
RAILWAY_TOKEN- Railway CLI token -
RAILWAY_PRODUCTION_URL- Production deployment URL -
RAILWAY_STAGING_URL- (Optional) Staging deployment URL
-
-
Coverage & Notifications
-
CODECOV_TOKEN- (Optional) Codecov upload token -
SLACK_WEBHOOK_URL- (Optional) Slack webhook -
DISCORD_WEBHOOK_URL- (Optional) Discord webhook
-
-
Verification
- All secrets added to GitHub repository settings
- Test workflow triggered successfully
- No secret-related errors in workflow logs
Obtaining the Key:
- Visit https://console.groq.com/keys
- Sign in or create an account
- Click "Create API Key"
- Copy the generated key (starts with
gsk_) - Store securely - it won't be shown again
Adding to GitHub:
- Go to your repository on GitHub
- Navigate to: Settings → Secrets and variables → Actions
- Click New repository secret
- Name:
GROQ_API_KEY - Value: Paste your Groq API key
- Click Add secret
Obtaining the API Key:
- Visit https://elevenlabs.io/app/settings/api-keys
- Sign in or create an account
- Click "Create API Key" or copy existing key
- Copy the key (starts with
sk_)
Obtaining the Voice ID:
- Visit https://elevenlabs.io/app/voice-library
- Select a voice or use your cloned voice
- Copy the Voice ID (e.g.,
21m00Tcm4TlvDq8ikWAM) - Or use the default voice ID:
21m00Tcm4TlvDq8ikWAM
Adding to GitHub:
- Add
ELEVENLABS_API_KEYwith your API key - Add
ELEVENLABS_VOICE_IDwith your voice ID
Obtaining Credentials:
- Visit https://cloud.qdrant.io/
- Sign in or create an account
- Create a cluster or use existing cluster
- Copy the Cluster URL (e.g.,
https://xyz-abc123.qdrant.io) - Go to API Keys section
- Create or copy an API key
Adding to GitHub:
- Add
QDRANT_URLwith your cluster URL - Add
QDRANT_API_KEYwith your API key
Obtaining the Key:
- Visit https://api.together.xyz/settings/api-keys
- Sign in or create an account
- Click "Create API Key"
- Copy the generated key
Adding to GitHub:
- Add
TOGETHER_API_KEYwith your API key
Installing Railway CLI:
On macOS/Linux:
curl -fsSL https://railway.app/install.sh | shOn Windows (PowerShell):
iwr https://railway.app/install.ps1 | iexObtaining the Token:
# Login to Railway (opens browser)
railway login
# Get your authentication token
railway whoami --tokenAdding to GitHub:
- Copy the token from the CLI output
- Add
RAILWAY_TOKENwith your token - Important: This token has full access to your Railway account - keep it secure!
Obtaining the URL:
After deploying your application to Railway:
# Link to your Railway project
railway link
# Get the deployment URL
railway statusOr from Railway Dashboard:
- Visit https://railway.app/dashboard
- Select your project
- Click on your service
- Copy the public URL from the Settings → Networking section
Adding to GitHub:
- Add
RAILWAY_PRODUCTION_URLwith your production URL - Format:
https://your-app.railway.app(no trailing slash)
Obtaining the Token:
- Visit https://codecov.io
- Sign in with your GitHub account
- Click Add Repository
- Select your repository
- Copy the Upload Token from the setup instructions
Adding to GitHub:
- Add
CODECOV_TOKENwith your upload token
Creating a Webhook:
- Visit https://api.slack.com/apps
- Create a new app or select existing app
- Enable Incoming Webhooks
- Click Add New Webhook to Workspace
- Select the channel for notifications
- Copy the webhook URL
Adding to GitHub:
- Add
SLACK_WEBHOOK_URLwith your webhook URL
Creating a Webhook:
- Open Discord and go to your server
- Right-click the channel → Edit Channel
- Go to Integrations → Webhooks
- Click New Webhook
- Copy the webhook URL
Adding to GitHub:
- Add
DISCORD_WEBHOOK_URLwith your webhook URL
Regular secret rotation is a critical security practice. Follow these procedures to rotate secrets safely.
| Secret Type | Rotation Period | Priority |
|---|---|---|
| API Keys (Groq, ElevenLabs, Qdrant, Together) | Every 90 days | High |
| Railway Token | Every 180 days | High |
| Codecov Token | Every 365 days | Medium |
| Webhook URLs (Slack, Discord) | Every 180 days | Low |
-
Generate New Secret
- Create new API key/token in the service provider's dashboard
- Keep the old secret active during transition
-
Update GitHub Secret
- Go to: Settings → Secrets and variables → Actions
- Click on the secret name
- Click Update secret
- Paste the new value
- Click Update secret
-
Verify Functionality
- Trigger a test workflow run
- Monitor for any authentication errors
- Check that all services are working correctly
-
Revoke Old Secret
- Once verified, revoke the old secret in the service provider's dashboard
- Document the rotation in your security log
-
Update Local Environments
- Update
.envfiles in local development environments - Notify team members to update their local secrets
- Update
# 1. Generate new key at https://console.groq.com/keys
# 2. Update GitHub secret: GROQ_API_KEY
# 3. Test with a workflow run
# 4. Revoke old key in Groq Console
# 5. Update local .env filesVerification:
# Test locally
export GROQ_API_KEY="new_key_here"
uv run pytest tests/unit/test_core.py -v# 1. Generate new key at https://elevenlabs.io/app/settings/api-keys
# 2. Update GitHub secret: ELEVENLABS_API_KEY
# 3. Test with a workflow run
# 4. Revoke old key in ElevenLabs Dashboard
# 5. Update local .env filesVerification:
# Test locally
export ELEVENLABS_API_KEY="new_key_here"
uv run pytest tests/unit/modules/test_speech.py -v# 1. Generate new key at https://cloud.qdrant.io/
# 2. Update GitHub secret: QDRANT_API_KEY
# 3. Test with a workflow run
# 4. Revoke old key in Qdrant Dashboard
# 5. Update local .env filesVerification:
# Test locally
export QDRANT_API_KEY="new_key_here"
uv run pytest tests/unit/modules/test_memory.py -vImportant: Railway tokens have full account access. Rotate carefully.
# 1. Generate new token
railway login
railway whoami --token
# 2. Update GitHub secret: RAILWAY_TOKEN
# 3. Test deployment with a non-production branch
# 4. Verify deployment succeeds
# 5. Old token is automatically invalidated after logoutVerification:
# Test new token locally
export RAILWAY_TOKEN="new_token_here"
railway status# 1. Regenerate token at https://codecov.io/gh/YOUR_ORG/YOUR_REPO/settings
# 2. Update GitHub secret: CODECOV_TOKEN
# 3. Test with a workflow run
# 4. Old token is automatically revokedIf a secret is compromised, follow these steps immediately:
-
Immediate Revocation
# Revoke the compromised secret in the service provider's dashboard # This takes priority over everything else
-
Generate New Secret
# Create a new secret immediately # Use a different format/pattern if possible
-
Update GitHub
# Update the GitHub secret with the new value # Do this within minutes of revocation
-
Verify All Services
# Run test workflows to ensure everything works # Check production services are functioning
-
Audit Access
# Review service logs for unauthorized access # Check for any suspicious activity # Document the incident
-
Notify Team
# Inform team members of the compromise # Ensure everyone updates their local environments # Review security practices
Use this checklist when rotating secrets:
## Secret Rotation: [SECRET_NAME] - [DATE]
- [ ] **Preparation**
- [ ] Scheduled maintenance window (if needed)
- [ ] Team notified of rotation
- [ ] Backup of current configuration
- [ ] **Rotation**
- [ ] New secret generated
- [ ] GitHub secret updated
- [ ] Test workflow triggered
- [ ] Workflow passed successfully
- [ ] **Verification**
- [ ] Production services functioning
- [ ] No authentication errors in logs
- [ ] Coverage/monitoring still working
- [ ] **Cleanup**
- [ ] Old secret revoked
- [ ] Local environments updated
- [ ] Team confirmed updates
- [ ] Rotation documented
- [ ] **Next Rotation**
- [ ] Next rotation date: [DATE + ROTATION_PERIOD]
- [ ] Calendar reminder setSet up calendar reminders for secret rotation:
# API Keys: Every 90 days
# Railway Token: Every 180 days
# Codecov Token: Every 365 daysRecommended Tools:
- Google Calendar with email reminders
- GitHub Issues with due dates
- Project management tools (Jira, Linear, etc.)
-
Never commit secrets to version control
- Always use
.envfiles (gitignored) - Use GitHub Secrets for CI/CD
- Scan commits for accidental secret exposure
- Always use
-
Use least privilege access
- API keys should have minimal required permissions
- Railway tokens should be service-specific when possible
- Regularly audit access levels
-
Monitor secret usage
- Review service logs for unusual activity
- Set up alerts for failed authentication attempts
- Track API usage patterns
-
Document all secrets
- Maintain a secret inventory
- Document rotation dates
- Track who has access to what
-
Secure secret storage
- Use password managers for personal copies
- Never share secrets via email or chat
- Use secure channels for secret distribution
- Push to main: Runs all tests, smoke tests, and deploys to production
- Push to develop: Runs tests and integration tests
- Pull Request: Runs tests and status checks
You can manually trigger workflows from the Actions tab:
- Go to Actions → Select workflow
- Click "Run workflow"
- Select branch and run
The pipeline enforces a minimum code coverage of 70%. Tests will fail if coverage drops below this threshold.
Coverage reports are:
- Uploaded to Codecov (if token is configured)
- Available as artifacts in the workflow run
- Displayed in the workflow summary
- Push to
mainbranch - Tests run automatically
- Smoke tests validate deployment readiness
- If all tests pass, deploys to Railway
- Post-deployment tests verify the deployment
# Install Railway CLI
curl -fsSL https://railway.app/install.sh | sh
# Login
railway login
# Deploy
railway up --service rose-production- Ensure all environment variables are set in GitHub secrets
- Check that dependencies are properly specified in
pyproject.toml - Review the workflow logs for specific error messages
- Verify
RAILWAY_TOKENis valid and not expired - Check Railway dashboard for deployment errors
- Ensure all required environment variables are set in Railway
- Verify Railway service name matches the workflow configuration
- Verify
CODECOV_TOKENis set correctly - Check Codecov dashboard for upload errors
- Coverage upload failures don't fail the build (fail_ci_if_error: false)
Edit .github/workflows/test.yml:
- name: Check coverage threshold
run: |
uv run pytest tests/ \
--cov=ai_companion \
--cov-fail-under=70 \ # Change this value
-m "not slow and not integration" \
--quietEdit .github/workflows/test.yml:
- name: Deploy to Railway
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
run: |
railway up --service rose-production # Change service name here- Add marker to
tests/pytest.ini:
markers =
your_marker: description of your marker- Use in workflow:
- name: Run your tests
run: |
uv run pytest tests/ -v -m "your_marker"-
Always run tests locally before pushing
uv run pytest tests/ -v
-
Check coverage locally
uv run pytest tests/ --cov=ai_companion --cov-report=html
-
Use conventional commit messages
feat:for new featuresfix:for bug fixesdocs:for documentationtest:for testschore:for maintenance
-
Review workflow logs
- Check Actions tab for detailed logs
- Download artifacts for coverage reports
- Review failed test output
Monitor workflow runs at: https://github.com/YOUR_USERNAME/YOUR_REPO/actions
Monitor deployments at: https://railway.app/dashboard
Monitor coverage trends at: https://codecov.io/gh/YOUR_USERNAME/YOUR_REPO
For issues with:
- GitHub Actions: Check workflow logs and GitHub Actions documentation
- Railway: Check Railway dashboard and Railway documentation
- Codecov: Check Codecov dashboard and Codecov documentation
- Tests: Review test output and pytest documentation