All files / apps/gha Gha.ts

100% Statements 31/31
88.88% Branches 16/18
100% Functions 3/3
100% Lines 31/31

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97                                          11x 11x 11x 11x   11x                               7x       7x 7x       11x     11x   11x 11x   11x           11x 11x 11x 11x   1x 1x 1x     10x   10x 3x         7x 7x 7x   7x   7x   3x 3x 3x      
import 'reflect-metadata';
import type { Container } from 'inversify';
import { DispatchActionCommand } from '../../envilder/application/dispatch/DispatchActionCommand.js';
import type { DispatchActionCommandHandler } from '../../envilder/application/dispatch/DispatchActionCommandHandler.js';
import type { CliOptions } from '../../envilder/domain/CliOptions.js';
import type { MapFileConfig } from '../../envilder/domain/MapFileConfig.js';
import type { ILogger } from '../../envilder/domain/ports/ILogger.js';
import { ConsoleLogger } from '../../envilder/infrastructure/logger/ConsoleLogger.js';
import { readMapFileConfig } from '../../envilder/infrastructure/variableStore/FileVariableStore.js';
import { TYPES } from '../../envilder/types.js';
import { Startup } from './Startup.js';
 
/**
 * Reads GitHub Actions inputs from environment variables.
 * GitHub Actions passes inputs as INPUT_<NAME> environment variables.
 */
function readInputs(): {
  options: CliOptions;
  provider?: string;
  vaultUrl?: string;
} {
  const mapFile = process.env.INPUT_MAP_FILE;
  const envFile = process.env.INPUT_ENV_FILE;
  const provider = process.env.INPUT_PROVIDER;
  const vaultUrl = process.env.INPUT_VAULT_URL;
 
  return {
    options: {
      map: mapFile,
      envfile: envFile,
      // GitHub Action only supports pull mode
      push: false,
    },
    provider: provider || undefined,
    vaultUrl: vaultUrl || undefined,
  };
}
 
async function executeCommand(
  serviceProvider: Container,
  options: CliOptions,
): Promise<void> {
  const commandHandler = serviceProvider.get<DispatchActionCommandHandler>(
    TYPES.DispatchActionCommandHandler,
  );
 
  const command = DispatchActionCommand.fromCliOptions(options);
  await commandHandler.handleCommand(command);
}
 
export async function main() {
  const { options, provider, vaultUrl } = readInputs();
 
  let serviceProvider: Container;
  let logger: ILogger = new ConsoleLogger();
 
  try {
    const fileConfig = options.map ? await readMapFileConfig(options.map) : {};
 
    const config: MapFileConfig = {
      ...fileConfig,
      ...(provider && { provider }),
      ...(vaultUrl && { vaultUrl }),
    };
 
    const startup = Startup.build();
    startup.configureServices().configureInfrastructure(config);
    serviceProvider = startup.create();
    logger = serviceProvider.get<ILogger>(TYPES.ILogger);
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    logger.error(`🚨 Failed to initialize: ${message}`);
    throw error;
  }
 
  try {
    // Validate required inputs
    if (!options.map || !options.envfile) {
      throw new Error(
        '🚨 Missing required inputs! Please provide map-file and env-file.',
      );
    }
 
    logger.info('🔑 Envilder GitHub Action - Starting secret pull...');
    logger.info(`📋 Map file: ${options.map}`);
    logger.info(`📄 Env file: ${options.envfile}`);
 
    await executeCommand(serviceProvider, options);
 
    logger.info('✅ Secrets pulled successfully!');
  } catch (error) {
    logger.error('🚨 Uh-oh! Looks like Mario fell into the wrong pipe! 🍄💥');
    logger.error(error instanceof Error ? error.message : String(error));
    throw error;
  }
}