Versioned & Local Deps for E2E Preview Envs (#933)

* initial

* update deploy

* test

* fix

* fix artifact sharing

* fix workflow

* push stuff

* dynamic trigger e2e

* add permissions

* trigger

* trigger

* trigger

* test ci

* update dir

* add dockerize.sh

* with shared artifacts

* with artifact upload

* test variant

* debug

* test again

* try-at-once

* one more try

* add dockerfiles

* test

* add turbo build

* progress

* fix build

* progress

* version

* test with follow up action

* progress

* progress

* update

* update

* update

* with provenance false

* multiple deployments

* fix issuez

* update

* update

* fix

* more envs

* deploy two

* oopdate

* better yaml

* unleash

* update infra

* fix + comment

* cleanup

* update deprecated Checkout version

* remove commented code

* WITH_LOCAL_DEPS arg for python

* update

* iteration

* change to poetry

* with deploy

* update

* iteration

* with pnpm

* with Pr number

* test matrix

* update workflow

* with app installation for ui

* consolidate dockerfiles

* more changes

* with monorepo install

* fix dockerfile path

* with linking

* with deploy step

* rewire

* fix type errors

* fix

* fix typo

* lots of good stuff

* with all demos

* better stuff

* array

* remove temp matrix in deploy

* better table

* update workflow name
This commit is contained in:
Ariel Weinberger
2024-11-18 21:49:25 -06:00
committed by GitHub
parent d8c2c4456a
commit e378e18019
9 changed files with 397 additions and 270 deletions
-4
View File
@@ -15,7 +15,3 @@ docs
**/.husky
**/node_modules
**/.next
!examples/**/node_modules
!examples/**/.next
+90 -53
View File
@@ -1,4 +1,4 @@
name: Preview Environments (Deploy)
name: Preview Environments
on:
pull_request:
@@ -12,60 +12,26 @@ concurrency:
jobs:
build_images:
runs-on: ubuntu-latest
name: Dockerize
name: Build Images
strategy:
matrix:
app:
- { name: 'coagents-research-canvas-ui', path: 'examples/coagents-research-canvas/ui', dockerfile: 'Dockerfile.ui', type: 'node' }
- { name: 'coagents-research-canvas-agent', path: 'examples/coagents-research-canvas/agent', dockerfile: 'Dockerfile.agent', type: 'poetry' }
- { name: 'coagents-ai-researcher-ui', path: 'examples/coagents-ai-researcher/ui', dockerfile: 'Dockerfile.ui', type: 'node' }
- { name: 'coagents-ai-researcher-agent', path: 'examples/coagents-ai-researcher/agent', dockerfile: 'Dockerfile.agent', type: 'poetry' }
- { name: 'coagents-qa-native-ui', path: 'examples/coagents-qa-native/ui', dockerfile: 'Dockerfile.ui', type: 'node' }
- { name: 'coagents-qa-native-agent', path: 'examples/coagents-qa-native/agent', dockerfile: 'Dockerfile.agent', type: 'poetry' }
- { name: 'coagents-qa-text-ui', path: 'examples/coagents-qa-text/ui', dockerfile: 'Dockerfile.ui', type: 'node' }
- { name: 'coagents-qa-text-agent', path: 'examples/coagents-qa-text/agent', dockerfile: 'Dockerfile.agent', type: 'poetry' }
- { project: "coagents-research-canvas", type: "agent", deps: "remote-deps" }
- { project: "coagents-research-canvas", type: "agent", deps: "local-deps" }
- { project: "coagents-research-canvas", type: "ui" }
- { project: "coagents-ai-researcher", type: "agent", deps: "remote-deps" }
- { project: "coagents-ai-researcher", type: "agent", deps: "local-deps" }
- { project: "coagents-ai-researcher", type: "ui" }
- { project: "coagents-qa-text", type: "agent", deps: "remote-deps" }
- { project: "coagents-qa-text", type: "agent", deps: "local-deps" }
- { project: "coagents-qa-text", type: "ui" }
- { project: "coagents-qa-native", type: "agent", deps: "remote-deps" }
- { project: "coagents-qa-native", type: "agent", deps: "local-deps" }
- { project: "coagents-qa-native", type: "ui" }
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: dopplerhq/secrets-fetch-action@v1.2.0
id: doppler
with:
doppler-token: ${{ secrets.DOPPLER_TOKEN }}
doppler-project: copilotkit-previews
doppler-config: prd
- name: (Node) Setup pnpm
if: matrix.app.type == 'node'
uses: pnpm/action-setup@v4
with:
version: "9.5"
- name: (Node) Use Node.js 21
if: matrix.app.type == 'node'
uses: actions/setup-node@v2
with:
node-version: 21.x
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- name: (Node) Install dependencies
if: matrix.app.type == 'node'
working-directory: ./CopilotKit
run: pnpm install --frozen-lockfile
- name: (Node) Install app
if: matrix.app.type == 'node'
working-directory: ${{ matrix.app.path }}
run: pnpm install --frozen-lockfile
- name: (Node) Build app
if: matrix.app.type == 'node'
working-directory: ${{ matrix.app.path }}
run: pnpm run build
env:
OPENAI_API_KEY: ${{ steps.doppler.outputs.OPENAI_API_KEY }}
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
@@ -86,12 +52,83 @@ jobs:
run: |
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 058264219587.dkr.ecr.us-east-1.amazonaws.com
- name: Build Image
- name: (UI) Setup pnpm
if: matrix.app.type == 'ui'
uses: pnpm/action-setup@v4
with:
version: "9.5"
- name: (UI) Use Node.js 21
if: matrix.app.type == 'ui'
uses: actions/setup-node@v2
with:
node-version: 21.x
cache: 'pnpm'
cache-dependency-path: '**/pnpm-lock.yaml'
- name: (UI) Install dependencies
if: matrix.app.type == 'ui'
working-directory: ./CopilotKit
run: pnpm install --frozen-lockfile
- name: (UI) Install app dependencies
if: matrix.app.type == 'ui'
working-directory: examples/${{ matrix.app.project }}/${{ matrix.app.type }}
run: pnpm install --frozen-lockfile
- name: (UI, Local Deps) Install monorepo
if: matrix.app.type == 'ui'
working-directory: ./CopilotKit
run: pnpm install --frozen-lockfile
- name: (UI, Local Deps) Build @copilotkit packages
if: matrix.app.type == 'ui'
working-directory: ./CopilotKit
run: pnpx turbo run build
- name: (UI, Local Deps) Link @copilotkit packages
if: matrix.app.type == 'ui'
working-directory: ./examples/${{ matrix.app.project }}/${{ matrix.app.type }}
run: |
docker buildx build -t 058264219587.dkr.ecr.us-east-1.amazonaws.com/coagents:${{ matrix.app.name }}-${{ github.run_id }} --build-arg APP_DIR=${{ matrix.app.path }} --secret id=OPENAI_API_KEY . -f ./examples/${{ matrix.app.dockerfile }} --platform=linux/amd64 --provenance=false --push
for package in $(ls -d ../../../CopilotKit/packages/*); do
pnpm link $package
done
- name: (UI) Build app
if: matrix.app.type == 'ui'
working-directory: examples/${{ matrix.app.project }}/${{ matrix.app.type }}
run: pnpm run build
env:
OPENAI_API_KEY: ${{ steps.doppler.outputs.OPENAI_API_KEY }}
- name: (UI) Build Image
if: matrix.app.type == 'ui'
run: |
docker buildx build \
-t 058264219587.dkr.ecr.us-east-1.amazonaws.com/coagents:${{ matrix.app.project }}-ui-${{ github.run_id }} \
--build-arg APP_DIR=examples/${{ matrix.app.project }}/${{ matrix.app.type }} \
-f ./examples/Dockerfile.${{ matrix.app.type }} \
--platform=linux/amd64 \
--provenance=false \
--push \
.
env:
DOCKER_BUILDKIT: 1
- name: (Agent) Build Image
if: matrix.app.type == 'agent'
run: |
docker buildx build \
-t 058264219587.dkr.ecr.us-east-1.amazonaws.com/coagents:${{ matrix.app.project }}-agent-${{ matrix.app.deps }}-${{ github.run_id }} \
--build-arg APP_DIR=examples/${{ matrix.app.project }}/${{ matrix.app.type }} \
-f ./examples/Dockerfile.${{ matrix.app.type }} \
--build-arg WITH_LOCAL_DEPS=${{ matrix.app.deps == 'local-deps' }} \
--platform=linux/amd64 \
--provenance=false \
--push \
.
env:
DOCKER_BUILDKIT: 1
OPENAI_API_KEY: ${{ steps.doppler.outputs.OPENAI_API_KEY }}
cdk_deploy:
runs-on: ubuntu-latest
@@ -138,8 +175,8 @@ jobs:
run: cdk deploy --profile default --all --require-approval never --outputs-file=cdk_outputs.json --concurrency 10
env:
UNIQUE_ENV_ID: 'PR${{ github.event.number }}'
OPENAI_API_KEY: ${{ steps.doppler.outputs.OPENAI_API_KEY }}
GITHUB_RUN_ID: "${{ github.run_id }}"
GITHUB_ACTIONS_RUN_ID: "${{ github.run_id }}"
GITHUB_PR_NUMBER: "${{ github.event.number }}"
- name: Generate table from outputs
id: generate-table
+1 -1
View File
@@ -1,4 +1,4 @@
name: Preview Environments (Destroy)
name: Destroy Preview Environments
on:
pull_request:
+3 -2
View File
@@ -1,6 +1,7 @@
FROM public.ecr.aws/docker/library/python:3.12.0-slim-bullseye
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter
ARG APP_DIR
ARG WITH_LOCAL_DEPS
ENV POETRY_VIRTUALENVS_CREATE=false
@@ -14,8 +15,8 @@ COPY ${APP_DIR}/pyproject.toml ${APP_DIR}/poetry.lock ./
# Copy SDK and install dependencies in a single layer
COPY sdk-python/ /opt/sdk-python
WORKDIR /asset
RUN poetry install --no-interaction --no-ansi && \
poetry add /opt/sdk-python
RUN poetry install --no-interaction --no-ansi
RUN if [ "$WITH_LOCAL_DEPS" = "true" ]; then poetry add /opt/sdk-python; fi
# Copy application code last
COPY ${APP_DIR}/ ./
+4 -3
View File
@@ -12,13 +12,14 @@ ARG APP_DIR
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter
WORKDIR /app
# Copy the built artifacts from the builder stage
# COPY --from=builder-monorepo /app/${APP_DIR}/.next/standalone ./
# COPY --from=builder-monorepo /app/${APP_DIR}/.next/static ./.next/static
COPY ${APP_DIR}/package.json ${APP_DIR}/pnpm-lock.yaml ./
RUN pnpm i --frozen-lockfile
# Copy the built artifacts from the builder stage
COPY ${APP_DIR}/.next/standalone ./
COPY ${APP_DIR}/.next/static ./.next/static
# Set the environment variables (if needed)
ENV NODE_ENV=production
EXPOSE 3000
+119 -139
View File
@@ -1,171 +1,151 @@
#!/usr/bin/env node
import "source-map-support/register";
import * as cdk from "aws-cdk-lib";
import { requireEnv } from "../lib/utils";
import { PreviewProjectStack } from "../lib/demo-project-stack";
import { createAgentProjectStack, createUIProjectStack } from "../lib/utils";
// app
const app = new cdk.App();
const uniqueEnvironmentId = requireEnv("UNIQUE_ENV_ID");
const githubRunId = requireEnv("GITHUB_RUN_ID")
/**
* CoAgents Research Canvas Demo
/*
* Research Canvas
*/
const researchCanvasAgent = new PreviewProjectStack(app, `CoAgentsResearchCanvasDemoAgent`, {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
},
projectName: "CoAgents Research Canvas - Agent",
demoDir: "examples/coagents-research-canvas/agent",
ecrImageTag: `coagents-research-canvas-agent-${githubRunId}`,
overrideDockerWorkdir: "./",
overrideDockerfile: "examples/Dockerfile.agent",
uniqueEnvironmentId,
environmentVariablesFromSecrets: ["OPENAI_API_KEY", "TAVILY_API_KEY"],
port: "8000",
includeInPRComment: false,
outputEnvVariable: "COAGENTS_RESEARCH_CANVAS_AGENT_ENDPOINT_URL",
// Remote Dependencies
const agentWithRemoteDeps = createAgentProjectStack({
app,
project: "coagents-research-canvas",
description: "CoAgents Research Canvas (Agent) - Remote Depenencies",
dependencies: "Remote"
});
const researchCanvasUI = new PreviewProjectStack(app, `CoAgentsResearchCanvasDemoUI`, {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
},
projectName: "CoAgents Research Canvas - UI",
demoDir: "examples/coagents-research-canvas/ui",
ecrImageTag: `coagents-research-canvas-ui-${githubRunId}`,
overrideDockerWorkdir: "./",
overrideDockerfile: "examples/Dockerfile.ui",
uniqueEnvironmentId,
environmentVariablesFromSecrets: ["OPENAI_API_KEY"],
buildSecrets: ["OPENAI_API_KEY"],
environmentVariables: {
REMOTE_ACTION_URL: `${researchCanvasAgent.fnUrl}/copilotkit`,
},
port: "3000",
includeInPRComment: true,
outputEnvVariable: "COAGENTS_RESEARCH_CANVAS_UI_ENDPOINT_URL"
const uiWithRemoteDeps = createUIProjectStack({
app,
project: "coagents-research-canvas",
description: "CoAgents Research Canvas (UI) - Remote Depenencies",
dependencies: "Remote",
agentProject: agentWithRemoteDeps
});
/**
// Local Dependencies
const agentWithLocalDeps = createAgentProjectStack({
app,
project: "coagents-research-canvas",
description: "CoAgents Research Canvas (Agent) - Local Depenencies",
dependencies: "Local"
});
const uiWithLocalDeps = createUIProjectStack({
app,
project: "coagents-research-canvas",
description: "CoAgents Research Canvas (UI) - Local Depenencies",
dependencies: "Local",
agentProject: agentWithLocalDeps
});
/*
* CoAgents Perplexity Demo
*/
const perplexityAgent = new PreviewProjectStack(app, `CoAgentsPerplexityDemoAgent`, {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
},
projectName: "CoAgents Perplexity Clone - Agent",
demoDir: "examples/coagents-ai-researcher/agent",
ecrImageTag: `coagents-research-canvas-agent-${githubRunId}`,
overrideDockerWorkdir: "./",
overrideDockerfile: "examples/Dockerfile.agent",
uniqueEnvironmentId,
environmentVariablesFromSecrets: ["OPENAI_API_KEY", "TAVILY_API_KEY"],
port: "8000",
includeInPRComment: false,
outputEnvVariable: "COAGENTS_PERPLEXITY_AGENT_ENDPOINT_URL",
// Remote Dependencies
const perplexityAgentWithRemoteDeps = createAgentProjectStack({
app,
project: "coagents-ai-researcher",
description: "CoAgents Perplexity Clone (Agent) - Remote Dependencies",
dependencies: "Remote"
});
const perplexityUI = new PreviewProjectStack(app, `CoAgentsPerplexityDemoUI`, {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
},
projectName: "CoAgents Perplexity Clone - UI",
demoDir: "examples/coagents-ai-researcher/ui",
ecrImageTag: `coagents-ai-researcher-ui-${githubRunId}`,
overrideDockerWorkdir: "./",
overrideDockerfile: "examples/Dockerfile.ui",
uniqueEnvironmentId,
environmentVariablesFromSecrets: ["OPENAI_API_KEY"],
buildSecrets: ["OPENAI_API_KEY"],
environmentVariables: {
// REMOTE_ACTION_URL: `${perplexityAgent.fnUrl}/copilotkit`,
},
port: "3000",
includeInPRComment: true,
outputEnvVariable: "COAGENTS_PERPLEXITY_UI_ENDPOINT_URL",
const perplexityUIWithRemoteDeps = createUIProjectStack({
app,
project: "coagents-ai-researcher",
description: "CoAgents Perplexity Clone (UI) - Remote Dependencies",
dependencies: "Remote",
agentProject: perplexityAgentWithRemoteDeps
});
/**
// Local Dependencies
const perplexityAgentWithLocalDeps = createAgentProjectStack({
app,
project: "coagents-ai-researcher",
description: "CoAgents Perplexity Clone (Agent) - Local Dependencies",
dependencies: "Local"
});
const perplexityUIWithLocalDeps = createUIProjectStack({
app,
project: "coagents-ai-researcher",
description: "CoAgents Perplexity Clone (UI) - Local Dependencies",
dependencies: "Local",
agentProject: perplexityAgentWithLocalDeps
});
/*
* CoAgents QA Text Demo
*/
const qaTextAgent = new PreviewProjectStack(app, `CoAgentsQATextDemoAgent`, {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
},
projectName: "CoAgents QA Text - Agent",
demoDir: "examples/coagents-ai-researcher/agent",
ecrImageTag: `coagents-ai-researcher-agent-${githubRunId}`,
overrideDockerWorkdir: "./",
overrideDockerfile: "examples/Dockerfile.agent",
uniqueEnvironmentId,
environmentVariablesFromSecrets: ["OPENAI_API_KEY", "TAVILY_API_KEY"],
port: "8000",
includeInPRComment: false,
outputEnvVariable: "COAGENTS_QA_TEXT_AGENT_ENDPOINT_URL",
// Remote Dependencies
const qaTextAgentWithRemoteDeps = createAgentProjectStack({
app,
project: "coagents-qa-text",
description: "CoAgents QA Text (Agent) - Remote Dependencies",
dependencies: "Remote"
});
const qaTextUI = new PreviewProjectStack(app, `CoAgentsQATextDemoUI`, {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
},
projectName: "CoAgents QA Text - UI",
demoDir: "examples/coagents-qa-text/ui",
ecrImageTag: `coagents-qa-text-ui-${githubRunId}`,
overrideDockerWorkdir: "./",
overrideDockerfile: "examples/Dockerfile.ui",
uniqueEnvironmentId,
environmentVariablesFromSecrets: ["OPENAI_API_KEY"],
buildSecrets: ["OPENAI_API_KEY"],
environmentVariables: {
// REMOTE_ACTION_URL: `${qaTextAgent.fnUrl}/copilotkit`,
},
port: "3000",
includeInPRComment: true,
outputEnvVariable: "COAGENTS_QA_TEXT_UI_ENDPOINT_URL",
const qaTextUIWithRemoteDeps = createUIProjectStack({
app,
project: "coagents-qa-text",
description: "CoAgents QA Text (UI) - Remote Dependencies",
dependencies: "Remote",
agentProject: qaTextAgentWithRemoteDeps
});
/**
// Local Dependencies
const qaTextAgentWithLocalDeps = createAgentProjectStack({
app,
project: "coagents-qa-text",
description: "CoAgents QA Text (Agent) - Local Dependencies",
dependencies: "Local"
});
const qaTextUIWithLocalDeps = createUIProjectStack({
app,
project: "coagents-qa-text",
description: "CoAgents QA Text (UI) - Local Dependencies",
dependencies: "Local",
agentProject: qaTextAgentWithLocalDeps
});
/*
* CoAgents QA Native Demo
*/
const qaNativeAgent = new PreviewProjectStack(app, `CoAgentsQANativetDemoAgent`, {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
},
projectName: "CoAgents QA Native - Agent",
demoDir: "examples/coagents-ai-researcher/agent",
ecrImageTag: `coagents-qa-native-agent-${githubRunId}`,
overrideDockerWorkdir: "./",
overrideDockerfile: "examples/Dockerfile.agent",
uniqueEnvironmentId,
environmentVariablesFromSecrets: ["OPENAI_API_KEY", "TAVILY_API_KEY"],
buildSecrets: ["OPENAI_API_KEY"],
port: "8000",
includeInPRComment: false,
outputEnvVariable: "COAGENTS_QA_NATIVE_AGENT_ENDPOINT_URL",
// Remote Dependencies
const qaNativeAgentWithRemoteDeps = createAgentProjectStack({
app,
project: "coagents-qa-native",
description: "CoAgents QA Native (Agent) - Remote Dependencies",
dependencies: "Remote"
});
const qaNativeAUI = new PreviewProjectStack(app, `CoAgentsQANativeDemoUI`, {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
},
projectName: "CoAgents QA Native - UI",
demoDir: "examples/coagents-qa-native/ui",
ecrImageTag: `coagents-qa-native-ui-${githubRunId}`,
overrideDockerWorkdir: "./",
overrideDockerfile: "examples/Dockerfile.ui",
uniqueEnvironmentId,
environmentVariablesFromSecrets: ["OPENAI_API_KEY"],
buildSecrets: ["OPENAI_API_KEY"],
environmentVariables: {
// REMOTE_ACTION_URL: `${qaNativeAgent.fnUrl}/copilotkit`,
},
port: "3000",
includeInPRComment: true,
outputEnvVariable: "COAGENTS_QA_NATIVE_UI_ENDPOINT_URL",
});
const qaNativeUIWithRemoteDeps = createUIProjectStack({
app,
project: "coagents-qa-native",
description: "CoAgents QA Native (UI) - Remote Dependencies",
dependencies: "Remote",
agentProject: qaNativeAgentWithRemoteDeps
});
// Local Dependencies
const qaNativeAgentWithLocalDeps = createAgentProjectStack({
app,
project: "coagents-qa-native",
description: "CoAgents QA Native (Agent) - Local Dependencies",
dependencies: "Local"
});
const qaNativeUIWithLocalDeps = createUIProjectStack({
app,
project: "coagents-qa-native",
description: "CoAgents QA Native (UI) - Local Dependencies",
dependencies: "Local",
agentProject: qaNativeAgentWithLocalDeps
});
+49 -19
View File
@@ -15,15 +15,45 @@ function generateTable() {
console.log(json);
// const rows = [{
// "Name": "test",
// "Preview (Local Dependencies)": "url"
// "Preview (Remote Dependencies)": "url",
// }]
// Group entries by ProjectName
const projectGroups = Object.values(json).reduce((acc, entry) => {
if (!acc[entry.ProjectName]) {
acc[entry.ProjectName] = {
name: entry.ProjectName,
remote: '',
local: ''
};
}
// Add URLs based on dependency type
if (entry.Dependencies === 'Remote') {
acc[entry.ProjectName].remote = `[Preview](${entry.FunctionUrl})`;
} else if (entry.Dependencies === 'Local') {
acc[entry.ProjectName].local = `[Preview](${entry.FunctionUrl})`;
}
return acc;
}, {});
// Convert grouped data to rows array
const rows = Object.values(projectGroups).map(project => ({
"Name": project.name,
"Preview (Local Dependencies)": project.local,
"Preview (Remote Dependencies)": project.remote
}));
structure.push({
table: {
headers: ["Name", "URL"],
rows: Object.entries(json)
.filter(([key, value]) => value.IncludeInComment === "true")
.map(([key, value]) => ({
Name: value.ProjectName,
URL: `[Link](${value.FunctionUrl})`,
})),
headers: ["Name", "Preview (Local Dependencies)", "Preview (Remote Dependencies)"],
rows,
},
});
@@ -32,19 +62,19 @@ function generateTable() {
fs.writeFileSync(path.resolve(__dirname, "./preview-comment.md"), md);
}
function generateProcessedOutputForTests() {
let output = "";
const json = JSON.parse(file);
// function generateProcessedOutputForTests() {
// let output = "";
// const json = JSON.parse(file);
Object.entries(json)
.filter(([key, value]) => !!value.OutputEnvVariable)
.forEach(([key, value]) => {
const envVariableName = value.OutputEnvVariable;
output += `${envVariableName}="${value.FunctionUrl.replace(/\/$/, '')}"\n`;
});
// Object.entries(json)
// .filter(([key, value]) => !!value.OutputEnvVariable)
// .forEach(([key, value]) => {
// const envVariableName = value.OutputEnvVariable;
// output += `${envVariableName}="${value.FunctionUrl.replace(/\/$/, '')}"\n`;
// });
fs.writeFileSync(path.resolve(__dirname, "./.env.test"), output);
}
// fs.writeFileSync(path.resolve(__dirname, "./.env.test"), output);
// }
generateTable();
generateProcessedOutputForTests();
// generateProcessedOutputForTests();
+27 -48
View File
@@ -8,18 +8,15 @@ import * as logs from "aws-cdk-lib/aws-logs"; // Add this import
import * as events from "aws-cdk-lib/aws-events";
import * as targets from "aws-cdk-lib/aws-events-targets";
import * as ecr from "aws-cdk-lib/aws-ecr";
import { requireEnv } from "./utils";
interface ProjectStackProps extends cdk.StackProps {
export interface ProjectStackProps extends cdk.StackProps {
/**
* Path to the directory of the demo to deploy, relative to the root of the repository.
*/
projectName: string;
projectDescription: string;
demoDir: string;
uniqueEnvironmentId: string;
/**
* Path to the workdir, relative to the root of the repository. By default, this will be the `demoDir`.
*/
overrideDockerWorkdir?: string;
/**
* Path to the Dockerfile to use, relative to the root of the repository. By default, this will be `${demoDir}/Dockerfile`.
*/
@@ -30,19 +27,23 @@ interface ProjectStackProps extends cdk.StackProps {
environmentVariablesFromSecrets?: string[];
buildSecrets?: string[];
buildArgs?: Record<string, string>;
port: number | string;
port: string;
timeout?: number;
memorySize?: number;
includeInPRComment?: boolean;
outputEnvVariable?: string;
ecrImageTag: string;
overrideBuildProps?: Partial<cdk.aws_ecr_assets.DockerImageAssetProps>;
imageTag: string;
outputs?: Record<string, string>;
}
export class PreviewProjectStack extends cdk.Stack {
fnUrl: string;
constructor(scope: Construct, id: string, props: ProjectStackProps) {
const processedId = `${id}${props.uniqueEnvironmentId}`;
const uniqueEnvironmentId = requireEnv("UNIQUE_ENV_ID");
const processedId = `${id}${uniqueEnvironmentId}`;
super(scope, processedId, props);
const secrets = secretsmanager.Secret.fromSecretNameV2(
@@ -87,35 +88,7 @@ export class PreviewProjectStack extends cdk.Stack {
Object.assign(buildArgs, props.buildArgs);
}
const dockerWorkdir = props.overrideDockerWorkdir ?
path.resolve(__dirname, "../../", props.overrideDockerWorkdir) :
path.resolve(__dirname, "../../", props.demoDir)
// const fn = new lambda.Function(this, `Function`, {
// logGroup: logGroup,
// runtime: lambda.Runtime.FROM_IMAGE,
// architecture: lambda.Architecture.X86_64,
// handler: lambda.Handler.FROM_IMAGE,
// environment: {
// ...environmentVariables,
// PORT: props.port.toString(),
// AWS_LWA_INVOKE_MODE: "RESPONSE_STREAM",
// },
// code: lambda.Code.fromAssetImage(dockerWorkdir, {
// platform: ecr_assets.Platform.LINUX_AMD64,
// buildSecrets,
// buildArgs,
// file: props.overrideDockerfile ? props.overrideDockerfile : "Dockerfile",
// }),
// timeout: cdk.Duration.seconds(props.timeout ?? 300),
// memorySize: props.memorySize ?? 1024,
// });
const ecrRepo = ecr.Repository.fromRepositoryName(
this,
"ExamplesRepo",
"coagents"
);
const ecrRepository = ecr.Repository.fromRepositoryName(this, "ECRRepo", "coagents");
const fn = new lambda.Function(this, `Function`, {
logGroup: logGroup,
@@ -127,8 +100,8 @@ export class PreviewProjectStack extends cdk.Stack {
PORT: props.port.toString(),
AWS_LWA_INVOKE_MODE: "RESPONSE_STREAM",
},
code: lambda.Code.fromEcrImage(ecrRepo, {
tagOrDigest: props.ecrImageTag
code: lambda.Code.fromEcrImage(ecrRepository, {
tagOrDigest: props.imageTag
}),
timeout: cdk.Duration.seconds(props.timeout ?? 300),
memorySize: props.memorySize ?? 1024,
@@ -136,7 +109,7 @@ export class PreviewProjectStack extends cdk.Stack {
const eventRule = new events.Rule(this, 'LambdaWarmUpSchedule', {
schedule: events.Schedule.rate(cdk.Duration.minutes(5)),
schedule: events.Schedule.rate(cdk.Duration.minutes(1)),
});
eventRule.addTarget(new targets.LambdaFunction(fn));
@@ -176,18 +149,24 @@ export class PreviewProjectStack extends cdk.Stack {
value: props.projectName,
});
new cdk.CfnOutput(this, "UniqueEnvironmentId", {
value: `${props.uniqueEnvironmentId}`,
new cdk.CfnOutput(this, "ProjectDescription", {
value: props.projectDescription,
});
if (props.outputEnvVariable) {
new cdk.CfnOutput(this, "OutputEnvVariable", {
value: props.outputEnvVariable,
});
new cdk.CfnOutput(this, "UniqueEnvironmentId", {
value: `${uniqueEnvironmentId}`,
});
if (props.outputs) {
for (const [key, value] of Object.entries(props.outputs)) {
new cdk.CfnOutput(this, key, {
value: value,
});
}
}
// Add tag for PR number to all resources
cdk.Tags.of(this).add("env-id", props.uniqueEnvironmentId);
cdk.Tags.of(this).add("env-id", uniqueEnvironmentId);
cdk.Tags.of(this).add("preview-env", "true");
}
}
+104 -1
View File
@@ -1,7 +1,110 @@
import { App } from "aws-cdk-lib";
import { PreviewProjectStack } from "./demo-project-stack";
export function requireEnv(name: string): string {
const value = process.env[name];
if (!value) {
throw new Error(`Required environment variable ${name} is missing`);
}
return value;
}
}
export function toCdkStackName(input: string) {
return input
.split("-") // Split the string by hyphens
.map((word) => word.charAt(0).toUpperCase() + word.slice(1)) // Capitalize each word
.join(""); // Join the words back together
}
export function createAgentProjectStack({
app,
project,
description,
dependencies,
}: {
app: App;
project: string;
description: string;
dependencies: "Remote" | "Local";
}) {
const cdkStackName =
toCdkStackName(project) + "Agent" + dependencies + "Deps";
const dockerfile =
dependencies === "Remote"
? `examples/Dockerfile.agent-remote-deps`
: `examples/Dockerfile.agent-local-deps`;
const GITHUB_ACTIONS_RUN_ID = requireEnv("GITHUB_ACTIONS_RUN_ID");
const outputs: Record<string,string> = {
Dependencies: dependencies,
};
if (process.env.GITHUB_PR_NUMBER) {
outputs["PRNumber"] = process.env.GITHUB_PR_NUMBER;
}
return new PreviewProjectStack(app, cdkStackName, {
projectName: project,
projectDescription: description,
demoDir: `examples/${project}/agent`,
overrideDockerfile: dockerfile,
environmentVariablesFromSecrets: ["OPENAI_API_KEY", "TAVILY_API_KEY"],
port: "8000",
includeInPRComment: false,
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
},
imageTag: `${project}-agent-${
dependencies === "Remote" ? "remote-deps" : "local-deps"
}-${GITHUB_ACTIONS_RUN_ID}`,
outputs
});
}
export function createUIProjectStack({
app,
project,
description,
dependencies,
agentProject,
}: {
app: App;
project: string;
description: string;
dependencies: "Remote" | "Local";
agentProject: PreviewProjectStack;
}) {
const cdkStackName = toCdkStackName(project) + "UI" + dependencies + "Deps";
const dockerfile =
dependencies === "Remote"
? `examples/Dockerfile.ui-remote-deps`
: `examples/Dockerfile.ui-local-deps`;
const GITHUB_ACTIONS_RUN_ID = requireEnv("GITHUB_ACTIONS_RUN_ID");
const outputs: Record<string,string> = {
Dependencies: dependencies,
};
if (process.env.GITHUB_PR_NUMBER) {
outputs["PRNumber"] = process.env.GITHUB_PR_NUMBER;
}
return new PreviewProjectStack(app, cdkStackName, {
projectName: project,
projectDescription: `${description} (Dependencies: ${dependencies})`,
demoDir: `examples/${project}/ui`,
overrideDockerfile: dockerfile,
environmentVariablesFromSecrets: ["OPENAI_API_KEY"],
environmentVariables: {
REMOTE_ACTION_URL: `${agentProject.fnUrl}/copilotkit`,
},
buildSecrets: ["OPENAI_API_KEY"],
port: "3000",
includeInPRComment: true,
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
},
imageTag: `${project}-ui-${GITHUB_ACTIONS_RUN_ID}`,
outputs,
});
}