diff --git a/.github/workflow-templates/org-bot-caller.properties.json b/.github/workflow-templates/org-bot-caller.properties.json new file mode 100644 index 0000000..8c2fec6 --- /dev/null +++ b/.github/workflow-templates/org-bot-caller.properties.json @@ -0,0 +1,11 @@ +{ + "name": "Organization Issue/PR Bot Caller", + "description": "Calls the centralized th30d4y org bot workflow for new issues and pull requests.", + "iconName": "octicon-comment-discussion", + "categories": [ + "Automation" + ], + "filePatterns": [ + ".*" + ] +} diff --git a/.github/workflow-templates/org-bot-caller.yml b/.github/workflow-templates/org-bot-caller.yml new file mode 100644 index 0000000..2bd7cba --- /dev/null +++ b/.github/workflow-templates/org-bot-caller.yml @@ -0,0 +1,22 @@ +name: Organization Issue/PR Bot Caller + +on: + issues: + types: [opened] + pull_request: + types: [opened] + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + org-bot: + uses: th30d4y/.github/.github/workflows/org-bot.yml@main + with: + event_type: ${{ github.event_name == 'issues' && 'Issue' || 'Pull Request' }} + number: ${{ github.event.issue.number || github.event.pull_request.number }} + title: ${{ github.event.issue.title || github.event.pull_request.title }} + url: ${{ github.event.issue.html_url || github.event.pull_request.html_url }} + secrets: inherit diff --git a/.github/workflows/org-bot.yml b/.github/workflows/org-bot.yml index 1080faa..44f63a9 100644 --- a/.github/workflows/org-bot.yml +++ b/.github/workflows/org-bot.yml @@ -1,6 +1,24 @@ name: Organization Issue/PR Bot on: + workflow_call: + inputs: + event_type: + description: Issue or Pull Request + required: false + type: string + number: + description: Issue or pull request number + required: false + type: number + title: + description: Issue or pull request title (optional; falls back to "(no title)") + required: false + type: string + url: + description: Issue or pull request URL + required: false + type: string issues: types: [opened] pull_request: @@ -22,6 +40,24 @@ jobs: script: | try { const payload = context.payload; + if (context.eventName === "workflow_call") { + const eventType = ${{ toJson(inputs.event_type) }}; + const number = ${{ toJson(inputs.number) }}; + const title = ${{ toJson(inputs.title) }}; + const url = ${{ toJson(inputs.url) }}; + + if (!eventType || number == null || !url) { + core.setFailed("workflow_call requires event_type, number, and url inputs."); + return; + } + + core.setOutput("type", eventType); + core.setOutput("number", String(number)); + core.setOutput("title", title || "(no title)"); + core.setOutput("url", url); + return; + } + if (context.eventName === "issues" && payload.issue) { core.setOutput("type", "Issue"); core.setOutput("number", String(payload.issue.number)); @@ -47,15 +83,20 @@ jobs: uses: actions/github-script@v7 with: script: | - const message = - context.eventName === "issues" - ? "👋 Thank you for opening this issue. We will review it and get back to you soon. — th30d4y" - : "👋 Hello! Thanks for your contribution. We will review this and get back to you as soon as possible. — th30d4y"; - const issueNumber = context.issue.number; + const eventType = ${{ toJson(steps.metadata.outputs.type) }}; + const message = eventType === "Issue" + ? "👋 Thank you for opening this issue. We will review it and get back to you soon. — th30d4y" + : "👋 Hello! Thanks for your contribution. We will review this and get back to you as soon as possible. — th30d4y"; + const issueNumber = Number(${{ toJson(steps.metadata.outputs.number) }}); const owner = context.repo.owner; const repo = context.repo.repo; try { + if (Number.isNaN(issueNumber) || issueNumber <= 0) { + core.setFailed("Unable to determine issue/pull request number for comment."); + return; + } + const comments = await github.paginate(github.rest.issues.listComments, { owner, repo, diff --git a/README.md b/README.md index 5a86cfe..3776803 100644 --- a/README.md +++ b/README.md @@ -1 +1,66 @@ # .github + +Organization-wide GitHub defaults and shared automation. + +## Organization Issue/PR Bot rollout + +This repository now provides: + +- A centralized reusable workflow: `.github/workflows/org-bot.yml` +- A workflow template for other repositories: `.github/workflow-templates/org-bot-caller.yml` + +### 1) Configure organization secrets + +In **Organization Settings → Secrets and variables → Actions**, create: + +- `EMAIL_USER` +- `EMAIL_PASS` + +Grant both secrets to all repositories that should use the bot. + +### 2) Enable in each repository + +In each target repository, add the caller workflow from template: + +- `.github/workflows/org-bot-caller.yml` + +Or copy this minimum caller workflow: + +```yml +name: Organization Issue/PR Bot Caller + +on: + issues: + types: [opened] + pull_request: + types: [opened] + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + org-bot: + uses: th30d4y/.github/.github/workflows/org-bot.yml@main + with: + event_type: ${{ github.event_name == 'issues' && 'Issue' || 'Pull Request' }} + number: ${{ github.event.issue.number || github.event.pull_request.number }} + title: ${{ github.event.issue.title || github.event.pull_request.title }} + url: ${{ github.event.issue.html_url || github.event.pull_request.html_url }} + secrets: inherit +``` + +> Tip: once you publish a stable tag for this workflow (for example `v1`), prefer `@v1` instead of `@main` so repositories get controlled, versioned updates instead of inheriting breaking changes immediately. + +### 3) Validate and roll out + +1. Enable on 1–2 repositories first. +2. Open a test issue and a test PR to confirm: + - welcome comment is posted + - owner email is sent +3. Roll out to remaining repositories. + +### 4) Optional enforcement + +If your GitHub plan supports required workflows/rulesets, enforce the caller workflow org-wide. Otherwise, each repository must include the caller workflow file.