Skip to content

Feature/rest api platform [DO NOT MERGE] #29

Feature/rest api platform [DO NOT MERGE]

Feature/rest api platform [DO NOT MERGE] #29

Workflow file for this run

name: Deploy Preview
on:
pull_request:
branches: [ master ]
types: [opened, synchronize, reopened]
permissions:
contents: read
packages: read
pull-requests: write
deployments: write
id-token: write
concurrency:
group: preview-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.ref }}
cancel-in-progress: true
env:
NODE_ENV: development
HUSKY: 0
jobs:
security-check:
name: Security Check
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
pull-requests: read
contents: read
outputs:
is-fork: ${{ steps.check.outputs.is-fork }}
is-authorized: ${{ steps.check.outputs.is-authorized }}
steps:
- name: Verify user
uses: "deriv-com/shared-actions/.github/actions/verify_user_in_organization@v1"
with:
username: ${{github.event.pull_request.user.login}}
token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
- name: Check PR source and permissions
id: check
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const isFork = pr.head.repo.full_name !== pr.base.repo.full_name;
let isAuthorized = false;
try {
const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: pr.user.login
});
isAuthorized = ['admin', 'write'].includes(permission.permission);
} catch (e) {
console.error('Error checking permissions:', e);
isAuthorized = false;
}
core.setOutput('is-fork', isFork.toString());
core.setOutput('is-authorized', isAuthorized.toString());
if (isFork && !isAuthorized) {
core.notice('⚠️ This PR is from a fork and requires approval from maintainers');
}
preview:
name: Deploy Preview
needs: security-check
runs-on: ubuntu-latest
if: |
github.event.workflow_run.conclusion != 'action_required' ||
github.event.workflow_run.conclusion == 'approved'
environment:
name: preview
url: ${{ steps.deploy.outputs.deployment-url }}
permissions:
deployments: write
issues: write
pull-requests: write
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Additional security checks for forks
id: security_checks
if: needs.security-check.outputs.is-fork == 'true'
run: |
# Function to check file patterns
check_patterns() {
local file="$1"
local patterns=(
"crypto\."
"eval[\s]*\("
"child_process"
"exec[A-Z][a-z]*\("
"http[s]?\."
"net\."
"process\.env"
"require\(['\"]child_process"
"fs\."
"new\s+Function"
"__proto__"
"Function\("
"require\(['\"]\.\."
"require\(['\"]~"
"process\.binding"
"v8\."
"vm\."
"\.constructor\."
"Object\.prototype"
"Object\.defineProperty"
"Object\.setPrototypeOf"
)
for pattern in "${patterns[@]}"; do
if grep -q "$pattern" "$file"; then
echo "⚠️ Suspicious pattern found in $file: $pattern"
return 1
fi
done
return 0
}
exit_code=0
while IFS= read -r file; do
if [ -f "$file" ]; then
if file "$file" | grep -q "binary"; then
echo "❌ Binary file detected: $file"
exit_code=1
fi
if ! file "$file" | grep -q "binary"; then
if ! check_patterns "$file"; then
exit_code=1
fi
fi
fi
done < <(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }})
if [ $exit_code -eq 0 ]; then
echo "SECURITY_CHECK_RESULT=✅ All security checks passed" >> $GITHUB_ENV
else
echo "SECURITY_CHECK_RESULT=⚠️ Security review required - See above for details" >> $GITHUB_ENV
exit 1
fi
- name: Setup environment
uses: ./.github/actions/setup-environment
- name: Deploy to Vercel
id: deploy
timeout-minutes: 10
uses: ./.github/actions/deploy/vercel/development
env:
# Pass all repository secrets to the action
REACT_APP_WS_PORT: ${{ secrets.REACT_APP_WS_PORT }}
REACT_APP_WS_URL: ${{ secrets.REACT_APP_WS_URL }}
REACT_OAUTH_URL: ${{ secrets.REACT_OAUTH_URL }}
REACT_CURRENT_ENVIRONMENT: preview
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
pr-number: ${{ github.event.pull_request.number }}
- name: Add preview URL to pull request
uses: actions/github-script@v7
with:
script: |
const isFork = '${{ needs.security-check.outputs.is-fork }}' === 'true';
const isAuthorized = '${{ needs.security-check.outputs.is-authorized }}' === 'true';
let securityStatus = '';
if (isFork) {
securityStatus = `\n\n🔒 Security Status:
- PR is from a fork repository
- Author permission level: ${isAuthorized ? '✅ Authorized' : '⚠️ Requires Approval'}
- Security checks: ${process.env.SECURITY_CHECK_RESULT || '✅ Passed'}
Note: First-time contributors require maintainer approval for workflow runs.`;
}
const deploymentUrl = '${{ steps.deploy.outputs.deployment-url }}';
const comment = `✨ Preview deployment is ready!
🔗 Preview URL: ${deploymentUrl}
📝 Commit: ${context.sha.substring(0, 7)}
🕒 Deployed at: ${new Date().toISOString()}${securityStatus}`;
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
- name: Update deployment status
uses: ./.github/actions/deployment-status
if: success()
with:
environment: 'preview'
deployment-url: ${{ steps.deploy.outputs.deployment-url }}
sha: ${{ github.event.pull_request.head.sha }}
status: 'success'
description: '✨ Preview deployment completed'
- name: Handle deployment failure
if: failure()
uses: ./.github/actions/deployment-status
with:
environment: 'preview'
deployment-url: ${{ steps.deploy.outputs.deployment-url }}
sha: ${{ github.event.pull_request.head.sha }}
status: 'failure'
description: '❌ Preview deployment failed'