Skip to content
Merged
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
121 changes: 121 additions & 0 deletions .github/workflows/cla-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
name: CLA Check

on:
pull_request:
types: [opened, synchronize, reopened]

permissions:
pull-requests: write
contents: read
statuses: write

jobs:
cla-check:
runs-on: ubuntu-latest
steps:
- name: Fetch & check CLA signature
id: check
run: |
# Fetch signatures.json directly from raw GitHub (public repo)
# Use wget as primary (handles 200-with-404-body better than curl)
wget -q -O signatures.json "https://raw.githubusercontent.com/codecoradev/.github/main/.cla/signatures.json" 2>/dev/null \
|| curl -sfL "https://raw.githubusercontent.com/codecoradev/.github/main/.cla/signatures.json" -o signatures.json 2>/dev/null \
|| echo '{"signatures":[]}' > signatures.json
# Validate JSON — if invalid, use empty
python3 -c "import json; json.load(open('signatures.json'))" 2>/dev/null \
|| echo '{"signatures":[]}' > signatures.json
python3 - << 'EOF'
import json, os

author = os.environ["PR_AUTHOR"]
with open("signatures.json") as f:
data = json.load(f)

signatures = data.get("signatures", [])
found = any(
s.get("github_username", "").lower() == author.lower()
for s in signatures
)

with open(os.environ["GITHUB_OUTPUT"], "a") as f:
f.write(f"signed={'true' if found else 'false'}\n")

print(f"CLA signed by @{author}: {found}")
EOF
env:
PR_AUTHOR: ${{ github.event.pull_request.user.login }}

- name: Comment on PR (unsigned only)
if: steps.check.outputs.signed != 'true'
uses: actions/github-script@v7
with:
script: |
const author = '${{ github.event.pull_request.user.login }}';
const prNumber = ${{ github.event.pull_request.number }};

const body = [
'## ⚠️ CodeCoraDev CLA Bot',
'',
`Hi @${author}! Thanks for your contribution.`,
'',
'Before this PR can be reviewed, please sign our Contributor License Agreement:',
'',
'- 📋 **Individual?** → [Sign CLA Individual](https://codecoradev.github.io/cla/?type=individual)',
'- 🏢 **Corporate?** → [Sign CLA Corporate](https://codecoradev.github.io/cla/?type=corporate)',
'',
'---',
'<sub>By signing, you agree to the terms in [CLA_INDIVIDUAL.md](https://github.com/codecoradev/.github/blob/main/CLA_INDIVIDUAL.md) or [CLA_CORPORATE.md](https://github.com/codecoradev/.github/blob/main/CLA_CORPORATE.md).</sub>',
].join('\n');

// Find existing CLA bot comment
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});

const botComment = comments.data.find(c =>
c.user.login === 'github-actions[bot]' &&
c.body.includes('CodeCoraDev CLA Bot')
);

if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body,
});
}

- name: Set commit status
uses: actions/github-script@v7
with:
script: |
const signed = '${{ steps.check.outputs.signed }}' === 'true';
await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: '${{ github.event.pull_request.head.sha }}',
state: signed ? 'success' : 'failure',
context: 'CLA Check',
description: signed
? '✅ CLA signed'
: '❌ CLA not signed — sign at https://codecoradev.github.io/cla',
target_url: signed
? 'https://github.com/codecoradev/.github/blob/main/.cla/signatures.json'
: 'https://codecoradev.github.io/cla',
});

- name: Fail if not signed
if: steps.check.outputs.signed != 'true'
run: |
echo "❌ CLA not signed by ${{ github.event.pull_request.user.login }}"
exit 1
12 changes: 5 additions & 7 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ import { createConfig } from '@codecora/theme/vitepress/config'

export default createConfig({
product: 'covecto',
title: 'Covecto',
description: 'Dual-engine image vectorization — pixel-exact for icons, smooth curves for art.',
title: 'Covecto: Image to SVG Vectorizer CLI | CodeCora',
description: 'Covecto converts images to SVG with a dual-engine vectorizer CLI: pixel-exact for icons, smooth Bézier curves for art. SVG, PDF, EPS output. Zero dependencies.',
accent: 'orange',
repo: 'covecto',
head: [
['meta', { property: 'og:title', content: 'Covecto — Image to SVG Vectorization' }],
['meta', { property: 'og:description', content: 'Dual-engine image vectorizer: pixel-exact for icons, Bézier splines for art. CLI + HTTP API.' }],
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
],
// NOTE: do NOT pass `head` here — @codecora/theme createConfig() drops
// opts.head (never merged into its hardcoded head array). OG/Twitter meta
// lives in docs/index.md frontmatter instead; theme fix tracked separately.
ignoreDeadLinks: true,
sidebar: [
{
Expand Down
22 changes: 22 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
---
layout: home
head:
- - meta
- property: og:url
content: 'https://codecora.dev/covecto/docs'
- - meta
- property: og:title
content: 'Covecto: Image to SVG Vectorizer CLI | CodeCora'
- - meta
- property: og:description
content: 'Covecto converts images to SVG with a dual-engine vectorizer CLI: pixel-exact for icons, smooth Bézier curves for art. SVG, PDF, EPS output. Zero dependencies.'
- - meta
- name: twitter:card
content: 'summary_large_image'
- - meta
- name: twitter:title
content: 'Covecto: Image to SVG Vectorizer CLI | CodeCora'
- - meta
- name: twitter:description
content: 'Covecto converts images to SVG with a dual-engine vectorizer CLI: pixel-exact for icons, smooth Bézier curves for art. SVG, PDF, EPS output. Zero dependencies.'
- - link
- rel: canonical
href: 'https://codecora.dev/covecto/docs'

hero:
name: covecto
Expand Down
Loading