-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
Overview
We need to implement automated preview deployments for Pull Requests to enable better testing and review processes. These deployments should only trigger for PRs created by team members.
Requirements
- Automatic deployment of PRs to unique URLs
- Team member validation before deployment
- Clean up of preview environments after PR closure
- Integration with our existing CI/CD pipeline
Implementation Options
1. GitHub-Native Solution
Using GitHub Actions and GitHub Pages:
name: PR Preview Deployment
on:
pull_request:
types: [opened, synchronize]
jobs:
validate-author:
runs-on: ubuntu-latest
outputs:
is-team-member: ${{ steps.check-team.outputs.is_member }}
steps:
- name: Check if PR author is team member
id: check-team
uses: actions/github-script@v7
with:
script: |
const author = context.payload.pull_request.user.login;
const org = context.repo.owner;
try {
const { data } = await github.rest.teams.getMembershipForUserInOrg({
org: org,
team_slug: 'your-team-slug',
username: author
});
return data.state === 'active';
} catch (error) {
return false;
}
deploy-preview:
needs: validate-author
if: needs.validate-author.outputs.is-team-member == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
env:
VITE_PR_NUMBER: ${{ github.event.pull_request.number }}
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist
destination_dir: pr-${{ github.event.pull_request.number }}Configuration:
- Enable GitHub Pages in repository settings
- Create a team in your organization
- Add GITHUB_TOKEN secret with appropriate permissions
- Update team slug in the workflow
Preview URL format: https://{org}.github.io/{repo}/pr-{number}/
2. Vercel Integration
Using Vercel for automatic deployments:
- Connect GitHub repository to Vercel
- Create
vercel.json:
{
"github": {
"enabled": true,
"silent": true,
"autoJobCancelation": true
},
"builds": [
{
"src": "package.json",
"use": "@vercel/node"
}
]
}- Add team validation with GitHub App:
// api/validate-deployment.js
export default async function handler(req, res) {
const { author, installationId } = req.body;
const octokit = new Octokit({
auth: process.env.GITHUB_APP_TOKEN
});
try {
const { data } = await octokit.rest.teams.getMembershipForUserInOrg({
org: 'your-org',
team_slug: 'your-team',
username: author
});
return res.status(200).json({
proceed: data.state === 'active'
});
} catch (error) {
return res.status(200).json({ proceed: false });
}
}3. Netlify Solution
Using Netlify for deployments:
- Connect repository to Netlify
- Create
netlify.toml:
[build]
command = "npm run build"
publish = "dist"
[context.deploy-preview]
command = "npm run build"- Add build hook validation:
// netlify/functions/deploy-validation.js
exports.handler = async (event) => {
const payload = JSON.parse(event.body);
const author = payload.review_id ? payload.review.author : payload.pull_request.user.login;
const response = await fetch(
`https://api.github.com/orgs/${process.env.GITHUB_ORG}/teams/${process.env.TEAM_SLUG}/memberships/${author}`,
{
headers: {
Authorization: `token ${process.env.GITHUB_TOKEN}`,
},
}
);
return {
statusCode: 200,
body: JSON.stringify({
proceed: response.status === 200
})
};
};4. AWS Amplify Approach
Using AWS Amplify for preview deployments:
- Connect repository to AWS Amplify
- Create
amplify.yml:
version: 1
applications:
- frontend:
phases:
preBuild:
commands:
- npm ci
build:
commands:
- npm run build
artifacts:
baseDirectory: dist
files:
- '**/*'
cache:
paths:
- node_modules/**/*- Add Lambda function for team validation:
// amplify/backend/function/validateDeployment/src/index.js
const AWS = require('aws-sdk');
const { Octokit } = require('@octokit/rest');
exports.handler = async (event) => {
const octokit = new Octokit({
auth: process.env.GITHUB_TOKEN
});
const { author } = JSON.parse(event.body);
try {
const { data } = await octokit.rest.teams.getMembershipForUserInOrg({
org: process.env.GITHUB_ORG,
team_slug: process.env.TEAM_SLUG,
username: author
});
return {
statusCode: 200,
body: JSON.stringify({
proceed: data.state === 'active'
})
};
} catch (error) {
return {
statusCode: 200,
body: JSON.stringify({
proceed: false
})
};
}
};Security Considerations
- Use environment-specific secrets
- Implement proper token rotation
- Use minimal required permissions
- Enable branch protection rules
- Implement request signing for webhooks
Cleanup Process
- Implement automatic cleanup of preview environments when PRs are closed
- Set up retention policies for preview assets
- Monitor resource usage and costs
Next Steps
- Choose preferred deployment solution
- Set up required secrets and permissions
- Configure team membership
- Test with sample PR
- Document process for team
Timeline
- Setup and Configuration: 2 days
- Implementation: 3 days
- Testing: 2 days
- Documentation: 1 day
Please review and provide feedback on the preferred approach.