Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions .github/workflows/security-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
name: Security Checks

on:
pull_request:
branches: [ "develop" ]

jobs:
security:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write # Needed to comment on PR

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

# -------------------------------
# 1️⃣ TypeScript Type Checking
# -------------------------------
- name: TypeScript Check
id: tsc
run: |
npx tsc --noEmit > ts-report.txt 2>&1 || true
cat ts-report.txt
continue-on-error: true
- uses: actions/upload-artifact@v4
with:
name: typescript-report
path: ts-report.txt

# -------------------------------
# 2️⃣ ESLint with Security Plugin
# -------------------------------
- name: ESLint Security Lint
id: eslint
run: |
npx eslint . --ext .ts,.tsx -f json -o eslint-report.json || true
cat eslint-report.json
continue-on-error: true
- uses: actions/upload-artifact@v4
with:
name: eslint-report
path: eslint-report.json

# -------------------------------
# 3️⃣ NPM Audit
# -------------------------------
- name: NPM Audit
id: npm_audit
run: |
npm audit --json > npm-audit-report.json || true
cat npm-audit-report.json
continue-on-error: true
- uses: actions/upload-artifact@v4
with:
name: npm-audit-report
path: npm-audit-report.json

# -------------------------------
# 4️⃣ Semgrep SAST
# -------------------------------
- name: Semgrep Scan
id: semgrep
uses: returntocorp/semgrep-action@v1
with:
config: "p/ci"
continue-on-error: true

# -------------------------------
# 5️⃣ Secret Scanning with Gitleaks
# -------------------------------
- name: Gitleaks Scan
id: gitleaks
uses: zricethezav/gitleaks-action@v2
with:
report_path: gitleaks-report.json
fail: false # Continue even if leaks are found

- uses: actions/upload-artifact@v4
with:
name: gitleaks-report
path: gitleaks-report.json

# -------------------------------
# 6️⃣ Post Summary as PR Comment
# -------------------------------
- name: Generate and Post Security Summary
if: always() # Always run this step to post a comment
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');

function readJsonReport(file) {
if (!fs.existsSync(file)) return '⚠️ No report';
const content = fs.readFileSync(file, 'utf8');
if (!content.trim()) return '✅ No issues';
try {
const data = JSON.parse(content);
return (Array.isArray(data) && data.length > 0) || (typeof data === 'object' && Object.keys(data).length > 0 && data.vulnerabilities) ? '❌ Issues found' : '✅ No issues';
} catch (e) {
return '⚠️ Report invalid';
}
}

const tscReport = fs.existsSync('ts-report.txt') && fs.readFileSync('ts-report.txt', 'utf8').trim();

const body = `
## 🔐 Security Check Summary

| Check Type | Result |
| --- | --- |
| **TypeScript** | ${{ steps.tsc.outcome == 'success' ? '✅ No issues' : '❌ Issues found' }} |
| **ESLint Security** | ${{ steps.eslint.outcome == 'success' ? '✅ No issues' : '❌ Issues found' }} |
| **NPM Audit** | ${{ steps.npm_audit.outcome == 'success' ? '✅ No issues' : '❌ Issues found' }} |
| **Semgrep SAST** | ${{ steps.semgrep.outcome == 'success' ? '✅ No issues' : '❌ Issues found' }} |
| **Gitleaks Secrets** | ${{ steps.gitleaks.outcome == 'success' ? '✅ No issues' : '❌ Issues found' }} |

${tscReport ? `
<details>
<summary>TypeScript Details</summary>

```
${tscReport}
```

</details>
` : ''}

> 📄 Detailed reports are in workflow artifacts.
`;

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});

# -------------------------------
# 7️⃣ Fail job if any check failed
# -------------------------------
- name: Fail if issues found
if: >
steps.tsc.outcome == 'failure' ||
steps.eslint.outcome == 'failure' ||
steps.npm_audit.outcome == 'failure' ||
steps.semgrep.outcome == 'failure' ||
steps.gitleaks.outcome == 'failure'
run: |
echo "Security checks failed. Please review the PR comment and artifacts."
exit 1
50 changes: 50 additions & 0 deletions .github/workflows/stagingdeploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Sync GitHub develop to GitLab main

on:
push:
branches:
- develop

jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Set up Git identity
run: |
git config --global user.email "jumalawrence98@gmail.com"
git config --global user.name "Jumalaw98"

- name: Add GitLab remote
run: |
git remote add gitlab https://oauth2:${{ secrets.GITLAB_TOKEN_STAGE }}@gitlab.com/jumalaw98/ndc-website-test.git

- name: Sync with GitLab main and push
id: sync
run: |
set -e # Stop if any command fails
git fetch gitlab main

if ! git rebase gitlab/main; then
echo "MERGE_CONFLICT=true" >> $GITHUB_ENV
exit 1
fi

git push gitlab HEAD:main

- name: Comment on failure
if: failure() && env.MERGE_CONFLICT == 'true'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: "⚠️ Sync to GitLab failed due to merge/rebase conflicts. Please resolve them manually before retrying."
})
Loading