Skip to content

[Framework] 5 Critical Deployment Issues Requiring Framework Fixes #481

@seanspeaks

Description

@seanspeaks

Framework Deployment Issues: 5 Critical Fixes Needed

Summary: Multiple deployment issues discovered during frontify-frigg integration that require framework-level fixes. These issues force every Frigg user to implement CI/CD workarounds instead of being handled by the framework itself.

Priority Order

  1. Issue 3 (esbuild directories) - Blocks all CI/CD deployments ⚠️ CRITICAL
  2. Issue 5 (AWS discovery opt-out) - UX improvement for restrictive credentials
  3. Issue 2 (Prisma cleanup) - Blocks deployments randomly
  4. Issue 1 (osls dependency) - Easy one-line fix
  5. Issue 4 (plugin conflicts) - Cleanup task

Issue 1: osls Not Declared as frigg-cli Dependency

Problem

@friggframework/frigg-cli spawns osls (OSS Serverless) as a subprocess but doesn't declare it as a dependency.

Impact

  • Users must install osls globally: npm install -g osls
  • CI/CD workflows require extra installation step
  • Violates npm dependency management best practices
  • Error: spawn osls ENOENT

Evidence

// packages/frigg-cli/deploy-command/index.js
const command = 'osls';  // Subprocess call without dependency

// packages/frigg-cli/build-command/index.js
const command = 'osls';  // Same issue

Fix Required

// packages/frigg-cli/package.json
{
  "dependencies": {
    "osls": "^3.40.1"
  }
}

Current Workaround

# Every user's .github/workflows/deploy.yml
- name: Install osls globally
  run: npm install -g osls

Priority: Medium
Files: packages/frigg-cli/deploy-command/index.js, packages/frigg-cli/build-command/index.js, packages/frigg-cli/package.json


Issue 2: Prisma Layer Build Doesn't Clean Stale Artifacts

Problem

Prisma Lambda layer build script doesn't clean up stale artifacts, causing ENOTEMPTY errors when previous builds failed/interrupted.

Impact

  • Deployment fails: ENOTEMPTY: directory not empty
  • Corrupt layer directories block subsequent deployments
  • Requires manual cleanup
  • Cryptic error messages confuse users

Evidence

npm error syscall rmdir
npm error path /backend/layers/prisma/nodejs/node_modules/@prisma/client/runtime
npm error errno -39
npm error ENOTEMPTY: directory not empty, rmdir '...'

Root Cause

buildPrismaLayer() creates directories but never cleans existing ones before starting.

Fix Required (Recommended)

// packages/devtools/infrastructure/scripts/build-prisma-layer.js
async function buildPrismaLayer(config) {
    const { layerPath, targetEnv } = config;

    // Add cleanup at the beginning
    if (fs.existsSync(layerPath)) {
        console.log(`Cleaning existing layer directory: ${layerPath}`);
        await fs.rm(layerPath, { recursive: true, force: true });
    }

    // ... rest of build logic
}

Additional Improvements

  1. Add retry logic for npm install failures
  2. Better error messages explaining the issue
  3. Add --clean flag to frigg deploy command
  4. Implement proper rollback on build failure

Current Workaround

# Every user's .github/workflows/deploy.yml
- name: Clean Prisma layer directory
  run: rm -rf layers/prisma

Priority: High
Files: packages/devtools/infrastructure/scripts/build-prisma-layer.js, packages/devtools/infrastructure/domains/shared/utilities/prisma-layer-manager.js


Issue 3: serverless-esbuild Missing .serverless Directory ⚠️ CRITICAL

Problem

serverless-esbuild expects .esbuild/.serverless directory to exist, but Frigg doesn't create it.

IMPORTANT: Since Frigg's infrastructure builder adds serverless-esbuild to the plugins list, Frigg should handle creating the required directories. This is Frigg's responsibility, not the user's.

Impact

  • Deployment fails: ENOENT: no such file or directory, lstat '.esbuild/.serverless'
  • Blocks ALL CI/CD deployments
  • Not reproducible locally (directory persists after first run)
  • Forces every Frigg user to add workarounds

Evidence

Error: ENOENT: no such file or directory, lstat '/home/runner/work/frigg-integrations/frigg-integrations/backend/.esbuild/.serverless'
× Stack create-frigg-app-production failed to deploy (128s)

Root Cause

  1. Frigg infrastructure builder adds serverless-esbuild to plugins
  2. Plugin expects .esbuild/.serverless directory for build artifacts
  3. Frigg adds the plugin but doesn't handle its requirements ← Core issue
  4. CI/CD environments start clean, directory never exists

Fix Required (BEST Option)

// packages/devtools/serverless-plugin/index.js
class FriggServerlessPlugin {
    constructor(serverless, options) {
        this.serverless = serverless;
        this.options = options;

        this.hooks = {
            'before:package:initialize': this.ensureBuildDirectories.bind(this),
        };
    }

    async ensureBuildDirectories() {
        const fs = require('fs').promises;

        const buildDirs = ['.esbuild', '.esbuild/.serverless'];

        for (const dir of buildDirs) {
            await fs.mkdir(dir, { recursive: true });
        }

        this.serverless.cli.log('✓ Created build directories for serverless-esbuild');
    }
}

Why this is best:

  • Frigg serverless plugin already runs during deployment
  • Hooks into before:package:initialize lifecycle event
  • Centralized location for Frigg-specific setup
  • Won't run if serverless-esbuild isn't in plugins
  • Follows separation of concerns

Alternative Options

  • Option 2: Add to packages/frigg-cli/deploy-command/index.js before spawning osls
  • Option 3: Add to packages/devtools/infrastructure/infrastructure-composer.js

Current Workaround

# Every user's .github/workflows/deploy.yml
- name: Create esbuild directories
  run: mkdir -p .esbuild/.serverless

Priority: CRITICAL
Files: packages/devtools/serverless-plugin/index.js, packages/devtools/infrastructure/domains/shared/utilities/base-definition-factory.js


Issue 4: Conflicting Serverless Plugins (serverless-esbuild vs serverless-jetpack)

Problem

Frigg infrastructure builder adds serverless-esbuild, but legacy apps have serverless-jetpack. Both handle packaging and may conflict.

Impact

  • Unclear which plugin packages Lambda functions
  • Potential configuration conflicts
  • Unnecessary dependencies and build time
  • No migration guide

Evidence

// User's backend/package.json
{
  "devDependencies": {
    "serverless-esbuild": "^1.55.1",  // Added by Frigg
    "serverless-jetpack": "0.11.2"     // Legacy
  }
}

Fix Required (Recommended)

Choose serverless-esbuild and provide migration path:

  1. Update infrastructure builder to check for existing plugins
  2. Warn if both are present
  3. Document migration from jetpack to esbuild
  4. Update create-frigg-app templates

Alternative: Smart detection:

// base-definition-factory.js
function getPackagingPlugin(packageJson) {
    const hasJetpack = packageJson.devDependencies?.['serverless-jetpack'];
    const hasEsbuild = packageJson.devDependencies?.['serverless-esbuild'];

    if (hasJetpack && hasEsbuild) {
        console.warn('Both plugins found. Using serverless-esbuild.');
    }

    return hasEsbuild ? 'serverless-esbuild' :
           hasJetpack ? 'serverless-jetpack' :
           'serverless-esbuild'; // default
}

Recommendation: serverless-esbuild

  • More modern
  • Better TypeScript support
  • Faster builds
  • Active development

Priority: Medium
Files: packages/devtools/infrastructure/domains/shared/utilities/base-definition-factory.js


Issue 5: AWS Discovery Failures Don't Block Deployment (Silent Failures)

Problem

AWS resource discovery fails silently when IAM credentials lack permissions. No way to explicitly opt-out for restrictive deployment credentials.

Impact

  • Users see discovery errors but deployment continues
  • Unclear if deployment will work without discovered resources
  • No explicit discovery toggle
  • Forces users to grant broad permissions or deal with confusing errors

Evidence

Error discovering AWS resources: User: arn:aws:iam::123456789012:user/github-deploy
is not authorized to perform: ec2:DescribeVpcs on resource: arn:aws:ec2:eu-central-1:123456789012:vpc/*

Warning: AWS discovery failed, continuing with deployment...

Root Cause

From packages/devtools/infrastructure/CLAUDE.md:

const shouldRunDiscovery = (AppDefinition) => {
    return (
        AppDefinition.vpc?.enable === true ||
        AppDefinition.encryption?.useDefaultKMSForFieldLevelEncryption === true ||
        AppDefinition.ssm?.enable === true
    );
};

Discovery runs automatically but:

  1. No way to disable it
  2. Failures logged as warnings, deployment continues
  3. No validation that required permissions exist
  4. No manual override option

Fix Required (Recommended)

// AppDefinition schema - add discovery toggle
const appDefinition = {
    aws: {
        discovery: {
            enabled: true,              // Explicit opt-in/opt-out
            failOnError: false,         // Fail deployment if discovery fails
            requiredResources: []       // Specify what must be discovered
        }
    },
    vpc: {
        enable: true,
        vpcId: 'vpc-12345',            // Manual override if discovery disabled
        subnetIds: ['subnet-1', 'subnet-2'],
        securityGroupIds: ['sg-123']
    }
};
// packages/devtools/infrastructure/aws-discovery.js - improve error handling
async function discoverResources(appDefinition) {
    if (appDefinition.aws?.discovery?.enabled === false) {
        console.log('ℹ️  AWS discovery disabled, using manual configuration');
        return null;
    }

    try {
        const resources = await performDiscovery();
        return resources;
    } catch (error) {
        const message = `
❌ AWS Discovery Failed

The deployment credential doesn't have permissions for resource discovery.

Options:
1. Grant additional IAM permissions (see docs/IAM-POLICY-TEMPLATES.md)
2. Disable discovery and provide resources manually:

   aws: { discovery: { enabled: false } }
   vpc: { vpcId: 'vpc-xxx', subnetIds: [...] }

3. Continue without VPC/KMS features

Error: ${error.message}
        `;

        if (appDefinition.aws?.discovery?.failOnError === true) {
            throw new Error(message);
        } else {
            console.warn(message);
            return null;
        }
    }
}

Additional Improvements

  1. Add --skip-discovery flag to frigg deploy command
  2. Validate manual configuration when discovery disabled
  3. Document minimal IAM policy (deployment-only, no discovery)
  4. Add IAM permission checker before running discovery
  5. Better error messages per discovery step

Required IAM Permissions

Minimal (deployment-only):

  • cloudformation:*
  • lambda:*
  • apigateway:*
  • iam:CreateRole, iam:AttachRolePolicy
  • logs:CreateLogGroup, logs:PutRetentionPolicy

Optional (for discovery):

  • ec2:DescribeVpcs, ec2:DescribeSubnets, ec2:DescribeSecurityGroups
  • kms:ListKeys, kms:DescribeKey, kms:ListAliases
  • ssm:GetParameter, ssm:PutParameter

Priority: Medium
Files: packages/devtools/infrastructure/aws-discovery.js, packages/devtools/infrastructure/build-time-discovery.js


Summary

All 5 issues force users to implement workarounds in their CI/CD pipelines. These should be fixed in the framework.

Why This Matters

  • Every Frigg user encounters these issues
  • Workarounds are duplicated across all projects
  • Poor developer experience
  • Violates framework's "spin up integrations in minutes" promise

Recommended Implementation Order

  1. Issue 3 - Highest impact, quick serverless plugin fix
  2. Issue 5 - UX improvement, quick config addition
  3. Issue 2 - Random failures, moderate effort
  4. Issue 1 - One-line package.json fix
  5. Issue 4 - Cleanup task, document migration

Files Affected

  • packages/frigg-cli/package.json
  • packages/frigg-cli/deploy-command/index.js
  • packages/devtools/serverless-plugin/index.js
  • packages/devtools/infrastructure/scripts/build-prisma-layer.js
  • packages/devtools/infrastructure/aws-discovery.js
  • packages/devtools/infrastructure/build-time-discovery.js
  • packages/devtools/infrastructure/domains/shared/utilities/base-definition-factory.js

Metadata

Metadata

Assignees

No one assigned

    Labels

    prereleaseThis change is available in a prerelease.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions