diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 4d1a508a72..0000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: Bug Report -about: Report a bug to help us improve -title: '' -labels: 'kind/bug' -assignees: '' ---- - -# Checklist - -* [ ] I've searched the issue queue to verify this is not a duplicate bug report. -* [ ] I've included steps to reproduce the bug. -* [ ] I've pasted the output of `kargo version`. -* [ ] I've pasted logs, if applicable. - -# Description - - - -# Screenshots - - - -# Steps to Reproduce - - - -# Version - -``` -Paste the output from `kargo version` here. -``` - -# Logs - -``` -Paste any relevant application logs here. -``` diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..f350ee6fd5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,66 @@ +name: Bug Report +description: Report a bug to help us improve +labels: ["kind/bug"] +body: +- type: checkboxes + id: duplicate-check + attributes: + label: Pre-submission checklist + options: + - label: I have searched existing issues and confirmed this is not a duplicate. + required: true +- type: textarea + id: description + attributes: + label: Description + description: A clear and concise description of the bug. + validations: + required: true +- type: textarea + id: steps-to-reproduce + attributes: + label: Steps to Reproduce + description: Steps to reproduce the behavior. + placeholder: | + 1. ... + 2. ... + 3. ... + validations: + required: true +- type: textarea + id: expected-behavior + attributes: + label: Expected Behavior + description: What did you expect to happen? + validations: + required: true +- type: textarea + id: actual-behavior + attributes: + label: Actual Behavior + description: What actually happened? + validations: + required: true +- type: input + id: version + attributes: + label: Kargo Version + description: Output of `kargo version`. + placeholder: e.g. v1.3.0 + validations: + required: true +- type: textarea + id: logs + attributes: + label: Relevant Logs + description: If applicable, paste relevant log output. This will be automatically formatted as code. + render: shell + validations: + required: false +- type: textarea + id: screenshots + attributes: + label: Screenshots + description: If applicable, add screenshots to help explain the bug. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index edae68a834..7c0d01fe9d 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,4 +1,4 @@ -blank_issues_enabled: true +blank_issues_enabled: false contact_links: - name: Have you read the docs? diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 547dd0101d..0000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -name: Feature Request -about: Propose an enhancement for consideration by the maintainers -title: '' -labels: -- 'kind/proposal' -- 'kind/enhancement' -assignees: '' ---- - -__Note:__ If you're requesting a Helm chart option that may be very niche and not useful to the community at large, please consider using Kustomize to apply "last mile" tweaks to the output of `helm template` to suit your needs instead. - -# Checklist - -* [ ] I've searched the issue queue to verify this is not a duplicate feature request. -* [ ] I've pasted the output of `kargo version`, if applicable. -* [ ] I've pasted logs, if applicable. - -# Proposed Feature - - - -# Motivation - - diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000000..c2e6539662 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,54 @@ +name: Feature Request +description: Propose an enhancement for consideration by the maintainers +labels: ["kind/proposal", "kind/enhancement"] +body: +- type: markdown + attributes: + value: | + **Please read before submitting.** + + Feature requests are reviewed by maintainers on a best-effort basis. + Submitting a request does not guarantee it will be implemented. + + **Do NOT begin work on a feature until all blocking labels have been removed + from the issue by a maintainer.** Pull requests linked to issues that still + carry blocking labels (`kind/proposal`, `needs discussion`, `needs research`, + `maintainer only`, `area/security`, `size/large`, `size/x-large`, + `size/xx-large`) will be automatically closed. + + See the [Contributor Guide](https://docs.kargo.io/contributor-guide) for + full details on the contribution process. + + If you are requesting a Helm chart option that may be very niche and not + useful to the community at large, please consider using Kustomize to apply + "last mile" tweaks to the output of `helm template` instead. +- type: checkboxes + id: preconditions + attributes: + label: Pre-submission checklist + options: + - label: I have searched existing issues and confirmed this is not a duplicate. + required: true + - label: I understand that submitting a feature request does not guarantee it will be implemented. + required: true +- type: textarea + id: proposal + attributes: + label: Proposed Feature + description: What new feature would you like to see? + validations: + required: true +- type: textarea + id: motivation + attributes: + label: Motivation and Use Case + description: Why do you need this? Please give concrete examples of when someone would use this. + validations: + required: true +- type: textarea + id: alternatives + attributes: + label: Alternatives Considered + description: Have you considered any alternative solutions or workarounds? + validations: + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..a5b6cedb3a --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,34 @@ +**All pull requests must reference an existing issue with no blocking labels.** +PRs that do not meet this requirement will be automatically closed. See the +[Contributor Guide](https://docs.kargo.io/contributor-guide) for details. + +## Issue Reference + +Closes # + +## Description + + + +## Checklist + +- [ ] The PR is linked to an existing issue. +- [ ] The linked issue has no blocking labels (`kind/proposal`, + `needs discussion`, `needs research`, `maintainer only`, `area/security`, + `size/large`, `size/x-large`, `size/xx-large`). +- [ ] I have added or updated tests as appropriate. +- [ ] I have added or updated documentation as appropriate. + +### AI Use Disclosure + +Select one: + +- [ ] This PR was written by a human _without_ AI assistance. +- [ ] This PR was written by a human _with_ AI assistance. A human has reviewed every line prior to opening the PR. +- [ ] This PR was written by an AI _with human supervision._ A human has reviewed every line prior to opening the PR. +- [ ] This PR was written entirely by AI. No human has reviewed this prior to opening the PR. + +### Sign-Off + +- [ ] All commits are signed off (`git commit -s`) **(required)** +- [ ] All commits are cryptographically signed (`git commit -S`) **(preferred)** diff --git a/.github/workflows/pr-policy-check.yaml b/.github/workflows/pr-policy-check.yaml new file mode 100644 index 0000000000..67acd0a436 --- /dev/null +++ b/.github/workflows/pr-policy-check.yaml @@ -0,0 +1,108 @@ +name: PR Policy Check + +on: + pull_request_target: + types: + - opened + +permissions: + pull-requests: write + issues: read + +jobs: + check: + name: Validate linked issue + runs-on: ubuntu-latest + if: >- + github.event.pull_request.author_association != 'MEMBER' && + github.event.pull_request.author_association != 'OWNER' && + !endsWith(github.event.pull_request.user.login, '[bot]') + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d # v2.16.1 + with: + egress-policy: audit + + - name: Check for linked issue and blocking labels + env: + GH_TOKEN: ${{ secrets.AKUITYBOT_PAT }} + GH_REPO: ${{ github.repository }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + # Read PR body safely from the event payload instead of an env var. + PR_BODY=$(jq -r '.pull_request.body // ""' "$GITHUB_EVENT_PATH") + + # Parse issue reference from PR body. + # Supports: Closes #N, Fixes #N, Resolves #N (and singular forms), + # plus full URL variants like https://github.com/owner/repo/issues/N + ISSUE_NUMBER=$(echo "$PR_BODY" | grep -oiP '(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+(?:https://github\.com/[^/]+/[^/]+/issues/)?#?(\d+)' | head -1 | grep -oP '\d+$' || true) + + if [ -z "$ISSUE_NUMBER" ]; then + gh pr edit "$PR_NUMBER" --add-label "policy/no-linked-issue" + gh pr comment "$PR_NUMBER" --body "$(cat <<'COMMENT' + ## Automated Policy Notice + + This pull request has been closed because it does not reference an unblocked issue. + + All contributions to Kargo require a linked, unblocked issue. This ensures that proposed changes have been reviewed by maintainers before effort is invested. + + **To contribute:** + + 1. Open a [Bug Report](https://github.com/${{ github.repository }}/issues/new?template=bug_report.yml) or [Feature Request](https://github.com/${{ github.repository }}/issues/new?template=feature_request.yml) + 2. Wait for a maintainer to review the issue and remove any blocking labels + 3. Reference the issue in your PR using `Closes #` + + See the [Contributor Guide](https://docs.kargo.io/contributor-guide) for full details. + COMMENT + )" + gh pr close "$PR_NUMBER" + exit 1 + fi + + echo "Found linked issue: #$ISSUE_NUMBER" + + # Fetch the issue's labels. + LABELS=$(gh issue view "$ISSUE_NUMBER" --json labels --jq '.labels[].name') + + # Check for blocking labels. + BLOCKING_LABELS=( + "kind/proposal" + "needs discussion" + "needs research" + "maintainer only" + "area/security" + "size/large" + "size/x-large" + "size/xx-large" + ) + + FOUND_BLOCKERS="" + for blocker in "${BLOCKING_LABELS[@]}"; do + if echo "$LABELS" | grep -qxF "$blocker"; then + if [ -n "$FOUND_BLOCKERS" ]; then + FOUND_BLOCKERS="$FOUND_BLOCKERS, \`$blocker\`" + else + FOUND_BLOCKERS="\`$blocker\`" + fi + fi + done + + if [ -n "$FOUND_BLOCKERS" ]; then + gh pr edit "$PR_NUMBER" --add-label "policy/blocked-issue" + gh pr comment "$PR_NUMBER" --body "$(cat <- + !github.event.issue.pull_request && + ( + github.event.comment.author_association == 'MEMBER' || + github.event.comment.author_association == 'OWNER' + ) && + startsWith(github.event.comment.body, '/') + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d # v2.16.1 + with: + egress-policy: audit + + - name: Process command + env: + GH_TOKEN: ${{ secrets.AKUITYBOT_PAT }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.issue.number }} + COMMENT_BODY: ${{ github.event.comment.body }} + run: | + COMMAND=$(echo "$COMMENT_BODY" | head -1 | awk '{print $1}') + ARG=$(echo "$COMMENT_BODY" | head -1 | awk '{print $2}' | tr -d '#') + + case "$COMMAND" in + + /discuss) + gh issue edit "$NUMBER" --add-label "needs discussion" + gh issue comment "$NUMBER" --body "$(cat <<'MSG' + ## Discussion Needed + + A maintainer has indicated that this issue requires further discussion before any implementation work should begin. + + Please do not open a pull request for this issue until the discussion has concluded and all blocking labels have been removed. + MSG + )" + ;; + + /duplicate) + if [ -z "$ARG" ]; then + echo "::error::Usage: /duplicate #" + exit 1 + fi + gh issue comment "$NUMBER" --body "$(cat </dev/null || true + done + gh issue comment "$NUMBER" --body "$(cat <<'MSG' + ## Unblocked for Contribution + + A maintainer has unblocked this issue for external contribution. Process-blocking labels have been removed. + + If you would like to work on this, please comment to indicate your intent. + + Wait for a maintainer to acknowledge your comment and formally assign the issue to you before starting work. This ensures multiple contributors do not duplicate effort on the same issue. + + When you open a pull request, reference this issue using `Closes #`. + + Before starting, confirm the issue has no remaining blocking labels. See the [Contributor Guide](https://docs.kargo.io/contributor-guide) for details. + MSG + )" + ;; + + /help) + gh issue comment "$NUMBER" --body "$(cat <<'MSG' + ## Available Slash Commands + + | Command | Description | + |---------|-------------| + | `/discuss` | Add `needs discussion` label; blocks work | + | `/duplicate #N` | Close as duplicate of #N | + | `/enterprise` | Close as already planned for Kargo Enterprise | + | `/maintainer` | Add `maintainer only` label; blocks external contribution | + | `/research` | Add `needs research` label; blocks work | + | `/unblock` | Remove process-blocking labels; unblocks work | + | `/help` | Show this list | + MSG + )" + ;; + + *) + echo "Unknown command: $COMMAND" + exit 0 + ;; + esac + + pr-command: + name: Handle PR slash command + runs-on: ubuntu-latest + if: >- + github.event.issue.pull_request && + ( + github.event.comment.author_association == 'MEMBER' || + github.event.comment.author_association == 'OWNER' + ) && + startsWith(github.event.comment.body, '/') + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@fe104658747b27e96e4f7e80cd0a94068e53901d # v2.16.1 + with: + egress-policy: audit + + - name: Process command + env: + GH_TOKEN: ${{ secrets.AKUITYBOT_PAT }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.issue.number }} + COMMENT_BODY: ${{ github.event.comment.body }} + run: | + COMMAND=$(echo "$COMMENT_BODY" | head -1 | awk '{print $1}') + ARG=$(echo "$COMMENT_BODY" | head -1 | awk '{print $2}' | tr -d '#') + + case "$COMMAND" in + + /discuss) + gh pr edit "$NUMBER" --add-label "needs discussion" + gh pr comment "$NUMBER" --body "$(cat <<'MSG' + ## Discussion Needed + + A maintainer has indicated that further discussion is needed before this pull request can be merged. + + Please do not merge this PR until the discussion has concluded and all blocking labels have been removed. + MSG + )" + ;; + + /duplicate) + if [ -z "$ARG" ]; then + echo "::error::Usage: /duplicate #" + exit 1 + fi + gh pr comment "$NUMBER" --body "$(cat </dev/null || true + done + gh pr comment "$NUMBER" --body "$(cat <<'MSG' + ## Unblocked for Merge + + A maintainer has removed blocking labels from this pull request. Review may now proceed. + MSG + )" + ;; + + /unsolicited) + gh pr comment "$NUMBER" --body "$(cat <<'MSG' + ## Contribution Policy Notice + + This pull request has been closed because it does not reference an unblocked issue. + + All contributions require a linked, unblocked issue to ensure that proposed changes have been reviewed by maintainers before effort is invested. + + **To contribute:** + + 1. Open a [Bug Report](https://github.com/${{ github.repository }}/issues/new?template=bug_report.yml) or [Feature Request](https://github.com/${{ github.repository }}/issues/new?template=feature_request.yml) + 2. Wait for a maintainer to review the issue and remove any blocking labels + 3. Reference the issue in your PR using `Closes #` + + See the [Contributor Guide](https://docs.kargo.io/contributor-guide) for details. + MSG + )" + gh pr close "$NUMBER" + ;; + + /help) + gh pr comment "$NUMBER" --body "$(cat <<'MSG' + ## Available Slash Commands + + | Command | Description | + |---------|-------------| + | `/discuss` | Add `needs discussion` label; blocks merge | + | `/duplicate #N` | Close as duplicate of #N | + | `/enterprise` | Close as already planned for Kargo Enterprise | + | `/maintainer` | Close; linked issue is maintainer-only | + | `/premature` | Close; linked issue is not unblocked | + | `/quality` | Close; does not meet quality standards | + | `/research` | Add `needs research` label; blocks merge | + | `/unblock` | Remove blocking labels; unblocks merge | + | `/unsolicited` | Close; no linked issue | + | `/help` | Show this list | + MSG + )" + ;; + + *) + echo "Unknown command: $COMMAND" + exit 0 + ;; + esac diff --git a/docs/docs/60-contributor-guide/index.md b/docs/docs/60-contributor-guide/index.md index acd5e36762..3e27f05d2f 100644 --- a/docs/docs/60-contributor-guide/index.md +++ b/docs/docs/60-contributor-guide/index.md @@ -1,27 +1,98 @@ --- -description: A comprehensive introduction for developers who are looking to get involved with contributing directly to the Kargo project +description: Policies and procedures for contributing to the Kargo project sidebar_label: Contributor Guide --- -# Kargo Contributor's Guide +# Contributor Guide -This contributor guide is intended as a comprehensive introduction for -developers who are looking to get involved with contributing directly to the -Kargo project. +This guide defines the policies and procedures for contributing to Kargo. Please +read it in full before opening issues or pull requests. + +## Process Overview + +Kargo follows an **issue-first contribution model**. Unless authored by a +maintainer, all code contributions require a linked issue that has been reviewed +and unblocked by maintainers in advance. :::caution Ideas and contributions from the community are always welcome, however, items not appearing on the [roadmap](../100-roadmap.md) are reviewed on a best-effort -basis. - -If you would like to contribute, please avoid wasted or duplicated effort by -discussing feature requests and design proposals with maintainers prior to -starting work. While we cannot guarantee specific timelines or outcomes, we -value and consider every submission. +basis. While we cannot guarantee specific timelines or outcomes, we value and +consider every submission. ::: +1. **Open an issue** using the + [Bug Report](https://github.com/akuity/kargo/issues/new?template=bug_report.yml) + or + [Feature Request](https://github.com/akuity/kargo/issues/new?template=feature_request.yml) + template. + +1. **Wait for maintainer review.** Maintainers will triage the issue, ask + clarifying questions, and determine whether the work aligns with the + project's priorities and [roadmap](../100-roadmap.md). + +1. **Wait for the issue to be unblocked.** When an issue is ready for external + contribution, a maintainer will remove all blocking labels. **Do not begin + work while any blocking labels are present.** + +1. **Open a pull request** that references the unblocked issue using + `Closes #` in the PR body. + +## Blocking Labels + +The following labels indicate an issue is **not ready for external +contribution**. Pull requests linked to issues carrying any of these labels will +be automatically closed. + +| Label | Meaning | +| ----- | ------- | +| `kind/proposal` | Feature request under consideration. Not yet unblocked. | +| `needs discussion` | Needs further discussion before any work begins. | +| `needs research` | Needs investigation or research before work begins. | +| `maintainer only` | Reserved for maintainers due to size, complexity, or sensitivity. | +| `area/security` | Involves security-sensitive code. Maintainer-coordinated only. | +| `size/large` | Large scope. Requires maintainer coordination. | +| `size/x-large` | Very large scope. Requires maintainer coordination. | +| `size/xx-large` | Extremely large scope. Requires maintainer coordination. | + +An issue is ready for external contribution when **none** of these labels are +present. + +## Automatic Enforcement + +Pull requests that do not observe the process described above are +**automatically closed**. This includes: + +- PRs with no linked issue. + +- PRs linked to issues that still carry blocking labels. + +- Unsolicited PRs (no corresponding issue exists). + +This enforcement applies to external contributors only. Maintainers are exempt. + +## Quality Expectations + +All pull requests must: + +- Be authored and reviewed by a human. AI-assisted coding is acceptable, but + every line must be understood and verified by the submitter. Submissions that + appear to be generated without meaningful human review will be closed. + +- Include appropriate tests for new and modified code. + +- Follow existing code conventions and patterns. + +- Include DCO sign-off on all commits (see [Signing Commits](signing-commits)). + +- Include documentation updates where user-facing behavior has changed. + +Cryptographic signing of all commits is strongly encouraged. + +## Specific Topics + import DocCardList from '@theme/DocCardList';