@firebreak/lookout
v1.0.0
Published
TypeScript client for Lookout deployment notifications
Maintainers
Readme
Lookout
TypeScript/JavaScript client for sending deployment notifications to Lookout with smart step tracking and automatic timing.
Features
- 🚀 Simple API - Start tracking deployments in just a few lines of code
- ⏱️ Automatic Timing - SDK automatically tracks step duration
- 🔄 Auto Retry - Built-in retry logic with exponential backoff
- 📝 TypeScript - Full type definitions for excellent IDE support
- ✅ Validation - Input validation prevents bad API calls
- 🎯 Smart State Management - Tracks deployment and step state automatically
Installation
npm install @firebreak/lookoutQuick Start
import { LookoutClient } from '@firebreak/lookout';
// Create client
const client = new LookoutClient({
webhookUrl: process.env.LOOKOUT_WEBHOOK_URL,
apiToken: process.env.LOOKOUT_API_TOKEN,
teamId: process.env.SLACK_TEAM_ID,
});
// Start deployment
const deployment = await client.startDeployment({
deploymentId: 'deploy-123',
version: 'v1.2.0',
environment: 'production',
steps: ['Build', 'Test', 'Deploy'],
});
// Run steps with automatic timing
await deployment.runStep('Build', async () => {
// Your build logic here
});
await deployment.runStep('Test', async () => {
// Your test logic here
});
await deployment.runStep('Deploy', async () => {
// Your deploy logic here
});
// Mark deployment as successful
await deployment.success();GitHub Actions Integration
Step 1: Add Secrets
Add these secrets to your GitHub repository:
LOOKOUT_WEBHOOK_URL- Your Lookout webhook URLLOOKOUT_API_TOKEN- Your Lookout API tokenSLACK_TEAM_ID- Your Slack workspace IDSLACK_RELEASE_MANAGER_ID- Slack user ID for release manager
Step 2: Create Deployment Script
Create deploy-with-lookout.js:
const { LookoutClient } = require('@firebreak/lookout');
async function deploy() {
const client = new LookoutClient({
webhookUrl: process.env.LOOKOUT_WEBHOOK_URL,
apiToken: process.env.LOOKOUT_API_TOKEN,
teamId: process.env.SLACK_TEAM_ID,
});
const deployment = await client.startDeployment({
deploymentId: `${process.env.GITHUB_RUN_ID}-${process.env.GITHUB_RUN_NUMBER}`,
version: process.env.GITHUB_REF_NAME || 'unknown',
environment: 'production',
releaseManager: process.env.SLACK_RELEASE_MANAGER_ID,
steps: ['Build', 'Test', 'Deploy', 'Verify'],
});
try {
await deployment.runStep('Build', async () => {
// Build commands
console.log('Building...');
});
await deployment.runStep('Test', async () => {
// Test commands
console.log('Testing...');
});
await deployment.runStep('Deploy', async () => {
// Deploy commands
console.log('Deploying...');
});
await deployment.runStep('Verify', async () => {
// Verification commands
console.log('Verifying...');
});
await deployment.success();
} catch (error) {
await deployment.fail(error.message);
throw error;
}
}
deploy();Step 3: Update GitHub Actions Workflow
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: npm install @firebreak/lookout
- name: Deploy with Lookout notifications
run: node deploy-with-lookout.js
env:
LOOKOUT_WEBHOOK_URL: ${{ secrets.LOOKOUT_WEBHOOK_URL }}
LOOKOUT_API_TOKEN: ${{ secrets.LOOKOUT_API_TOKEN }}
SLACK_TEAM_ID: ${{ secrets.SLACK_TEAM_ID }}
SLACK_RELEASE_MANAGER_ID: ${{ secrets.SLACK_RELEASE_MANAGER_ID }}API Reference
LookoutClient
Main entry point for the SDK.
Constructor
new LookoutClient(config: LookoutConfig)Config Options:
webhookUrl(required) - Lookout webhook URLapiToken(required) - API authentication tokenteamId(required) - Slack team/workspace IDretry(optional) - Retry configurationmaxAttempts- Max retry attempts (default: 3)initialDelay- Initial delay in ms (default: 1000)maxDelay- Max delay in ms (default: 10000)backoff- 'linear' or 'exponential' (default: 'exponential')
timeout(optional) - Request timeout in ms (default: 30000)defaultEnvironment(optional) - Default environment namedefaultVersion(optional) - Default version string
Methods
startDeployment(options: DeploymentOptions): Promise
Create and start a deployment, sending initial notification.
const deployment = await client.startDeployment({
deploymentId: 'deploy-123',
version: 'v1.0.0',
environment: 'production',
releaseManager: 'U123456',
releaseNotes: '## Changes\n- Bug fixes',
steps: ['Build', 'Test', 'Deploy'],
});createDeployment(options: DeploymentOptions): DeploymentTracker
Create deployment tracker without sending initial notification.
DeploymentTracker
Manages individual deployment lifecycle.
Methods
runStep(name: string, fn: () => Promise): Promise
Run a step with automatic timing and error handling.
await deployment.runStep('Build', async () => {
// Build logic
});startStep(name: string): Promise
Manually start a step.
await deployment.startStep('Build');completeStep(name: string): Promise
Manually complete a step.
await deployment.completeStep('Build');failStep(name: string, error?: string): Promise
Mark a step as failed.
await deployment.failStep('Build', 'Compilation failed');success(): Promise
Mark deployment as successful.
await deployment.success();fail(error?: string): Promise
Mark deployment as failed.
await deployment.fail('Deployment timed out');update(): Promise
Manually send current state to Lookout.
await deployment.update();getState(): DeploymentState
Get current deployment state (read-only).
getDeploymentId(): string
Get deployment ID.
getStatus(): DeploymentStatus
Get current deployment status.
isComplete(): boolean
Check if deployment is complete (success or failed).
Error Handling
The SDK provides typed errors for different failure scenarios:
import { LookoutClient, ApiError, ValidationError, LookoutError } from '@firebreak/lookout';
try {
await deployment.success();
} catch (error) {
if (error instanceof ApiError) {
if (error.is('UNAUTHORIZED')) {
console.error('Invalid API token');
} else if (error.is('NOT_FOUND')) {
console.error('Team not configured');
} else if (error.statusCode >= 500) {
console.error('Server error - retrying...');
}
} else if (error instanceof ValidationError) {
console.error('Invalid input:', error.message);
console.error('Field:', error.field);
} else if (error instanceof LookoutError) {
console.error('SDK error:', error.code, error.message);
}
}Advanced Usage
Manual Step Control
const deployment = client.createDeployment({
deploymentId: 'deploy-123',
version: 'v1.0.0',
steps: [
{ name: 'Build', status: 'pending' },
{ name: 'Test', status: 'pending' },
{ name: 'Deploy', status: 'pending' },
],
});
// Send initial notification
await deployment.update();
// Manual control
await deployment.startStep('Build');
// ... build logic ...
await deployment.completeStep('Build');
await deployment.startStep('Test');
// ... if test fails ...
await deployment.failStep('Test', 'Tests failed');
await deployment.fail('Deployment aborted due to test failures');Custom Retry Configuration
const client = new LookoutClient({
webhookUrl: process.env.LOOKOUT_WEBHOOK_URL,
apiToken: process.env.LOOKOUT_API_TOKEN,
teamId: process.env.SLACK_TEAM_ID,
retry: {
maxAttempts: 5,
initialDelay: 2000,
maxDelay: 30000,
backoff: 'exponential',
},
timeout: 60000, // 60 seconds
});TypeScript Support
The SDK is written in TypeScript and provides full type definitions:
import type {
LookoutConfig,
DeploymentOptions,
DeploymentStatus,
StepStatus,
DeploymentState,
} from '@firebreak/lookout';
const options: DeploymentOptions = {
deploymentId: 'deploy-123',
version: 'v1.0.0',
environment: 'production',
status: 'in_progress', // Type-safe
steps: ['Build', 'Test', 'Deploy'],
};Examples
See the examples/ directory for more usage examples:
- basic-usage.ts - Simple deployment tracking
- github-actions.ts - GitHub Actions integration
- error-handling.ts - Error handling patterns
License
MIT
Support
For issues and questions, please open an issue.
