Skip to content

Convert setup-github-actions-aws.sh to @claude-dev-toolkit npm command #2

@PaulDuvall

Description

@PaulDuvall

Convert Bash Script to @claude-dev-toolkit npm Command

Overview

Convert the setup-github-actions-aws.sh bash script into a new Node.js command within the existing @claude-dev-toolkit npm package for better cross-platform compatibility and integration.

Current Bash Script Analysis

The existing script (scripts/setup-github-actions-aws.sh) performs:

  • AWS CLI dependency validation
  • GitHub repository detection from git remotes
  • AWS account/region detection
  • OIDC provider creation/validation
  • IAM role creation with GitHub Actions trust policy
  • Broad deployment policy attachment
  • Security guidance output

User Experience Requirements

Current User Workflow (Bash Script)

# Prerequisites: AWS CLI, git, bash
chmod +x scripts/setup-github-actions-aws.sh
./scripts/setup-github-actions-aws.sh
# Manual copy/paste of secrets to GitHub

Proposed User Workflow (npm Command)

# Prerequisites: Node.js, npm, AWS credentials
npm install -g @paulduvall/claude-dev-toolkit
cd my-github-project
claude-commands aws-github-setup
# Optionally auto-configure GitHub variables if gh CLI available

Command Usage Patterns

Basic Setup (Auto-detect everything)

claude-commands aws-github-setup

What it does:

  • Detects GitHub repo from git remote
  • Uses AWS default region/credentials
  • Creates standard role name
  • Outputs GitHub variables to copy

Advanced Setup (Custom configuration)

claude-commands aws-github-setup \
  --role-name "my-custom-deployment-role" \
  --region "us-west-2" \
  --github-vars-auto \
  --policy-file "./custom-deployment-policy.json"

Development/Testing

# Preview what would be created
claude-commands aws-github-setup --dry-run

# Validate existing setup
claude-commands aws-github-setup --validate

# Update existing role with new policy
claude-commands aws-github-setup --update-existing

Integration with GitHub CLI

# Auto-configure GitHub repository variables
claude-commands aws-github-setup --gh-auto-vars

# Validate GitHub Actions workflow
claude-commands aws-github-setup --validate-workflow .github/workflows/deploy.yml

Implementation Plan

1. Add AWS Dependencies

{
  "dependencies": {
    "@aws-sdk/client-iam": "^3.0.0",
    "@aws-sdk/client-sts": "^3.0.0",
    "@aws-sdk/client-cloudformation": "^3.0.0",
    "simple-git": "^3.0.0",
    "chalk": "^5.0.0",
    "ora": "^6.0.0"
  }
}

2. Create New Command Module

File: lib/aws-github-setup-command.js
Pattern: Follow existing command structure (like setup-command.js)

class AWSGitHubSetupCommand {
  constructor() {
    this.iamClient = null;
    this.stsClient = null;
    this.git = null;
  }

  async execute(options) {
    // Main orchestration method
  }

  async validatePrerequisites() {
    // AWS credentials, git repo, permissions
  }

  async detectGitHubRepository() {
    // Parse git remotes for GitHub org/repo
  }

  async ensureOIDCProvider(githubThumbprint) {
    // Create or validate existing OIDC provider
  }

  async createOrUpdateRole(repoInfo, options) {
    // IAM role with GitHub trust policy
  }

  async validateDeploymentWorkflow(workflowPath) {
    // Validate GitHub Actions workflow syntax
  }

  async configureGitHubVariables(roleArn, region) {
    // Use gh CLI if available to set repository variables
  }
}

3. AWS SDK Integration

Replace bash AWS CLI calls:

  • STSClient.getCallerIdentity() → Replace aws sts get-caller-identity
  • IAMClient.listOpenIDConnectProviders() → Replace aws iam list-open-id-connect-providers
  • IAMClient.createOpenIDConnectProvider() → Replace provider creation
  • IAMClient.getRole() / IAMClient.createRole() → Replace role operations
  • IAMClient.putRolePolicy() / IAMClient.attachRolePolicy() → Replace policy ops

4. Enhanced GitHub Repository Detection

async detectGitHubRepository() {
  const git = require('simple-git');
  const repo = git();
  
  try {
    const remotes = await repo.getRemotes(true);
    const origin = remotes.find(r => r.name === 'origin');
    
    if (!origin) {
      throw new Error('No git origin remote found');
    }
    
    const url = origin.refs.fetch;
    const match = url.match(/github\.com[:/]([^/]+)\/([^/\.]+)/);
    
    if (!match) {
      throw new Error('Origin remote is not a GitHub repository');
    }
    
    return {
      org: match[1],
      repo: match[2],
      url: `https://github.com/${match[1]}/${match[2]}`
    };
  } catch (error) {
    throw new Error(`Failed to detect GitHub repository: ${error.message}`);
  }
}

5. CLI Command Integration

Add to bin/claude-commands:

program
  .command('aws-github-setup')
  .description('Setup AWS IAM role for GitHub Actions OIDC authentication')
  .option('--role-name <name>', 'IAM role name', 'github-actions-deployment-role')
  .option('--region <region>', 'AWS region (defaults to configured region)')
  .option('--policy-file <path>', 'Custom IAM policy JSON file')
  .option('--github-vars-auto', 'Automatically configure GitHub repository variables')
  .option('--validate', 'Validate existing setup without making changes')
  .option('--update-existing', 'Update existing role with new configuration')
  .option('--validate-workflow <path>', 'Validate GitHub Actions workflow file')
  .option('--dry-run', 'Preview actions without making changes')
  .option('--verbose', 'Show detailed progress information')
  .action(async (options) => {
    const AwsGitHubSetupCommand = require('../lib/aws-github-setup-command');
    const cmd = new AwsGitHubSetupCommand();
    try {
      const result = await cmd.execute(options);
      if (!result.success && !result.dryRun) {
        process.exit(1);
      }
    } catch (error) {
      console.error(`❌ AWS GitHub setup failed: ${error.message}`);
      process.exit(1);
    }
  });

6. Enhanced Output Formatting

Preserve and improve bash script UX:

const chalk = require('chalk');
const ora = require('ora');

class ProgressReporter {
  constructor() {
    this.spinner = null;
  }

  start(message) {
    this.spinner = ora(message).start();
  }

  success(message) {
    this.spinner.succeed(chalk.green(message));
  }

  error(message) {
    this.spinner.fail(chalk.red(message));
  }

  info(message) {
    console.log(chalk.blue('ℹ️ '), message);
  }

  section(title) {
    console.log(chalk.cyan.bold(`\n🔧 ${title}`));
    console.log(chalk.cyan('='.repeat(50)));
  }
}

7. Comprehensive Error Handling

class AWSGitHubSetupError extends Error {
  constructor(message, code, recoverySteps = []) {
    super(message);
    this.name = 'AWSGitHubSetupError';
    this.code = code;
    this.recoverySteps = recoverySteps;
  }
}

// Error scenarios and recovery steps
const ERROR_SCENARIOS = {
  NO_AWS_CREDENTIALS: {
    message: 'AWS credentials not found or invalid',
    recovery: [
      'Configure AWS credentials: aws configure',
      'Or set environment variables: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY',
      'Or use AWS profile: export AWS_PROFILE=your-profile'
    ]
  },
  INSUFFICIENT_PERMISSIONS: {
    message: 'Insufficient AWS IAM permissions',
    recovery: [
      'Ensure your AWS user/role has IAM permissions for:',
      '  • iam:CreateOpenIDConnectProvider',
      '  • iam:ListOpenIDConnectProviders',
      '  • iam:CreateRole',
      '  • iam:GetRole',
      '  • iam:PutRolePolicy',
      '  • sts:GetCallerIdentity'
    ]
  },
  NOT_GITHUB_REPO: {
    message: 'Current directory is not a GitHub repository',
    recovery: [
      'Navigate to a Git repository with GitHub remote',
      'Or initialize: git init && git remote add origin https://github.com/user/repo'
    ]
  }
};

8. Testing Integration

Create tests/test_aws_github_setup.js:

const AWSGitHubSetupCommand = require('../lib/aws-github-setup-command');
const { mockClient } = require('aws-sdk-client-mock');
const { IAMClient, STSClient } = require('@aws-sdk/client-iam');

describe('AWS GitHub Setup Command', () => {
  let command;
  let iamMock;
  let stsMock;

  beforeEach(() => {
    command = new AWSGitHubSetupCommand();
    iamMock = mockClient(IAMClient);
    stsMock = mockClient(STSClient);
  });

  test('should detect GitHub repository from git remote', async () => {
    // Mock git operations
    // Test repository detection logic
  });

  test('should create OIDC provider if not exists', async () => {
    // Mock AWS IAM operations
    // Verify OIDC provider creation
  });

  test('should handle permission errors gracefully', async () => {
    // Mock permission denied errors
    // Verify error messages and recovery steps
  });

  test('should validate GitHub Actions workflow', async () => {
    // Test workflow file validation
  });
});

Real-World Integration Examples

Example 1: New Project Setup

# Developer starts new project
git clone https://github.com/myorg/new-project
cd new-project

# Install toolkit
npm install -g @paulduvall/claude-dev-toolkit

# Setup AWS infrastructure
claude-commands aws-github-setup --github-vars-auto

# Workflow is ready - push triggers deployment
git push origin main

Example 2: Existing Project Migration

# Existing project with manual AWS setup
cd existing-project

# Validate current setup
claude-commands aws-github-setup --validate

# Update with new permissions
claude-commands aws-github-setup --update-existing --policy-file ./updated-policy.json

# Test the workflow
claude-commands aws-github-setup --validate-workflow .github/workflows/deploy.yml

Example 3: Multi-Environment Setup

# Setup different roles for different environments
claude-commands aws-github-setup --role-name "staging-deployment-role" --env staging
claude-commands aws-github-setup --role-name "prod-deployment-role" --env production

# Each environment gets different trust policies and permissions

Advanced Features

GitHub Actions Workflow Integration

# .github/workflows/deploy.yml
name: Deploy
on: 
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ vars.AWS_DEPLOYMENT_ROLE }}
          aws-region: ${{ vars.AWS_REGION }}
      - name: Deploy
        run: |
          # Your deployment commands

GitHub Variables Configuration

The command will set up Repository Variables instead of secrets for non-sensitive data:

Variables (Non-sensitive, visible in workflow logs)

  • AWS_DEPLOYMENT_ROLE - IAM Role ARN for deployment
  • AWS_REGION - AWS region for deployments
  • DEPLOYMENT_ENVIRONMENT - Environment name (staging/prod)

Secrets (Sensitive, encrypted)

Only used if additional sensitive configuration is needed:

  • Custom deployment keys
  • Third-party API keys
  • Database passwords

GitHub CLI Integration for Variables

async configureGitHubVariables(roleArn, region, repoInfo) {
  const { execSync } = require('child_process');
  
  try {
    // Set repository variables using gh CLI
    execSync(`gh variable set AWS_DEPLOYMENT_ROLE --body "${roleArn}"`, {
      cwd: process.cwd(),
      stdio: 'pipe'
    });
    
    execSync(`gh variable set AWS_REGION --body "${region}"`, {
      cwd: process.cwd(), 
      stdio: 'pipe'
    });
    
    console.log('✅ GitHub repository variables configured successfully');
    
    return {
      AWS_DEPLOYMENT_ROLE: roleArn,
      AWS_REGION: region
    };
  } catch (error) {
    console.log('⚠️  Could not auto-configure GitHub variables');
    console.log('📋 Manual setup required:');
    console.log(`   Variable Name: AWS_DEPLOYMENT_ROLE`);
    console.log(`   Variable Value: ${roleArn}`);
    console.log(`   Variable Name: AWS_REGION`);
    console.log(`   Variable Value: ${region}`);
    
    return null;
  }
}

Policy Template System

// Built-in policy templates
const POLICY_TEMPLATES = {
  'minimal': {
    // Least privilege for basic deployments
  },
  'serverless': {
    // Lambda, API Gateway, S3, CloudFormation
  },
  'container': {
    // ECS, ECR, ALB, CloudFormation
  },
  'full-stack': {
    // Complete web application stack
  }
};

// Usage
claude-commands aws-github-setup --policy-template serverless

Security Validation

async validateSecurityConfiguration() {
  const checks = [
    'Trust policy scoped to specific repository',
    'Role session duration appropriate (≤ 1 hour)',
    'No wildcard permissions on sensitive resources',
    'CloudTrail logging enabled for role usage'
  ];
  
  // Implement security checks
}

Prerequisites and Setup Requirements

System Requirements

  • Node.js: ≥16.0.0
  • NPM: Latest version
  • Git: For repository detection
  • GitHub CLI (optional): For automated variable configuration

AWS Requirements

  • Credentials: Configured via AWS CLI, environment variables, or IAM role
  • Permissions: IAM permissions for OIDC and role management
  • Region: Specified or default region configured

GitHub Requirements

  • Repository: Must be a GitHub repository with remote configured
  • Access: Repository admin access for variables configuration
  • GitHub CLI (optional): For automated variables configuration

Error Scenarios and Recovery

Common Issues and Solutions

1. AWS Credential Issues

❌ Error: AWS credentials not found
💡 Solutions:
   • Run: aws configure
   • Set: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
   • Use: AWS_PROFILE environment variable

2. Permission Issues

❌ Error: Access denied creating IAM role
💡 Solutions:
   • Ensure IAM user has required permissions
   • Use administrator access for initial setup
   • Check AWS CloudTrail for specific permission denials

3. Repository Detection Issues

❌ Error: Not a GitHub repository
💡 Solutions:
   • Ensure you're in a Git repository directory
   • Verify GitHub remote: git remote -v
   • Add GitHub remote: git remote add origin https://github.com/user/repo

4. Existing Resource Conflicts

❌ Error: Role already exists with different configuration
💡 Solutions:
   • Use: --update-existing flag to modify existing role
   • Use: --role-name to specify different name
   • Validate: --validate to check current configuration

5. GitHub Variables Configuration Issues

❌ Error: GitHub CLI not authenticated
💡 Solutions:
   • Run: gh auth login
   • Or manually set variables in GitHub repository settings
   • Navigate to: Settings > Actions > Variables

GitHub Variables vs Secrets Best Practices

Use Variables For:

Non-sensitive configuration (visible in workflow logs)

  • AWS Role ARNs (already public in CloudTrail)
  • AWS Regions
  • Environment names
  • Application configuration

Use Secrets For:

🔒 Sensitive data (encrypted, not visible in logs)

  • API keys and tokens
  • Database passwords
  • Private keys
  • OAuth client secrets

Security Benefits:

  • Reduced secret sprawl: Only truly sensitive data in secrets
  • Audit visibility: Variables visible in workflow logs for debugging
  • Principle of least privilege: Separate sensitive vs non-sensitive data
  • Easier troubleshooting: Variable values visible during workflow runs

Output Format with Variables Focus

🚀 AWS IAM Role Setup for GitHub Actions - SEC Parsing Agent
============================================================
📋 AWS Account: 123456789012
📋 Current User: arn:aws:iam::123456789012:user/developer
📋 Region: us-east-1
✅ Detected GitHub repository: myorg/my-repo

🔐 Ensuring GitHub OIDC provider exists...
✅ OIDC provider already exists: arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com

🔧 Ensuring deployment role: github-actions-deployment-role
✅ Created role: arn:aws:iam::123456789012:role/github-actions-deployment-role
✅ Inline policy applied.

============================================================
✅ Setup Complete!
============================================================
📋 GitHub Variables to add (Repository Settings > Actions > Variables):
   Variable Name: AWS_DEPLOYMENT_ROLE
   Variable Value: arn:aws:iam::123456789012:role/github-actions-deployment-role

   Variable Name: AWS_REGION
   Variable Value: us-east-1

🔗 Next Steps:
   1) Add the variables above to your GitHub repository
   2) Use variables in your workflow: ${{ vars.AWS_DEPLOYMENT_ROLE }}
   3) Trigger your deployment workflows

🔐 Security Notes:
   - Role is scoped to repo: myorg/my-repo
   - Variables are visible in workflow logs (non-sensitive data)
   - Policy is broad (*) for bootstrap; restrict later for least privilege
   - Sessions limited to 1 hour; actions logged in CloudTrail

Success Criteria

  • Functionality: All bash script features replicated
  • Cross-platform: Works on Windows/macOS/Linux
  • User Experience: Intuitive commands with helpful error messages
  • Integration: Seamless workflow with existing toolkit
  • Security: Maintains and improves security posture with proper variable/secret separation
  • Testing: Comprehensive test coverage
  • Documentation: Clear usage examples and troubleshooting
  • GitHub Actions: Validated workflow integration with variables
  • Error Handling: Actionable error messages with recovery steps
  • Performance: Fast execution with progress feedback
  • GitHub Variables: Proper separation of sensitive vs non-sensitive configuration

Implementation Timeline

  • Phase 1 (Week 1): Core AWS SDK integration and CLI structure
  • Phase 2 (Week 2): GitHub detection, error handling, and variable configuration
  • Phase 3 (Week 3): Testing suite, documentation, and workflow validation
  • Phase 4 (Week 4): Advanced features, security validation, and release

This implementation will transform a Unix-only bash script into a comprehensive, cross-platform development tool that integrates seamlessly with modern CI/CD workflows while following GitHub security best practices for variables vs secrets.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions