diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..fde2f48 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,31 @@ +name: Bug report +description: Report a reproducible problem with a Beatrice project. +title: "Bug: " +body: + - type: markdown + attributes: + value: For security vulnerabilities, use the private reporting option on the repository's Security tab. + - type: input + id: version + attributes: + label: Version and platform + description: Include the app version or commit, OS and relevant hardware or browser. + validations: + required: true + - type: textarea + id: steps + attributes: + label: Steps to reproduce + validations: + required: true + - type: textarea + id: behavior + attributes: + label: Expected and actual behavior + validations: + required: true + - type: textarea + id: logs + attributes: + label: Relevant logs or screenshots + description: Redact tokens, personal data and sensitive audio. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..b14fbb7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: true +contact_links: + - name: Report a security vulnerability + url: https://github.com/Project-Beatrice-V2/.github/blob/main/SECURITY.md + about: Follow the private reporting instructions for the affected repository. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..a9ef4db --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: '/' + schedule: + interval: weekly + day: monday + time: '05:00' + timezone: Etc/UTC + open-pull-requests-limit: 2 + groups: + actions-minor-patch: + patterns: ["*"] + update-types: [minor, patch] diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..d80b667 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,11 @@ +## Summary + + + +## Verification + + + +## Risk and rollout + + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..7faa3d0 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,35 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +permissions: {} + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + configuration: + name: Configuration validation + runs-on: ubuntu-24.04 + timeout-minutes: 10 + permissions: + contents: read + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0 + with: + python-version: '3.12' + - run: python -m pip install check-jsonschema==0.39.0 + - name: Validate workflow and community form schemas + run: | + check-jsonschema --builtin-schema vendor.github-workflows .github/workflows/*.yml + check-jsonschema --builtin-schema vendor.github-issue-forms .github/ISSUE_TEMPLATE/bug_report.yml + check-jsonschema --builtin-schema vendor.github-issue-config .github/ISSUE_TEMPLATE/config.yml + check-jsonschema --builtin-schema vendor.mergify .mergify.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..e00a9c6 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,34 @@ +name: CodeQL + +on: + push: + branches: [main] + pull_request: + schedule: + - cron: '50 4 * * 1' + workflow_dispatch: + +permissions: {} + +concurrency: + group: codeql-${{ github.ref }} + cancel-in-progress: true + +jobs: + analyze: + name: CodeQL analysis + runs-on: ubuntu-24.04 + timeout-minutes: 35 + permissions: + contents: read + security-events: write + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + # This repository ships assets or documentation and GitHub Actions workflows. + - uses: github/codeql-action/init@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3 + with: + languages: actions + build-mode: none + - uses: github/codeql-action/analyze@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3 diff --git a/.github/workflows/pr-policy.yml b/.github/workflows/pr-policy.yml new file mode 100644 index 0000000..69ab4fc --- /dev/null +++ b/.github/workflows/pr-policy.yml @@ -0,0 +1,58 @@ +name: PR policy + +on: + pull_request: + types: [opened, reopened, synchronize, edited, ready_for_review] + +permissions: {} + +concurrency: + group: pr-policy-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + policy: + name: Review policy + if: '!github.event.pull_request.draft' + runs-on: ubuntu-24.04 + timeout-minutes: 5 + permissions: + pull-requests: read + steps: + - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const pr = context.payload.pull_request; + const title = pr.title.trim(); + const description = (pr.body ?? '') + .replace(//g, '') + .split('\n') + .filter(line => !/^\s*(?:#|[-*] \[)/.test(line)) + .join(' ') + .trim(); + + if (pr.user.type !== 'Bot') { + if (title.length < 8 || /^(?:draft|wip)(?:\b|:)/i.test(title)) { + core.setFailed('Use a descriptive PR title and keep unfinished work in draft.'); + } + if (description.length < 15) { + core.setFailed('Describe the change and how you verified it in the PR body.'); + } + } + + const files = await github.paginate(github.rest.pulls.listFiles, { + ...context.repo, + pull_number: pr.number, + per_page: 100 + }); + const paths = files.flatMap(file => [file.filename, file.previous_filename].filter(Boolean)); + const tests = /(^|\/)(tests?|__tests__)(\/|$)|(?:^|\/)test_[^/]+\.py$|\.(?:test|spec)\.[cm]?[jt]sx?$/i; + const source = /\.(?:[cm]?[jt]sx?|py|c|h|css|html|ipynb|sh|ps1|bat)$/i; + const risk = /(^\.github\/|(?:^|\/)(?:package(?:-lock)?\.json|(?:uv|poetry)\.lock|requirements[^/]*\.txt|pyproject\.toml|vercel\.json|(?:start|setup)[^/]*\.(?:sh|ps1|bat))$|\.(?:dll|exe|vst3|bin|zip)$)/i; + + if (paths.some(path => source.test(path) && !tests.test(path)) && !paths.some(path => tests.test(path))) { + core.warning('Source changed without a test change. Add coverage where practical or describe manual verification.'); + } + if (paths.some(path => risk.test(path)) || files.length < pr.changed_files) { + core.warning('Review dependency, automation, installer and binary changes with extra care.'); + } diff --git a/.mergify.yml b/.mergify.yml new file mode 100644 index 0000000..d766efe --- /dev/null +++ b/.mergify.yml @@ -0,0 +1,23 @@ +# yaml-language-server: $schema=https://docs.mergify.com/mergify-configuration-schema.json +pull_request_rules: + - name: Squash an approved README-only PR when a maintainer opts in + disabled: + reason: Enable after main has required reviews and checks, and the app is installed without bypass access. + conditions: + - base = main + - -draft + - label = automerge:docs + - -author = dependabot[bot] + - "#files = 1" + - files = README.md + - "#approved-reviews-by >= 1" + - "#changes-requested-reviews-by = 0" + - "#commits-behind = 0" + - "#check-failure = 0" + - check-success = @github-actions/Configuration validation + - check-success = @github-actions/Review policy + - check-success = @github-actions/CodeQL analysis + - check-success = @github-advanced-security/CodeQL + actions: + merge: + method: squash diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..354c003 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,9 @@ +# Contributing to Project Beatrice V2 + +Open the README in the repository you want to change and follow its platform and dependency setup. For projects with a Node lockfile, use `npm ci`. Keep dependency changes and their lockfile changes together. + +Open pull requests against `main`. Give each PR a descriptive title and summarize the change, why it matters, and how you verified it. Use draft status while the work is in progress. For changes to application behavior, update the existing tests where practical. If the repository has no harness or the change needs audio hardware, record the platform, steps and result of your manual verification. + +Keep generated installers, model weights, sample audio and credentials out of source changes unless the repository specifically manages those assets. Model contributions should follow the model repository's licensing and provenance requirements. Call out changes to dependencies, permissions, GitHub Actions, release scripts, launchers and bundled binaries in the PR so maintainers can review them closely. + +Maintainers should review the diff and all applicable checks before merging. Report vulnerabilities privately as described in [SECURITY.md](SECURITY.md). See the [automation guide](docs/automation.md) for check coverage and maintainer setup. diff --git a/README.md b/README.md index e67769c..ff4f507 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[](https://github.com/Project-Beatrice-V2/.github/actions/workflows/ci.yml) [](https://github.com/Project-Beatrice-V2/.github/actions/workflows/codeql.yml) [](https://github.com/Project-Beatrice-V2/.github/actions/workflows/pr-policy.yml) +