feat: new workflows (#470)

This commit is contained in:
Dani Akash
2026-03-17 18:56:55 +05:30
committed by GitHub
parent e67c17a0f8
commit 58adac17db
10 changed files with 58 additions and 150 deletions

192
.github/workflows/audit.yml vendored Normal file
View File

@@ -0,0 +1,192 @@
name: Daily Security Audit
on:
schedule:
# Runs at midnight IST (6:30 PM UTC previous day)
- cron: "30 18 * * *"
workflow_dispatch: # Allows manual triggering
jobs:
security-audit:
runs-on: ubuntu-latest
defaults:
run:
working-directory: packages/browseros-agent
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- name: Install dependencies
run: bun ci
- name: Run security audit
id: audit
continue-on-error: true
run: |
# Run audit and capture output (skip the version line)
bun audit --json 2>&1 | tail -n 1 > audit-results.json || true
# Check if vulnerabilities exist
VULN_COUNT=$(cat audit-results.json | bun -e "const data = JSON.parse(require('fs').readFileSync(0, 'utf-8')); console.log(Object.keys(data).reduce((sum, pkg) => sum + data[pkg].length, 0))")
echo "vuln_count=$VULN_COUNT" >> $GITHUB_OUTPUT
- name: Parse audit results
id: parse
if: always()
run: |
cat > parse-audit.ts << 'EOF'
const fs = require('fs');
const auditData = JSON.parse(fs.readFileSync('audit-results.json', 'utf-8'));
// Collect all vulnerabilities from all packages
const allVulns: any[] = [];
let totalCount = 0;
for (const [packageName, vulns] of Object.entries(auditData)) {
if (Array.isArray(vulns)) {
vulns.forEach((vuln: any) => {
allVulns.push({ ...vuln, packageName });
totalCount++;
});
}
}
if (totalCount === 0) {
console.log(JSON.stringify({
text: "✅ *Daily Security Audit - No Vulnerabilities Found*",
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: "✅ *Daily Security Audit*\n\nNo vulnerabilities found in dependencies!"
}
},
{
type: "context",
elements: [
{
type: "mrkdwn",
text: `Repository: ${process.env.GITHUB_REPOSITORY} | Branch: ${process.env.GITHUB_REF_NAME}`
}
]
}
]
}));
process.exit(0);
}
// Count by severity
const severityCounts = {
critical: 0,
high: 0,
moderate: 0,
low: 0
};
allVulns.forEach(vuln => {
severityCounts[vuln.severity as keyof typeof severityCounts]++;
});
let message = `⚠️ *Daily Security Audit - ${totalCount} Vulnerabilit${totalCount === 1 ? 'y' : 'ies'} Found*\n\n`;
message += `*Severity Breakdown:*\n`;
message += `• Critical: ${severityCounts.critical}\n`;
message += `• High: ${severityCounts.high}\n`;
message += `• Moderate: ${severityCounts.moderate}\n`;
message += `• Low: ${severityCounts.low}\n\n`;
message += `*Top Vulnerabilities:*\n`;
// Sort by severity
const severityOrder = { critical: 0, high: 1, moderate: 2, low: 3 };
allVulns.sort((a, b) =>
severityOrder[a.severity as keyof typeof severityOrder] -
severityOrder[b.severity as keyof typeof severityOrder]
);
allVulns.slice(0, 5).forEach(vuln => {
const emoji = {
critical: '🔴',
high: '🟠',
moderate: '🟡',
low: '🟢'
}[vuln.severity] || '⚪';
message += `\n${emoji} *${vuln.title}*\n`;
message += ` Package: \`${vuln.packageName}\`\n`;
message += ` Severity: ${vuln.severity.toUpperCase()}\n`;
message += ` Vulnerable: ${vuln.vulnerable_versions}\n`;
if (vuln.cwe?.length) {
message += ` CWE: ${vuln.cwe.join(', ')}\n`;
}
if (vuln.cvss?.score) {
message += ` CVSS: ${vuln.cvss.score}\n`;
}
if (vuln.url) {
message += ` <${vuln.url}|View Details>\n`;
}
});
if (allVulns.length > 5) {
message += `\n_...and ${allVulns.length - 5} more vulnerabilit${allVulns.length - 5 === 1 ? 'y' : 'ies'}_`;
}
const payload = {
text: `⚠️ Security Audit: ${totalCount} vulnerabilit${totalCount === 1 ? 'y' : 'ies'} found`,
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: message
}
},
{
type: "actions",
elements: [
{
type: "button",
text: {
type: "plain_text",
text: "View Full Report"
},
url: `https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`
}
]
},
{
type: "context",
elements: [
{
type: "mrkdwn",
text: `Repository: ${process.env.GITHUB_REPOSITORY} | Branch: ${process.env.GITHUB_REF_NAME}`
}
]
}
]
};
console.log(JSON.stringify(payload));
EOF
bun run parse-audit.ts > slack-payload.json
- name: Send to Slack
if: always()
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
run: |
curl -X POST \
-H 'Content-Type: application/json' \
-d @slack-payload.json \
$SLACK_WEBHOOK_URL
- name: Fail if vulnerabilities found
if: steps.audit.outputs.vuln_count != '0'
run: |
echo "Security audit found vulnerabilities"
exit 1

17
.github/workflows/branch-cleaner.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: GitHub Branch Cleaner
on:
schedule:
- cron: '0 0 * * 0'
workflow_dispatch:
jobs:
cleanup:
name: Clean up merged branches
runs-on: ubuntu-latest
steps:
- uses: mmorenoregalado/action-branches-cleaner@v2.0.3
with:
token: ${{ secrets.GITHUB_TOKEN }}
base_branches: main
days_old_threshold: 30

View File

@@ -1,11 +1,11 @@
name: 'CLA Assistant'
name: CLA Assistant
on:
issue_comment:
types: [created]
pull_request_target:
types: [opened, closed, synchronize]
# Explicitly configure permissions
permissions:
actions: write
contents: write
@@ -13,47 +13,46 @@ permissions:
statuses: write
jobs:
CLAAssistant:
cla:
runs-on: ubuntu-latest
if: |
(github.event_name == 'pull_request_target') ||
(github.event_name == 'issue_comment' && github.event.issue.pull_request &&
(github.event.comment.body == 'recheck' ||
github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA'))
steps:
- name: 'CLA Assistant'
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
- name: CLA Assistant
uses: contributor-assistant/github-action@v2.6.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_SIGNATURES_TOKEN }}
with:
# Path where signatures will be stored
path-to-signatures: 'signatures/version1/cla.json'
# Path to your CLA document
path-to-document: 'https://github.com/browseros-ai/BrowserOS/blob/main/CLA.md'
# Branch to store signatures (should not be protected)
path-to-signatures: 'cla-signatures.json'
path-to-document: 'https://github.com/${{ github.repository }}/blob/main/CLA.md'
branch: 'main'
# Allowlist for users who don't need to sign (bots, core team members)
allowlist: shadowfax92,felarof99,dependabot[bot],renovate[bot],github-actions[bot]
# Optional: Custom messages
remote-organization-name: 'browseros-ai'
remote-repository-name: 'cla-signatures'
allowlist: 'shadowfax92,felarof99,bot*,*[bot],dependabot,renovate,github-actions,snyk-bot,imgbot,greenkeeper,semantic-release-bot,allcontributors'
lock-pullrequest-aftermerge: false
custom-notsigned-prcomment: |
**CLA Assistant Lite bot** Thank you for your submission! We require contributors to sign our [Contributor License Agreement](https://github.com/browseros-ai/BrowserOS/blob/main/CLA.md) before we can accept your contribution.
Thank you for your contribution! Before we can merge this PR, we need you to sign our [Contributor License Agreement](https://github.com/${{ github.repository }}/blob/main/CLA.md).
By signing the CLA, you confirm that:
- You have read and agree to the AGPL-3.0 license terms
- Your contribution is your original work
- You grant us the rights to use your contribution under the AGPL-3.0 license
**To sign the CLA**, please add a comment to this PR with the following text:
**To sign the CLA, please comment on this PR with:**
`I have read the CLA Document and I hereby sign the CLA`
```
I have read the CLA Document and I hereby sign the CLA
```
You only need to sign once. After signing, this check will pass automatically.
---
<details>
<summary>Troubleshooting</summary>
- **Already signed but still failing?** Comment `recheck` to trigger a re-verification.
- **Signed with a different email?** Make sure your commit email matches your GitHub account email, or add your commit email to your GitHub account.
</details>
custom-pr-sign-comment: 'I have read the CLA Document and I hereby sign the CLA'
custom-allsigned-prcomment: |
**CLA Assistant Lite bot** ✅ All contributors have signed the CLA. Thank you for helping make BrowserOS better!
# Lock PR after merge to prevent signature tampering
lock-pullrequest-aftermerge: true
# Custom commit messages
create-file-commit-message: 'docs: Create CLA signatures file'
signed-commit-message: 'docs: $contributorName signed the CLA in $owner/$repo#$pullRequestNo'
All contributors have signed the CLA. Thank you!

42
.github/workflows/claude.yml vendored Normal file
View File

@@ -0,0 +1,42 @@
name: Claude Code
on:
pull_request:
types: [opened, ready_for_review]
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]
jobs:
claude:
if: |
github.event_name == 'pull_request' ||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude') && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude') && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude') && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.review.author_association)) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: read
id-token: write
actions: read
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
additional_permissions: |
actions: read

57
.github/workflows/code-quality.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
name: Code Quality
on:
pull_request:
branches:
- main
paths:
- 'packages/browseros-agent/**'
jobs:
biome:
name: runner / Biome
runs-on: ubuntu-latest
defaults:
run:
working-directory: packages/browseros-agent
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Setup Biome
uses: biomejs/setup-biome@v2
with:
version: latest
- name: Run Biome
run: biome ci .
typecheck:
name: runner / Typecheck
runs-on: ubuntu-latest
defaults:
run:
working-directory: packages/browseros-agent
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- name: Install dependencies
run: bun ci
- name: Run codegen
run: bun run --cwd apps/agent codegen
- name: Run Typecheck
run: bun run typecheck

20
.github/workflows/pr-title.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: PR Conventional Commit Validation
on:
pull_request:
types: [opened, synchronize, reopened, edited]
permissions:
pull-requests: write
issues: write
contents: read
jobs:
validate-pr-title:
runs-on: ubuntu-latest
steps:
- name: PR Conventional Commit Validation
uses: ytanikin/pr-conventional-commits@1.5.1
with:
task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert","build"]'
custom_labels: '{"feat": "feature", "fix": "fix", "docs": "documentation", "test": "test", "ci": "CI/CD", "refactor": "refactor", "perf": "performance", "chore": "chore", "revert": "revert", "wip": "WIP"}'

37
.github/workflows/release-agent-sdk.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: Release Agent SDK
on:
workflow_dispatch:
jobs:
publish:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
defaults:
run:
working-directory: packages/browseros-agent/packages/agent-sdk
steps:
- uses: actions/checkout@v6
- uses: oven-sh/setup-bun@v2
- uses: actions/setup-node@v6
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
- name: Install dependencies
run: bun ci
working-directory: packages/browseros-agent
- name: Build
run: bun run build
- name: Test
run: bun test
- name: Publish
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

27
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Tests
on: []
jobs:
test:
name: Run Tests
runs-on: macos-latest
timeout-minutes: 10
defaults:
run:
working-directory: packages/browseros-agent
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Setup Bun
uses: oven-sh/setup-bun@v2
- name: Install dependencies
run: bun ci
- name: Run all tests
run: bun test:all
env:
PUPPETEER_EXECUTABLE_PATH: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome