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
21 changes: 21 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
},
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
],
rules: {
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-non-null-assertion': 'warn',
},
env: {
node: true,
es6: true,
},
};
104 changes: 89 additions & 15 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,21 +1,95 @@
.gradle
/build/
/plugin/build
# Dependencies
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Ignore Gradle GUI config
gradle-app.setting
# Build outputs
dist/
build/
*.tsbuildinfo

# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Cache of project
.gradletasknamecache
# Coverage directory used by tools like istanbul
coverage/
*.lcov

# Intellij Files
.idea
# nyc test coverage
.nyc_output

# MacOs?
.DS_Store
# Dependency directories
node_modules/
jspm_packages/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test
.env.production
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# next.js build output
.next

# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
# gradle/wrapper/gradle-wrapper.properties
# nuxt.js build output
.nuxt

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
8 changes: 8 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"useTabs": false
}
79 changes: 40 additions & 39 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,65 +4,66 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Project Overview

This is a Kotlin Multiplatform CLI application for sending Slack notifications, primarily used in GitHub workflows. The project compiles to native executables for different platforms (macOS ARM64, Linux x64/ARM64, Windows x64) using Kotlin/Native.
This is a TypeScript GitHub Action for sending Slack notifications from GitHub workflows. The action provides rich formatting and supports creating new messages or updating existing ones to track workflow progress.

## Key Commands

### Building and Development
- `./gradlew build` - Full build including compilation and tests
- `./gradlew commonBinaries` - Build native executables (default task)
- `./gradlew linkReleaseExecutableCommon` - Build release executable
- `./gradlew linkDebugExecutableCommon` - Build debug executable

### Running
- `./gradlew runDebugExecutableCommon` - Run debug executable
- `./gradlew runReleaseExecutableCommon` - Run release executable

### Testing
- `./gradlew commonTest` - Run tests for common target
- `./gradlew allTests` - Run all tests with aggregated report
- `npm install` - Install dependencies
- `npm run build` - Build the action (TypeScript compilation + bundling)
- `npm test` - Run tests
- `npm run lint` - Run ESLint
- `npm run format` - Format code with Prettier

### Code Quality
- `./gradlew ktlintCheck` - Run linting
- `./gradlew ktlintFormat` - Auto-format code
- `./gradlew check` - Run all checks (tests + linting)
- `npm run lint` - Run linting with ESLint
- `npm run format` - Auto-format code with Prettier

## Architecture

### Main Components
- **Main.kt**: Entry point that delegates to PublishSlackCommand
- **PublishSlackCommand**: CLI command parser using Clikt library, handles GitHub Action environment variables
- **PublishSlackService**: Orchestrates the Slack publishing workflow
- **SlackClient**: Handles Slack API interactions (create/update messages)
- **src/index.ts**: Entry point that processes GitHub Action inputs and coordinates the workflow
- **src/services/publish-slack-service.ts**: Orchestrates the Slack publishing workflow
- **src/services/slack-client.ts**: Handles Slack API interactions using @slack/web-api
- **src/utils/github-event-parser.ts**: Parses GitHub event JSON files from various webhook formats
- **src/models/types.ts**: TypeScript types and enums for the application

### Key Models
- **GithubEvent**: Unified GitHub event data from various GitHub webhook payloads
- **JobType/JobStatus**: Enums for workflow job classification
- **SlackMessage/SlackBlock**: Slack message structure for rich formatting
- **GitHubEvent**: Unified GitHub event data from various GitHub webhook payloads
- **JobType/JobStatus**: Enums for workflow job classification with associated labels and colors
- **SlackMessage/SlackBlock/SlackAttachment**: Slack message structure for rich formatting

### Data Flow
1. GitHub Action provides environment variables and event JSON file
2. PublishSlackCommand parses CLI options and GitHub event data
3. Event JSON is normalized into GithubEvent via serializers in `model/serializers/`
4. PublishSlackService coordinates message creation/update via SlackClient
5. Output includes SLACK_MESSAGE_ID for subsequent workflow steps
1. GitHub Action inputs are processed from action.yml metadata
2. GitHub event JSON file is parsed and normalized into GitHubEvent
3. PublishSlackService coordinates message creation/update via SlackClient
4. Output includes SLACK_MESSAGE_ID for subsequent workflow steps

### Dependencies
- **Clikt**: CLI argument parsing
- **Ktor**: HTTP client for Slack API calls
- **kotlinx-serialization**: JSON parsing for GitHub events
- **kotlinx-datetime**: Date/time handling
- **Kotest**: Testing framework
- **@actions/core**: GitHub Actions toolkit for inputs/outputs
- **@actions/github**: GitHub Actions context utilities
- **@slack/web-api**: Official Slack Web API client
- **TypeScript**: Language and type system
- **@vercel/ncc**: Bundler for packaging the action

## Development Notes

### Platform Targeting
The project uses cross-compilation with a single "common" target that maps to the host platform. The native target selection happens at build time based on OS detection.
### GitHub Action Structure
The project follows GitHub Action conventions:
- `action.yml`: Metadata defining inputs, outputs, and runtime
- `dist/index.js`: Bundled JavaScript entry point (auto-generated)
- Inputs can come from workflow YAML or environment variables

### GitHub Integration
The CLI is designed to run in GitHub Actions and expects specific environment variables (GITHUB_EVENT_PATH, GITHUB_REPOSITORY, etc.). Event parsing handles multiple GitHub webhook formats through dedicated serializers.
The action processes GitHub event JSON files and environment variables:
- GITHUB_EVENT_PATH, GITHUB_REPOSITORY, GITHUB_RUN_ID, etc.
- Supports multiple GitHub webhook formats (push, pull_request, issues)
- Outputs SLACK_MESSAGE_ID for workflow chaining

### Build Process
The action is bundled using @vercel/ncc to create a single JavaScript file with all dependencies included. This eliminates the need for node_modules in the distributed action.

### Usage Context
This tool is typically used indirectly through:
1. [slack-notifier-cli-action](https://github.com/monta-app/slack-notifier-cli-action) - GitHub Action wrapper
2. [github-workflows](https://github.com/monta-app/github-workflows) - Shared workflow templates
This action can be used:
1. Directly in GitHub workflows
2. Indirectly through [github-workflows](https://github.com/monta-app/github-workflows) - Shared workflow templates
58 changes: 56 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,63 @@
### About

A CLI project for sending slack messages usable in GitHub workflows.
A TypeScript GitHub Action for sending Slack notifications from GitHub workflows with rich formatting.

### Usage

Typically you do not use this directly but via the [slack-notifier-cli-action](https://github.com/monta-app/slack-notifier-cli-action)
You can use this action directly in your GitHub workflows:

```yaml
- name: Send Slack Notification
uses: monta-app/slack-notifier-cli@v1
with:
job-type: 'build'
job-status: 'success'
slack-token: ${{ secrets.SLACK_BOT_TOKEN }}
slack-channel-id: 'C1234567890'
service-name: 'My Service'
service-emoji: ':rocket:'
```

### Inputs

| Input | Description | Required | Default |
|-------|-------------|----------|---------|
| `github-event-path` | GitHub event JSON file path | No | `${{ github.event_path }}` |
| `github-repository` | GitHub repository name | No | `${{ github.repository }}` |
| `github-run-id` | GitHub run ID | No | `${{ github.run_id }}` |
| `github-workflow` | GitHub workflow name | No | `${{ github.workflow }}` |
| `github-ref-name` | GitHub ref name | No | `${{ github.ref_name }}` |
| `service-name` | Service name for display | No | |
| `service-emoji` | Service emoji | No | |
| `job-type` | Job type (build, test, deploy, etc.) | Yes | |
| `job-status` | Job status (success, failure, progress, etc.) | Yes | |
| `slack-token` | Slack Bot Token | Yes | |
| `slack-channel-id` | Slack channel ID | Yes | |
| `slack-message-id` | Message ID to update (for updates) | No | |

### Outputs

| Output | Description |
|--------|-------------|
| `slack-message-id` | ID of the created/updated Slack message |

### Development

```bash
# Install dependencies
npm install

# Build the action
npm run build

# Run tests
npm test

# Lint code
npm run lint

# Format code
npm run format
```

Most projects don't use this directly, but indirectly through the [github-workflows](https://github.com/monta-app/github-workflows)
58 changes: 58 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: 'Slack Notifier CLI'
description: 'Send Slack notifications from GitHub workflows with rich formatting'
author: 'Monta'

inputs:
github-event-path:
description: 'GitHub Context event json file path'
required: false
default: ${{ github.event_path }}
github-repository:
description: 'GitHub Context repository'
required: false
default: ${{ github.repository }}
github-run-id:
description: 'GitHub Context run id'
required: false
default: ${{ github.run_id }}
github-workflow:
description: 'GitHub Context workflow'
required: false
default: ${{ github.workflow }}
github-ref-name:
description: 'GitHub Context ref name'
required: false
default: ${{ github.ref_name }}
service-name:
description: 'Name of the service for display in Slack'
required: false
service-emoji:
description: 'Emoji for the service'
required: false
job-type:
description: 'Job Type (e.g., build, test, deploy)'
required: true
job-status:
description: 'Job Status (e.g., success, failure, in_progress)'
required: true
slack-token:
description: 'Slack Bot Token (xoxb-...)'
required: true
slack-channel-id:
description: 'Slack channel ID where messages will be posted'
required: true
slack-message-id:
description: 'Slack message ID to update (for updating existing messages)'
required: false

outputs:
slack-message-id:
description: 'The ID of the Slack message that was created or updated'

runs:
using: 'node20'
main: 'dist/index.js'

branding:
icon: 'message-circle'
color: 'blue'
Loading
Loading