From cf5938c4323f1e9b5364ee0f9b6dd9a92fd4f2e4 Mon Sep 17 00:00:00 2001 From: Matthew Date: Tue, 10 Mar 2026 14:41:05 -0400 Subject: [PATCH] chore: just adding docs --- README.md | 181 +++++++++-------------- cache-cleanup/action.yml | 48 ------ docs/deploy-slack-action/index.md | 61 ++++++++ docs/draft-release-slack-action/index.md | 36 +++++ docs/helper-slack-action/index.md | 67 +++++++++ docs/public-ip/index.md | 55 +++++++ docs/slack-javascript-action/index.md | 21 +++ docs/slack-message-action/index.md | 103 +++++++++++++ 8 files changed, 414 insertions(+), 158 deletions(-) delete mode 100644 cache-cleanup/action.yml create mode 100644 docs/deploy-slack-action/index.md create mode 100644 docs/draft-release-slack-action/index.md create mode 100644 docs/helper-slack-action/index.md create mode 100644 docs/public-ip/index.md create mode 100644 docs/slack-javascript-action/index.md create mode 100644 docs/slack-message-action/index.md diff --git a/README.md b/README.md index e94579d..9474166 100644 --- a/README.md +++ b/README.md @@ -1,135 +1,96 @@ -# Basis Theory GitHub Actions +# Basis Theory Public GitHub Actions -## Deploy Notifier +A collection of reusable GitHub Actions maintained by [Basis Theory](https://basistheory.com) for deployment notifications, Slack messaging, CI cache management, and runner utilities. -This action will notify a Slack channel on specific deployment actions. +## Available Actions -### Inputs +| Action | Description | Docs | +|---|---|---| +| [deploy-slack-action](./deploy-slack-action) | High-level composite for deploy lifecycle notifications | [docs](./docs/deploy-slack-action/index.md) | +| [draft-release-slack-action](./draft-release-slack-action) | Notify Slack when a draft release is created | [docs](./docs/draft-release-slack-action/index.md) | +| [helper-slack-action](./helper-slack-action) | Core Node.js engine for all deploy/release Slack notifications | [docs](./docs/helper-slack-action/index.md) | +| [public-ip](./public-ip) | Get the GitHub Actions runner's public IPv4 address | [docs](./docs/public-ip/index.md) | +| [slack-javascript-action](./slack-javascript-action) | Shared JS library used by the Slack actions (not consumed directly) | [docs](./docs/slack-javascript-action/index.md) | +| [slack-message-action](./slack-message-action) | General-purpose send, update, and thread Slack messages | [docs](./docs/slack-message-action/index.md) | -- `slack-api-token` - **Required** The Slack API token. -- `channel` - **Required** The channel to send the message. -- `mention_person` - **Optional** The user to mention in the message. -- `status` - **Optional** The status of the run. Can be `start`, `done`, or - `request`. Default is `start`. +See the [`docs/`](./docs) directory for detailed documentation, inputs/outputs, and usage examples for each action. -### Example usage +## Quick Start + +### Deploy Notifications ```yaml name: Product Deploy on: release: - branches: [ master ] - types: [ released ] + branches: [master] + types: [released] jobs: - request_approval: + deploy: runs-on: ubuntu-latest steps: - - name: Send Deploy Request - uses: Basis-Theory/github-actions/deploy-slack-action@master - with: - slack-api-token: ${{ secrets.API_TOKEN }} - channel: ${{ vars.APPROVALS_CHANNEL }} - mention-person: ${{ vars.APPROVER }} - status: 'request' - - name: Start Deploy Message - uses: Basis-Theory/github-actions/deploy-slack-action@master - with: - slack-api-token: ${{ secrets.API_TOKEN }} - channel: ${{ vars.DEPLOY_CHANNEL }} - - name: Sleep for 10 seconds - run: sleep 10s - shell: bash - - name: Stop Deploy Message - if: always() - uses: Basis-Theory/github-actions/deploy-slack-action@master - with: - slack-api-token: ${{ secrets.API_TOKEN }} - channel: ${{ vars.DEPLOY_CHANNEL }} - status: 'done' + - name: Notify deploy start + uses: Basis-Theory/public-github-actions/deploy-slack-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: ${{ vars.DEPLOY_CHANNEL }} + + # ... deploy steps ... + + - name: Notify deploy done + if: always() + uses: Basis-Theory/public-github-actions/deploy-slack-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: ${{ vars.DEPLOY_CHANNEL }} + status: done ``` -## Slack - -This action sends a message to a Slack channel. +### Slack Messaging -### Inputs +```yaml +- name: Send a message + id: slack + uses: Basis-Theory/public-github-actions/slack-message-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: ${{ vars.CHANNEL }} + text: "Build started for ${{ github.repository }}" + +- name: Update the message + uses: Basis-Theory/public-github-actions/slack-message-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: ${{ vars.CHANNEL }} + update-message-id: ${{ steps.slack.outputs.message_id }} + text: "Build finished: ${{ job.status }}" +``` -- `slack-api-token` - **Required** The Slack API token. -- `channel` - **Required** The channel to send the message. -- `text` - **Optional** The text of the message. -- `blocks` - **Optional** The [blocks](https://app.slack.com/block-kit-builder/) - of the message. -- `update-message-id` - **Optional** The message ID to update. -- `thread-message-id` - **Optional** The message ID to add the message to a - thread. +### Public IP -### Outputs +```yaml +- name: Get runner IP + id: runner-ip + uses: Basis-Theory/public-github-actions/public-ip@master -- `message_id` - The message Id of the sent message +- run: echo "${{ steps.runner-ip.outputs.ipv4 }}" +``` -### Example +## Repository Structure -```yaml -name: Send Messages +``` +. +├── deploy-slack-action/ # Deploy notification composite action +├── draft-release-slack-action/ # Draft release notification composite action +├── helper-slack-action/ # Core Slack notification action (Node.js) +├── public-ip/ # Runner public IP composite action +├── slack-javascript-action/ # Shared JS source & build output +├── slack-message-action/ # General-purpose Slack messaging action +└── docs/ # Detailed documentation for each action +``` -on: - push: - branches: [ master ] +## License -jobs: - request_approval: - runs-on: ubuntu-latest - steps: - - name: Just a message - id: first_message - uses: Basis-Theory/github-actions/slack-message-action@master - with: - slack-api-token: ${{ secrets.API_TOKEN }} - channel: ${{ vars.CHANNEL }} - blocks: | - [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": ":rocket: Check it out" - } - } - ] - - name: Update a message - id: update_message - uses: Basis-Theory/github-actions/slack-message-action@master - with: - slack-api-token: ${{ secrets.API_TOKEN }} - channel: ${{ vars.CHANNEL }} - update-message-id: ${{ steps.first_message.outputs.message_id }} - blocks: | - [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": ":rocket: Check it out - updated" - } - } - ] - - name: Thread a message - id: thread_message - uses: Basis-Theory/github-actions/slack-message-action@master - with: - slack-api-token: ${{ secrets.API_TOKEN }} - channel: ${{ vars.CHANNEL }} - thread-message-id: ${{ steps.first_message.outputs.message_id }} - blocks: | - [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": ":threads: thead it out" - } - } - ] -``` +See [LICENSE](./LICENSE) for details. diff --git a/cache-cleanup/action.yml b/cache-cleanup/action.yml deleted file mode 100644 index b1a45b0..0000000 --- a/cache-cleanup/action.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Cleanup PR Caches -description: Deletes GitHub Actions caches scoped to a merged PR's branch and merge ref - -runs: - using: composite - steps: - - name: Cleanup merged PR branch caches - shell: bash - env: - GH_TOKEN: ${{ github.token }} - REPOSITORY: ${{ github.repository }} - COMMIT_SHA: ${{ github.sha }} - run: | - set -euo pipefail # fail fast on errors - - echo "Running as actor: $(gh api user --jq .login)" - echo "Token scopes check (should include actions:write):" - gh auth status || true - - PR_DATA=$(gh api --jq '.[0] | {number, branch: .head.ref}' \ - "/repos/${REPOSITORY}/commits/${COMMIT_SHA}/pulls") - - if [ -z "$PR_DATA" ] || [ "$PR_DATA" = "null" ]; then - echo "No PR found for commit ${COMMIT_SHA} → likely not a merge commit, skipping" - exit 0 - fi - - PR_NUMBER=$(echo "$PR_DATA" | jq -r '.number') - PR_BRANCH=$(echo "$PR_DATA" | jq -r '.branch') - echo "Cleaning caches for PR #${PR_NUMBER} (branch: ${PR_BRANCH})" - - for ref in "refs/pull/${PR_NUMBER}/merge" "refs/heads/${PR_BRANCH}"; do - echo "→ Ref: $ref" - caches=$(gh actions-cache list --repo "${REPOSITORY}" --branch "$ref" --limit 100 --json id,sizeInBytes,key 2>&1 || echo "[]") - - if [[ "$caches" == *"403"* || "$caches" == *"forbidden"* ]]; then - echo "ERROR: 403 on list → missing actions:write permission" - exit 1 - fi - - echo "$caches" | jq -r '.[] | "\(.id)\t\(.sizeInBytes)\t\(.key)"' | \ - while IFS=$'\t' read -r id size key; do - echo " Deleting: $key ($(( size / 1048576 )) MiB)" - gh actions-cache delete "$id" --repo "${REPOSITORY}" --confirm || echo "Delete failed (already gone?)" - done - done - - echo "Cleanup finished" \ No newline at end of file diff --git a/docs/deploy-slack-action/index.md b/docs/deploy-slack-action/index.md new file mode 100644 index 0000000..de3015f --- /dev/null +++ b/docs/deploy-slack-action/index.md @@ -0,0 +1,61 @@ +# deploy-slack-action + +A composite action that sends deployment lifecycle notifications to Slack. It wraps `helper-slack-action` and supports statuses: `start`, `done`, `request`, `success`, `cancelled`, `failure`. + +## How it works + +1. Resolves the job status from the `job-status` input or falls back to `job.status` +2. Delegates to `helper-slack-action` with the full GitHub context, Slack token, channel, and status + +## Inputs + +| Input | Required | Default | Description | +|---|---|---|---| +| `slack-api-token` | Yes | | Slack Bot API token | +| `channel` | Yes | | Slack channel ID to send the message to | +| `mention-person` | No | | Slack user to mention in the notification | +| `status` | No | `start` | Deploy status: `start`, `done`, `request`, `success`, `cancelled`, `failure` | +| `job-status` | No | | Overrides `job.status` for the final notification | + +## Usage + +### Basic deploy lifecycle + +```yaml +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Notify deploy start + uses: Basis-Theory/public-github-actions/deploy-slack-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: C01234ABCDE + status: start + + # ... deploy steps ... + + - name: Notify deploy done + if: always() + uses: Basis-Theory/public-github-actions/deploy-slack-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: C01234ABCDE + status: done +``` + +### With approval request and mention + +```yaml +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Request approval + uses: Basis-Theory/public-github-actions/deploy-slack-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: C01234ABCDE + status: request + mention-person: "@U01PT4W3RM5" +``` diff --git a/docs/draft-release-slack-action/index.md b/docs/draft-release-slack-action/index.md new file mode 100644 index 0000000..5c8319f --- /dev/null +++ b/docs/draft-release-slack-action/index.md @@ -0,0 +1,36 @@ +# draft-release-slack-action + +Sends a Slack notification when a draft release is created. It posts a message with the package name, version, contributing authors (mapped from GitHub usernames to Slack IDs), and a button linking to the release edit page. + +## How it works + +1. Captures the current job status +2. Delegates to `helper-slack-action` with `type: "draft-release-ready"` +3. The notification includes collaborator mentions resolved from the release notes' `@username` references + +## Inputs + +| Input | Required | Description | +|---|---|---| +| `slack-api-token` | Yes | Slack Bot API token | +| `channel` | Yes | Slack channel ID to send the message to | +| `mention-person` | No | Slack user to mention in the notification | + +## Usage + +```yaml +name: Draft Release Notification +on: + release: + types: [created] + +jobs: + notify: + if: github.event.release.draft + runs-on: ubuntu-latest + steps: + - uses: Basis-Theory/public-github-actions/draft-release-slack-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: C01234ABCDE +``` diff --git a/docs/helper-slack-action/index.md b/docs/helper-slack-action/index.md new file mode 100644 index 0000000..5c6e05b --- /dev/null +++ b/docs/helper-slack-action/index.md @@ -0,0 +1,67 @@ +# helper-slack-action + +The core Node.js-based Slack notification engine that powers both `deploy-slack-action` and `draft-release-slack-action`. It handles the full deploy notification lifecycle including approval flows, release notes threading, and status updates. + +## How it works + +The action routes to different behaviors based on the `type` and `status` inputs: + +- **`type: deploy` + `status: start`** — Posts a "Deploy Started" message with repo, version, author, and timestamps. Threads release notes beneath it. If an approval artifact exists, updates it. +- **`type: deploy` + `status: request`** — Posts an "Approval Requested" message mentioning the specified person, threads release notes, and uploads an artifact so the approval message can be updated later. +- **`type: deploy` + `status: done/success/failure/cancelled`** — Updates the original "Deploy Started" message (via `SLACK_MESSAGE_ID` env var) to reflect final status. On failure, threads a mention (either the deploy author's Slack ID or a user group fallback). On cancellation, marks the approval request as cancelled. +- **`type: draft-release-ready`** — Posts a draft release notification with collaborator mentions (GitHub-to-Slack user mapping). + +## Inputs + +| Input | Required | Default | Description | +|---|---|---|---| +| `slack-api-token` | Yes | | Slack Bot API token | +| `github` | Yes | | `${{ toJSON(github) }}` — the full GitHub context | +| `channel` | Yes | | Slack channel ID to send the message to | +| `mention-person` | No | | Slack user to mention for approvals | +| `status` | No | `start` | `start`, `done`, `request`, `success`, `failure`, `cancelled` | +| `type` | No | `deploy` | `deploy` or `draft-release-ready` | + +## Outputs + +| Output | Description | +|---|---| +| `message_id` | The Slack message timestamp ID of the sent message | + +## Usage + +### Deploy notification + +```yaml +- uses: Basis-Theory/public-github-actions/helper-slack-action@master + with: + github: ${{ toJSON(github) }} + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: C01234ABCDE + status: start +``` + +### Approval request with mention + +```yaml +- uses: Basis-Theory/public-github-actions/helper-slack-action@master + with: + github: ${{ toJSON(github) }} + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: C01234ABCDE + status: request + mention-person: "@U01PT4W3RM5" +``` + +### Draft release notification + +```yaml +- uses: Basis-Theory/public-github-actions/helper-slack-action@master + with: + github: ${{ toJSON(github) }} + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: C01234ABCDE + type: draft-release-ready +``` + +> **Note:** In most cases you should use `deploy-slack-action` or `draft-release-slack-action` instead of calling this action directly, as they handle passing the GitHub context automatically. diff --git a/docs/public-ip/index.md b/docs/public-ip/index.md new file mode 100644 index 0000000..127b200 --- /dev/null +++ b/docs/public-ip/index.md @@ -0,0 +1,55 @@ +# public-ip + +Retrieves the public IPv4 address of the GitHub Actions runner by calling `https://checkip.amazonaws.com`. Useful for temporarily allowlisting the runner's IP in firewalls or security groups before accessing protected resources. + +## Inputs + +This action has no inputs. + +## Outputs + +| Output | Description | +|---|---| +| `ipv4` | The public IPv4 address of the GitHub Actions runner | + +## Usage + +### Get runner IP and allowlist in AWS + +```yaml +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Get runner IP + id: runner-ip + uses: Basis-Theory/public-github-actions/public-ip@master + + - name: Allowlist IP in security group + run: | + aws ec2 authorize-security-group-ingress \ + --group-id sg-xxxxx \ + --protocol tcp --port 5432 \ + --cidr ${{ steps.runner-ip.outputs.ipv4 }}/32 + + # ... do work against the protected resource ... + + - name: Remove IP from security group + if: always() + run: | + aws ec2 revoke-security-group-ingress \ + --group-id sg-xxxxx \ + --protocol tcp --port 5432 \ + --cidr ${{ steps.runner-ip.outputs.ipv4 }}/32 +``` + +### Use the IP in other steps + +```yaml +- name: Get runner IP + id: runner-ip + uses: Basis-Theory/public-github-actions/public-ip@master + +- name: Print IP + run: echo "Runner IP is ${{ steps.runner-ip.outputs.ipv4 }}" +``` diff --git a/docs/slack-javascript-action/index.md b/docs/slack-javascript-action/index.md new file mode 100644 index 0000000..ddd2321 --- /dev/null +++ b/docs/slack-javascript-action/index.md @@ -0,0 +1,21 @@ +# slack-javascript-action + +The shared Node.js library that provides the Slack messaging and notification logic used by `helper-slack-action` and `slack-message-action`. This is **not intended to be consumed directly** as a GitHub Action — it serves as the build output referenced by other actions in this repository. + +## What it contains + +- **Slack API client** (`slack.client.ts`) — Send and update messages via `chat.postMessage` / `chat.update` +- **Block Kit builders** (`useBlocks.ts`) — Constructs Slack Block Kit payloads for deploy notifications, approval requests, release notes, and draft release announcements +- **Configuration** (`useConfig.ts`) — Parses the GitHub context and action inputs into a typed config object +- **Deploy helpers** (`deploy.helpers.ts`) — Deploy start/done notifications with status-aware headings and release note threading +- **Approval helpers** (`approval.helpers.ts`) — Approval request/response flow using GitHub Actions artifacts to persist message IDs across jobs +- **Draft release helpers** (`draft_release_ready.helpers.ts`) — Draft release notifications with GitHub-to-Slack username mapping + +## Build outputs + +- `dist/deploy/index.js` — Used by `helper-slack-action` +- `dist/slack/index.js` — Used by `slack-message-action` + +## GitHub-to-Slack user mapping + +The action maintains a mapping of GitHub usernames to Slack user IDs in `useConfig.ts` (for deploy author mentions) and `useBlocks.ts` (for draft release collaborator mentions). To add a new team member, update both mappings. diff --git a/docs/slack-message-action/index.md b/docs/slack-message-action/index.md new file mode 100644 index 0000000..ffe50f8 --- /dev/null +++ b/docs/slack-message-action/index.md @@ -0,0 +1,103 @@ +# slack-message-action + +A general-purpose Slack messaging action for sending, updating, or threading messages. Unlike the deploy-specific actions, this gives you full control over message content using Slack Block Kit or plain text. + +## How it works + +1. If `update-message-id` is provided, it updates the existing message with the new blocks/text +2. Otherwise, it sends a new message (optionally as a thread reply if `thread-message-id` is provided) +3. Returns the message ID (`ts`) as an output for chaining updates or threads + +## Inputs + +| Input | Required | Description | +|---|---|---| +| `slack-api-token` | Yes | Slack Bot API token | +| `channel` | Yes | Slack channel ID to send the message to | +| `blocks` | No | Slack Block Kit JSON payload | +| `text` | No | Plain text message content | +| `update-message-id` | No | Message ID to update (edits an existing message in place) | +| `thread-message-id` | No | Message ID to reply to (creates a threaded reply) | + +## Outputs + +| Output | Description | +|---|---| +| `message_id` | The Slack message timestamp ID of the sent/updated message | + +## Usage + +### Send a simple text message + +```yaml +- name: Send message + id: slack + uses: Basis-Theory/public-github-actions/slack-message-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: C01234ABCDE + text: "Build started for ${{ github.repository }}" +``` + +### Update an existing message + +```yaml +- name: Send initial message + id: slack + uses: Basis-Theory/public-github-actions/slack-message-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: C01234ABCDE + text: "Build in progress..." + +# ... build steps ... + +- name: Update message with result + if: always() + uses: Basis-Theory/public-github-actions/slack-message-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: C01234ABCDE + update-message-id: ${{ steps.slack.outputs.message_id }} + text: "Build finished: ${{ job.status }}" +``` + +### Thread a reply + +```yaml +- name: Send parent message + id: slack + uses: Basis-Theory/public-github-actions/slack-message-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: C01234ABCDE + text: "Deploy started" + +- name: Add details in thread + uses: Basis-Theory/public-github-actions/slack-message-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: C01234ABCDE + thread-message-id: ${{ steps.slack.outputs.message_id }} + text: "Deploying commit ${{ github.sha }}" +``` + +### Send Block Kit message + +```yaml +- name: Send blocks + uses: Basis-Theory/public-github-actions/slack-message-action@master + with: + slack-api-token: ${{ secrets.SLACK_API_TOKEN }} + channel: C01234ABCDE + blocks: | + [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "*Build Results*\nAll tests passed." + } + } + ] +```