Skip to content
Open
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
4 changes: 4 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_issue.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Instructions:
**Target branch:** <!-- e.g. develop, release-v0.17.x -->

## Observed behavior
<!-- REQUIRED -->
<!--
Description of the behavior that was observed, including screenshots or other references when applicable
-->
Expand All @@ -39,6 +40,7 @@ Please wrap errors in triple backticks for clean formatting like this:
…

## Expected behavior
<!-- REQUIRED -->
<!--
Description of what behavior was expected but did not occur
-->
Expand All @@ -53,13 +55,15 @@ Implications and real-world consequences for learners, coaches, admins, and othe
…

## Steps to reproduce
<!-- REQUIRED -->
<!--
Precise steps that someone else can follow in order to see this behavior
-->

…

## Context
<!-- REQUIRED -->
<!--
Tell us about your environment, including:
* Application version
Expand Down
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/enhancement_issue.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ Instructions:
**Target branch:** <!-- e.g. develop, release-v0.17.x -->

## Current behavior
<!-- REQUIRED -->
<!-- Briefly describe the current behavior; you may include screenshots, code, and notes -->

## Desired behavior
<!-- REQUIRED -->
<!-- Briefly describe the behavior you would like to see -->

## Value add
Expand Down
7 changes: 7 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_issue.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,21 @@ type: Tracking Issue
-->

## Requirements
<!-- REQUIRED -->

### What problem are we solving?
<!-- REQUIRED -->

### Why this? Why now?
<!-- REQUIRED -->

## Outcomes
<!-- REQUIRED -->

- [Specific, measurable outcome]

## Constraints
<!-- REQUIRED -->

- [Budget, deadline, technical limitation]

Expand All @@ -48,12 +53,14 @@ type: Tracking Issue
- [Explicit exclusion]

## Context
<!-- REQUIRED -->

### Relevant Feedback

- [Feedback from partners, users, clearinghouse, teammates]

### Technical Context
<!-- REQUIRED -->

- [Relevant systems, prior art, technical considerations]

Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/other_issue.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ about: For issues that don't fit any other category
-->

## Description
<!-- REQUIRED -->



Expand Down
4 changes: 4 additions & 0 deletions .github/ISSUE_TEMPLATE/product_issue.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,23 @@ type: Tracking Issue
_[General guidance: Product issues should describe the feature, but are not actually technically specced for dev work.]_

## Overview
<!-- REQUIRED -->

_[First, the workflow in one sentence]_

### Description and outcomes
<!-- REQUIRED -->
_[Then, more detail. Provide a short summary and/or list key outcomes that the user should be able to accomplish with this feature.]_



### Resources
<!-- REQUIRED -->
- _[Link Gherkin Scenarios]_
- _[Link Figma Scenarios]_

### Accessibility Requirements
<!-- REQUIRED -->


## AI usage
Expand Down
3 changes: 3 additions & 0 deletions .github/ISSUE_TEMPLATE/technical_task_issue.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Instructions:
-->

## Overview
<!-- REQUIRED -->

<!--
Describe what needs to be done and why.
Expand All @@ -36,6 +37,7 @@ Do NOT provide the solution - equip the developer to find it.
-->

### The Change
<!-- REQUIRED -->

<!--
Describe what needs to change and the general direction, using "should" or similar language to express an expected change.
Expand Down Expand Up @@ -68,6 +70,7 @@ Helps prevent scope creep and keeps PRs focused.
-->

### Acceptance Criteria
<!-- REQUIRED -->

<!--
Checklist of requirements for the task to be considered complete.
Expand Down
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/technical_tracking_issue.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ Instructions:
-->

## Overview
<!-- REQUIRED -->

<!--
Describe what this tracking issue encompasses and why the work matters.
Keep it concise: 3-5 sentences covering the "what" and "why".
-->

### Scope
<!-- REQUIRED -->

<!--
Define boundaries clearly.
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/automation-caller.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ on: # zizmor: ignore[dangerous-triggers]
issues:
types:
- assigned
- edited
- labeled
- opened
- reopened
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/automation-group-issues.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
LE_BOT_PRIVATE_KEY: ${{ secrets.LE_BOT_PRIVATE_KEY }}
issue-validation:
name: Issue Validation
if: ${{ github.event_name == 'issues' && github.event.action == 'opened' }}
if: ${{ github.event_name == 'issues' && (github.event.action == 'opened' || (contains(fromJSON('["edited","reopened"]'), github.event.action) && contains(github.event.issue.labels.*.name, 'needs-template'))) }}
uses: learningequality/.github/.github/workflows/issue-validation.yml@main
permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/automation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
SLACK_COMMUNITY_NOTIFICATIONS_WEBHOOK_URL: ${{ secrets.SLACK_COMMUNITY_NOTIFICATIONS_WEBHOOK_URL }}
issues:
name: Issues
if: ${{ (github.event_name == 'issues' && contains(fromJSON('["opened","reopened"]'), github.event.action)) || (github.event_name == 'issues' && contains(fromJSON('["labeled","unlabeled"]'), github.event.action) && github.event.label.name == 'help wanted') || (github.event_name == 'issues' && github.event.action == 'labeled' && (github.event.label.name == 'good first issue' || github.event.label.name == 'help wanted')) || (github.event_name == 'issues' && contains(fromJSON('["assigned","unassigned"]'), github.event.action)) || (github.event_name == 'issues' && github.event.action == 'opened') }}
if: ${{ (github.event_name == 'issues' && contains(fromJSON('["opened","reopened"]'), github.event.action)) || (github.event_name == 'issues' && contains(fromJSON('["labeled","unlabeled"]'), github.event.action) && github.event.label.name == 'help wanted') || (github.event_name == 'issues' && github.event.action == 'labeled' && (github.event.label.name == 'good first issue' || github.event.label.name == 'help wanted')) || (github.event_name == 'issues' && contains(fromJSON('["assigned","unassigned"]'), github.event.action)) || (github.event_name == 'issues' && (github.event.action == 'opened' || (contains(fromJSON('["edited","reopened"]'), github.event.action) && contains(github.event.issue.labels.*.name, 'needs-template')))) }}
uses: learningequality/.github/.github/workflows/automation-group-issues.yml@main
permissions:
contents: read
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/issue-validation.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Ask rtibblesbot to validate a contributor issue
name: Check a contributor issue against the templates and request validation
on:
workflow_call:
secrets:
Expand All @@ -25,6 +25,9 @@ jobs:
needs: [check-if-contributor]
if: ${{ needs.check-if-contributor.outputs.is_contributor == 'true' }}
runs-on: ubuntu-latest
concurrency:
group: issue-validation-${{ github.event.issue.number }}
cancel-in-progress: false
steps:
- name: Generate App Token
id: generate-token
Expand Down
4 changes: 2 additions & 2 deletions automation-registry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ automations:
leaf: issue-validation.yml
on:
issues:
types: [opened]
if: "github.event_name == 'issues' && github.event.action == 'opened'"
types: [opened, edited, reopened]
if: "github.event_name == 'issues' && (github.event.action == 'opened' || (contains(fromJSON('[\"edited\",\"reopened\"]'), github.event.action) && contains(github.event.issue.labels.*.name, 'needs-template')))"
secrets:
LE_BOT_APP_ID: required
LE_BOT_PRIVATE_KEY: required
Expand Down
1 change: 1 addition & 0 deletions automation-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ on: # zizmor: ignore[dangerous-triggers]
issues:
types:
- assigned
- edited
- labeled
- opened
- reopened
Expand Down
19 changes: 15 additions & 4 deletions docs/community-automations.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ A section is required when its heading carries a `<!-- REQUIRED -->` comment in
<!-- REQUIRED -->
```

A `###` heading can be marked too. A section runs to the next heading of the same or higher level, so a `##` section includes its `###` subsections. A body's heading matches the template's at either level and in any case.

A template that marks no section requires every level-two heading, so that a repo is strict rather than silently unchecked. To change what a repo requires, edit the markers in that repo's template. No change is required here.

Four states fail, and the log and comment name every one of them rather than stopping at the first:
Expand All @@ -108,9 +110,14 @@ These two automations ask `rtibblesbot` to validate claims in contributor-submit

## `issue-validation`

Runs on `issues: [opened]`. It proceeds only if the repository is in `ISSUE_VALIDATION_REPOS`, the issue opener is a contributor, and the issue does not already have the `community-issue-review` label.
Runs on `issues: [opened, edited, reopened]` for open issues whose opener is a contributor, in public repositories. `edited` and `reopened` only run while the issue carries `needs-template`, so issues opened before the check existed are never flagged.

It first checks the description against this repo's `.github/ISSUE_TEMPLATE/*.md`, using the `<!-- REQUIRED -->` rules of `pull-request-template`. The issue does not record which template it came from, so it passes if it satisfies any one of them.

It posts a comment mentioning `@rtibblesbot` and adds the label. If the label does not exist in the repository, the add-label call creates it.
- **Fails:** posts one comment naming the template it shares the most headings with and what that template still needs, and adds `needs-template`. No validation is requested.
- **Passes:** deletes that comment, removes `needs-template`, and requests validation, unless the issue already carries `community-issue-review`.

Validation is requested by a comment mentioning `@rtibblesbot` and the `community-issue-review` label. If a label does not exist in the repository, the add-label call creates it.

**The mention is essential.** The agent polls its GitHub notifications and has no inbound endpoint, so a mention is the only way to reach it. Adding a label does not generate a notification, and a handle inside backticks, as in `BOT_MESSAGE_RTIBBLESBOT_REVIEW`, does not trigger one either.

Expand Down Expand Up @@ -145,18 +152,22 @@ The weekly `unassign-inactive-issues` run also sweeps stalled validations throug

If the agent never responds, for example, because the service is down or all available tokens have reached their limits, the label would otherwise remain indefinitely. The sweep removes it when the issue's `labeled` event is older than `ISSUE_REVIEW_MAX_DAYS` days.

The same run closes, as not planned, every open issue labelled `needs-template` for longer than `ISSUE_TEMPLATE_MAX_DAYS` days, with `BOT_MESSAGE_ISSUE_TEMPLATE_CLOSED`. To keep an issue open, a maintainer fixes its description or removes the label. Reopening a closed issue reruns the check and restarts the clock.

## Scope and configuration

Neither automation closes issues or acts on the validation findings. The agent's comment recommends whether the issue should be closed; a maintainer must request that action in a reply.
Neither automation acts on the validation findings. The agent's comment recommends whether the issue should be closed; a maintainer must request that action in a reply.

Configure the following constants in `scripts/constants.js`:

- `ISSUE_VALIDATION_REPOS`: The repositories where validation runs, which are the community repositories plus the sandbox the automations are tested in.
- `LABEL_COMMUNITY_ISSUE_REVIEW`: The label applied while validation is in progress.
- `ISSUE_VALIDATION_MARKER`: The marker that signals validation completion, shared with `learningequality/coding-agent`.
- `ISSUE_REVIEW_MAX_DAYS`: The maximum age of the label before the sweep clears it.
- `BOT_MESSAGE_ISSUE_VALIDATION`: The comment text posted to request validation.
- `ISSUE_VALIDATION_FOLLOW_UPS`: The six verdicts and the follow-up each one asks a maintainer for, used in the Slack line.
- `LABEL_NEEDS_TEMPLATE`: The label on an issue that fails the template check.
- `ISSUE_TEMPLATE_MAX_DAYS`: How long that label stays on before the sweep closes the issue.
- `BOT_MESSAGE_ISSUE_TEMPLATE_CLOSED`: The comment posted when the sweep closes an issue.

# `holiday-message`

Expand Down
18 changes: 13 additions & 5 deletions scripts/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,15 @@ const BOT_MESSAGE_ISSUE_VALIDATION =
`- @rtibblesbot's comments are LLM-generated, so please evaluate them critically.\n\n` +
`A maintainer decides what happens next. This check does not close the issue.`;

const LABEL_NEEDS_TEMPLATE = 'needs-template';
const ISSUE_TEMPLATE_MAX_DAYS = 7;
const ISSUE_TEMPLATE_MARKER = '<!-- issue-template-check -->';

const BOT_MESSAGE_ISSUE_TEMPLATE_CLOSED =
`**Closing this issue because its description still doesn't follow an issue template ` +
`after ${ISSUE_TEMPLATE_MAX_DAYS} days.** Once you've edited it to follow one, ` +
`comment here and a maintainer can reopen it.`;

// Repositories to include in PR statistics reports
const PR_STATS_REPOS = [
'kolibri',
Expand All @@ -200,10 +209,6 @@ const PR_STATS_REPOS = [
// Repositories in which we accept open-source contributions
const COMMUNITY_REPOS = [...PR_STATS_REPOS];

// No other automation gates on the repo, so all of them already run in the
// sandbox. See docs/testing-automations.md.
const ISSUE_VALIDATION_REPOS = [...COMMUNITY_REPOS, 'test-actions'];

// Every place GitHub reads a pull request template from. The contents API is
// case sensitive, so both spellings are needed.
const PR_TEMPLATE_PATHS = [
Expand Down Expand Up @@ -244,14 +249,17 @@ module.exports = {
LABEL_COMMUNITY_REVIEW,
BOT_MESSAGE_COMMUNITY_REVIEW,
LABEL_COMMUNITY_ISSUE_REVIEW,
ISSUE_VALIDATION_REPOS,
ISSUE_VALIDATION_MARKER,
ISSUE_VALIDATION_DUPLICATE_VERDICT,
ISSUE_VALIDATION_FOLLOW_UPS,
ISSUE_VALIDATION_NO_VERDICT,
ISSUE_VALIDATION_NO_VERDICT_FOLLOW_UP,
ISSUE_REVIEW_MAX_DAYS,
BOT_MESSAGE_ISSUE_VALIDATION,
LABEL_NEEDS_TEMPLATE,
ISSUE_TEMPLATE_MAX_DAYS,
ISSUE_TEMPLATE_MARKER,
BOT_MESSAGE_ISSUE_TEMPLATE_CLOSED,
TEAMS_WITH_CLOSE_CONTRIBUTORS,
HOLIDAY_MESSAGE,
PR_STATS_REPOS,
Expand Down
Loading
Loading