From 87fc93cb2f8c7390af7e1bf6dd38f3675cd91112 Mon Sep 17 00:00:00 2001 From: dejaguarkyng Date: Mon, 1 Jun 2026 17:01:31 +0000 Subject: [PATCH] Add shared CI and security baseline --- .github/ISSUE_TEMPLATE/bug_report.yml | 49 ++++++ .github/ISSUE_TEMPLATE/config.yml | 8 + .github/ISSUE_TEMPLATE/feature_request.yml | 35 +++++ .github/PULL_REQUEST_TEMPLATE.md | 26 ++++ .github/dependabot.yml | 12 ++ .github/workflows/pr-ci.yml | 22 +++ .github/workflows/reusable-node-pr-ci.yml | 141 ++++++++++++++++++ .github/workflows/reusable-static-pr-ci.yml | 82 ++++++++++ CI_CD_ROADMAP.md | 29 ++++ CONTRIBUTING.md | 10 +- SECURITY.md | 4 +- SUPPORT.md | 10 ++ workflow-templates/node-pr-ci.properties.json | 7 + workflow-templates/node-pr-ci.yml | 29 ++++ .../static-pr-ci.properties.json | 7 + workflow-templates/static-pr-ci.yml | 23 +++ 16 files changed, 490 insertions(+), 4 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/pr-ci.yml create mode 100644 .github/workflows/reusable-node-pr-ci.yml create mode 100644 .github/workflows/reusable-static-pr-ci.yml create mode 100644 CI_CD_ROADMAP.md create mode 100644 SUPPORT.md create mode 100644 workflow-templates/node-pr-ci.properties.json create mode 100644 workflow-templates/node-pr-ci.yml create mode 100644 workflow-templates/static-pr-ci.properties.json create mode 100644 workflow-templates/static-pr-ci.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..d29bd84 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,49 @@ +name: Bug report +description: Report a reproducible problem in a Jungle Grid public repository. +title: "[Bug]: " +body: + - type: markdown + attributes: + value: | + Do not report security vulnerabilities here. Email security@junglegrid.dev instead. + - type: input + id: repository + attributes: + label: Repository or package + description: Which Jungle Grid repository, package, CLI, MCP server, or example is affected? + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected behavior + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual behavior + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce + description: Include commands, configuration snippets without secrets, and minimal examples. + validations: + required: true + - type: textarea + id: environment + attributes: + label: Environment + description: Include OS, Node.js/runtime version, package version, MCP host, browser, or CLI details as relevant. + validations: + required: false + - type: textarea + id: logs + attributes: + label: Logs or screenshots + description: Remove API keys, tokens, job secrets, customer data, and private URLs before posting. + render: text + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..d50a84f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Security vulnerability + url: mailto:security@junglegrid.dev + about: Please report vulnerabilities privately instead of opening a public issue. + - name: Jungle Grid documentation + url: https://junglegrid.dev/docs + about: Read product and platform documentation. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..31a54a7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,35 @@ +name: Feature request +description: Suggest a focused improvement for a Jungle Grid public repository. +title: "[Feature]: " +body: + - type: markdown + attributes: + value: | + Do not include private credentials, customer data, or undisclosed security issues. + - type: textarea + id: problem + attributes: + label: Problem + description: What workflow or limitation should this improve? + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed solution + description: Describe the smallest useful change. + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + validations: + required: false + - type: textarea + id: context + attributes: + label: Additional context + description: Link related issues, docs, or examples. + validations: + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..28f2944 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,26 @@ +## Summary + +## Type of Change + +- [ ] Bug fix +- [ ] Feature +- [ ] Documentation +- [ ] CI, security, or maintenance + +## Validation + +- [ ] I ran the relevant tests/checks locally +- [ ] I updated documentation where needed +- [ ] Not applicable + +## Security and Secrets + +- [ ] This change does not commit secrets, private keys, tokens, or `.env` files +- [ ] This change does not expose secrets to pull requests from forks +- [ ] Security-sensitive behavior has been called out for maintainers + +## Checklist + +- [ ] The change is focused and easy to review +- [ ] New or changed behavior is covered by tests where practical +- [ ] CI is expected to pass diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..2739009 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + time: "09:00" + groups: + github-actions: + patterns: + - "*" diff --git a/.github/workflows/pr-ci.yml b/.github/workflows/pr-ci.yml new file mode 100644 index 0000000..048e628 --- /dev/null +++ b/.github/workflows/pr-ci.yml @@ -0,0 +1,22 @@ +name: PR CI + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + static: + if: github.event_name != 'pull_request' || !github.event.pull_request.draft + uses: ./.github/workflows/reusable-static-pr-ci.yml + permissions: + contents: read + with: + working-directory: "." diff --git a/.github/workflows/reusable-node-pr-ci.yml b/.github/workflows/reusable-node-pr-ci.yml new file mode 100644 index 0000000..881f66e --- /dev/null +++ b/.github/workflows/reusable-node-pr-ci.yml @@ -0,0 +1,141 @@ +name: Reusable Node PR CI + +on: + workflow_call: + inputs: + node-version: + description: Node.js version to install. + required: false + type: string + default: "20" + package-manager: + description: "Package manager to use: npm, pnpm, yarn, or bun." + required: true + type: string + working-directory: + description: Directory containing the package manifest and lockfile. + required: false + type: string + default: "." + run-lint: + description: Run npm/pnpm/yarn/bun lint script. + required: false + type: boolean + default: false + run-format: + description: Run npm/pnpm/yarn/bun format check script. + required: false + type: boolean + default: false + format-script: + description: Script name for formatting checks. + required: false + type: string + default: "format:check" + run-typecheck: + description: Run npm/pnpm/yarn/bun typecheck script. + required: false + type: boolean + default: false + run-tests: + description: Run npm/pnpm/yarn/bun test script. + required: false + type: boolean + default: false + run-build: + description: Run npm/pnpm/yarn/bun build script. + required: false + type: boolean + default: false + +permissions: + contents: read + +jobs: + node-pr-ci: + name: Node PR CI + runs-on: ubuntu-latest + timeout-minutes: 20 + defaults: + run: + working-directory: ${{ inputs.working-directory }} + + steps: + - name: Check out repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: Validate package manager input + run: | + case "${{ inputs.package-manager }}" in + npm|pnpm|yarn|bun) ;; + *) echo "Unsupported package manager: ${{ inputs.package-manager }}" >&2; exit 1 ;; + esac + + - name: Set up Node.js + if: inputs.package-manager != 'bun' + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: ${{ inputs.node-version }} + cache: ${{ inputs.package-manager }} + cache-dependency-path: | + ${{ inputs.working-directory }}/package-lock.json + ${{ inputs.working-directory }}/npm-shrinkwrap.json + ${{ inputs.working-directory }}/pnpm-lock.yaml + ${{ inputs.working-directory }}/yarn.lock + + - name: Set up Node.js without dependency cache + if: inputs.package-manager == 'bun' + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: ${{ inputs.node-version }} + + - name: Set up Bun + if: inputs.package-manager == 'bun' + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 + with: + bun-version: latest + + - name: Enable Corepack + if: inputs.package-manager == 'pnpm' || inputs.package-manager == 'yarn' + run: corepack enable + + - name: Install dependencies + run: | + case "${{ inputs.package-manager }}" in + npm) + npm ci + ;; + pnpm) + pnpm install --frozen-lockfile + ;; + yarn) + if node -e "const p=require('./package.json'); process.exit(/^yarn@([2-9]|[1-9][0-9])\./.test(p.packageManager || '') ? 0 : 1)"; then + yarn install --immutable + else + yarn install --frozen-lockfile + fi + ;; + bun) + bun install --frozen-lockfile + ;; + esac + + - name: Run lint + if: inputs.run-lint + run: ${{ inputs.package-manager }} run lint + + - name: Run format check + if: inputs.run-format + run: ${{ inputs.package-manager }} run ${{ inputs.format-script }} + + - name: Run typecheck + if: inputs.run-typecheck + run: ${{ inputs.package-manager }} run typecheck + + - name: Run tests + if: inputs.run-tests + run: ${{ inputs.package-manager }} test + + - name: Run build + if: inputs.run-build + run: ${{ inputs.package-manager }} run build diff --git a/.github/workflows/reusable-static-pr-ci.yml b/.github/workflows/reusable-static-pr-ci.yml new file mode 100644 index 0000000..6edc1a2 --- /dev/null +++ b/.github/workflows/reusable-static-pr-ci.yml @@ -0,0 +1,82 @@ +name: Reusable Static PR CI + +on: + workflow_call: + inputs: + working-directory: + description: Directory to validate. + required: false + type: string + default: "." + run-secret-scan: + description: Run TruffleHog verified secret scan. + required: false + type: boolean + default: true + +permissions: + contents: read + +jobs: + static-pr-ci: + name: Static PR CI + runs-on: ubuntu-latest + timeout-minutes: 15 + defaults: + run: + working-directory: ${{ inputs.working-directory }} + + steps: + - name: Check out repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + fetch-depth: 0 + + - name: Validate JSON files + run: | + mapfile -t files < <(find . -path './.git' -prune -o -type f \( -name '*.json' -o -name '*.json.example' \) -print) + if [ "${#files[@]}" -eq 0 ]; then + echo "No JSON files found." + exit 0 + fi + python3 -m json.tool "${files[@]}" > /dev/null + + - name: Validate YAML files + run: | + mapfile -t files < <(find . -path './.git' -prune -o -type f \( -name '*.yml' -o -name '*.yaml' \) -print) + if [ "${#files[@]}" -eq 0 ]; then + echo "No YAML files found." + exit 0 + fi + ruby -e 'require "yaml"; ARGV.each { |path| YAML.load_file(path) }' "${files[@]}" + + - name: Validate shell syntax + run: | + mapfile -t files < <(find . -path './.git' -prune -o -type f \( -name '*.sh' -o -perm -111 \) -print) + if [ "${#files[@]}" -eq 0 ]; then + echo "No shell files found." + exit 0 + fi + for file in "${files[@]}"; do + if head -n 1 "$file" | grep -Eq '^#!.*/(env +)?(ba)?sh'; then + bash -n "$file" + elif [ "${file##*.}" = "sh" ]; then + bash -n "$file" + fi + done + + - name: Block committed dotenv/private key files + run: | + if find . -path './.git' -prune -o -type f \( -name '.env' -o -name '.env.*' -o -name '*.pem' -o -name '*.key' \) ! -name '.env.example' -print | grep -q .; then + echo "Potential secret-bearing file detected. Commit examples only, such as .env.example." >&2 + exit 1 + fi + + - name: Scan for verified secrets + if: inputs.run-secret-scan + uses: trufflesecurity/trufflehog@466da5b0bb161144f6afca9afe5d57975828c410 # v3.90.8 + with: + path: ${{ inputs.working-directory }} + base: ${{ github.event.repository.default_branch }} + head: HEAD + extra_args: --only-verified diff --git a/CI_CD_ROADMAP.md b/CI_CD_ROADMAP.md new file mode 100644 index 0000000..663e45a --- /dev/null +++ b/CI_CD_ROADMAP.md @@ -0,0 +1,29 @@ +# CI/CD Roadmap + +## Current CI Baseline + +Jungle Grid public repositories should use pull request CI with least-privilege `GITHUB_TOKEN` permissions, dependency installation from lockfiles, no deployment credentials, and no secrets passed to forked pull requests. + +The shared reusable workflows in this repository provide: + +- Node/TypeScript PR CI for repositories with real package scripts. +- Static/example PR CI for documentation, shell, JSON, YAML, and configuration repositories. +- Verified secret scanning in PR CI through TruffleHog. + +## Repository Coverage + +- `.github`: organization standards, default community files, workflow templates, and reusable CI. +- `mcp-server`: npm package candidate/current package; CI should build and test before merge. +- `junglegrid-examples`: examples and documentation; CI should validate configuration files and shell examples. +- `forgegrid`: Next.js application; CI should run the real lint/build scripts before merge. + +## CD Readiness + +Production deployment and package publishing are intentionally not configured in this baseline. A release workflow should be added only after each repository has a documented release contract, required maintainers, rollback expectations, and scoped credentials. + +Recommended future release paths: + +- `mcp-server`: use a manual `workflow_dispatch` or tag-based npm publish workflow with npm provenance, an `NPM_TOKEN` scoped to `@jungle-grid/mcp`, protected environments, and required maintainer approval. +- `junglegrid-examples`: no deployment is needed unless examples are later published as documentation artifacts. +- `forgegrid`: define the hosting target, environment names, required secrets, preview behavior, production approval policy, and rollback plan before adding CD. +- `.github`: no deployment workflow is needed. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 27cfb76..bc663d0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,9 @@ Thanks for your interest in contributing. - Use descriptive commit messages. - Link related issues in the pull request description. - Include before/after details for user-visible changes. -- Ensure CI passes before requesting review. +- Run the relevant lint, typecheck, test, build, or example validation commands before requesting review. +- Ensure CI passes before requesting review or merge. +- Do not include secrets, private keys, `.env` files, customer data, or production credentials. ## Reporting Issues @@ -31,4 +33,8 @@ Follow existing style and conventions in the repository. Prefer readability and ## Questions -If you are unsure about design or scope, open an issue first to discuss. \ No newline at end of file +If you are unsure about design or scope, open an issue first to discuss. + +## Security Issues + +Do not report vulnerabilities in public issues or pull requests. Email security@junglegrid.dev and follow `SECURITY.md`. diff --git a/SECURITY.md b/SECURITY.md index 87fae7a..634598c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,7 +2,7 @@ ## Reporting a Vulnerability -Please do not open public GitHub issues for security reports. +Please do not open public GitHub issues for security reports or suspected vulnerabilities. Email: security@junglegrid.dev @@ -15,4 +15,4 @@ Include: We aim to acknowledge valid reports within 72 hours. -GitHub specifically recommends adding a SECURITY.md file so people know how to report vulnerabilities privately. \ No newline at end of file +Please give maintainers a reasonable opportunity to investigate and remediate before public disclosure. diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000..f98893f --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,10 @@ +# Support + +For product documentation, start with: + +- Website: https://junglegrid.dev +- Docs: https://junglegrid.dev/docs + +Use GitHub issues for reproducible bugs, documentation corrections, and focused feature requests in the relevant repository. + +Do not report security vulnerabilities in public issues. Follow the private reporting process in `SECURITY.md`. diff --git a/workflow-templates/node-pr-ci.properties.json b/workflow-templates/node-pr-ci.properties.json new file mode 100644 index 0000000..9dfa644 --- /dev/null +++ b/workflow-templates/node-pr-ci.properties.json @@ -0,0 +1,7 @@ +{ + "name": "Node/TypeScript PR CI", + "description": "PR validation for npm, pnpm, yarn, or bun Node.js repositories using the Jungle Grid reusable CI workflow.", + "iconName": "octicon workflow", + "categories": ["JavaScript", "TypeScript", "Node", "Continuous integration"], + "filePatterns": ["package.json$"] +} diff --git a/workflow-templates/node-pr-ci.yml b/workflow-templates/node-pr-ci.yml new file mode 100644 index 0000000..a5890a2 --- /dev/null +++ b/workflow-templates/node-pr-ci.yml @@ -0,0 +1,29 @@ +name: Node PR CI + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + node: + if: github.event_name != 'pull_request' || !github.event.pull_request.draft + uses: Jungle-Grid/.github/.github/workflows/reusable-node-pr-ci.yml@main # Replace main with a reviewed commit SHA after installing. + permissions: + contents: read + with: + node-version: "20" + package-manager: "npm" + working-directory: "." + run-lint: false + run-format: false + run-typecheck: false + run-tests: true + run-build: true diff --git a/workflow-templates/static-pr-ci.properties.json b/workflow-templates/static-pr-ci.properties.json new file mode 100644 index 0000000..750ddd6 --- /dev/null +++ b/workflow-templates/static-pr-ci.properties.json @@ -0,0 +1,7 @@ +{ + "name": "Static Example/Docs PR CI", + "description": "PR validation for documentation, examples, templates, shell snippets, JSON, and YAML configuration repositories.", + "iconName": "octicon checklist", + "categories": ["Automation", "Continuous integration"], + "filePatterns": ["README.md$", ".*\\.json$", ".*\\.ya?ml$", ".*\\.sh$"] +} diff --git a/workflow-templates/static-pr-ci.yml b/workflow-templates/static-pr-ci.yml new file mode 100644 index 0000000..8056799 --- /dev/null +++ b/workflow-templates/static-pr-ci.yml @@ -0,0 +1,23 @@ +name: Static PR CI + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + static: + if: github.event_name != 'pull_request' || !github.event.pull_request.draft + uses: Jungle-Grid/.github/.github/workflows/reusable-static-pr-ci.yml@main # Replace main with a reviewed commit SHA after installing. + permissions: + contents: read + with: + working-directory: "." + run-secret-scan: true