Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions .github/workflows/js.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,21 @@ jobs:
PACKED_OTEL_TARBALL=$(npm pack --pack-destination ../../js/artifacts)
echo "packed_otel_tarball=$PACKED_OTEL_TARBALL" >> "$GITHUB_OUTPUT"

- name: Build and pack @braintrust/template-nunjucks
id: prepare_template_nunjucks_artifact
shell: bash
run: |
cd integrations/template-nunjucks
pnpm run build
PACKED_NUNJUCKS_TARBALL=$(npm pack --pack-destination ../../js/artifacts)
echo "packed_nunjucks_tarball=$PACKED_NUNJUCKS_TARBALL" >> "$GITHUB_OUTPUT"

- name: List artifacts before upload
shell: bash
run: |
echo "Braintrust tarball: ${{ steps.prepare_artifact.outputs.packed_tarball }}"
echo "Otel tarball: ${{ steps.prepare_otel_artifact.outputs.packed_otel_tarball }}"
echo "Template-nunjucks tarball: ${{ steps.prepare_template_nunjucks_artifact.outputs.packed_nunjucks_tarball }}"
ls -la js/artifacts/

- name: Upload build artifacts
Expand All @@ -103,6 +113,7 @@ jobs:
path: |
js/artifacts/${{ steps.prepare_artifact.outputs.packed_tarball }}
js/artifacts/${{ steps.prepare_otel_artifact.outputs.packed_otel_tarball }}
js/artifacts/${{ steps.prepare_template_nunjucks_artifact.outputs.packed_nunjucks_tarball }}
retention-days: 1

api-compatibility:
Expand Down Expand Up @@ -206,7 +217,7 @@ jobs:
strategy:
fail-fast: false
matrix:
integration: [otel-v1, span]
integration: [otel-v1, span, template-nunjucks]
os: [ubuntu-latest, windows-latest]
node-version: [20, 22]

Expand Down Expand Up @@ -239,7 +250,11 @@ jobs:
# Remove package-lock.json to avoid version mismatch with downloaded artifacts
rm -f package-lock.json

if [ "${{ matrix.integration }}" != "otel-v1" ]; then
if [ "${{ matrix.integration }}" = "template-nunjucks" ]; then
npm install
npx tsx ../../install-build.ts ../../../artifacts braintrust
npx tsx ../../install-build.ts ../../../artifacts template-nunjucks
elif [ "${{ matrix.integration }}" != "otel-v1" ]; then
npm install
npx tsx ../../install-build.ts ../../../artifacts braintrust
else
Expand Down Expand Up @@ -398,6 +413,13 @@ jobs:
fail-fast: false
matrix:
node-version: [20, 22]
mode:
[
braintrust-node-compat,
braintrust-browser-node-compat,
braintrust-browser-no-compat,
braintrust-no-compat,
]

steps:
- name: Checkout repository
Expand Down Expand Up @@ -439,6 +461,8 @@ jobs:
- name: Run Cloudflare Worker smoke test
working-directory: js/smoke
shell: bash
env:
CLOUDFLARE_WORKER_MODE: ${{ matrix.mode }}
run: |
./run-tests.sh cloudflare-worker

Expand Down Expand Up @@ -567,6 +591,6 @@ jobs:
- name: Run Deno smoke test
working-directory: js/smoke
env:
BRAINTRUST_BUILD_DIR: ${{ github.workspace }}/js/smoke/tests/deno/build/braintrust/dist/browser.mjs
BRAINTRUST_BUILD_DIR: ${{ github.workspace }}/js/smoke/tests/deno/build/braintrust/dist/index.mjs
run: |
./run-tests.sh deno
60 changes: 60 additions & 0 deletions .github/workflows/template-nunjucks-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: template-nunjucks

on:
pull_request:
paths:
- "integrations/template-nunjucks/**"
- "js/**"
- ".github/workflows/template-nunjucks-test.yaml"
push:
branches: [main]
paths:
- "integrations/template-nunjucks/**"
- "js/**"

jobs:
test:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
node-version: [20, 22]

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
registry-url: "https://registry.npmjs.org"

- uses: pnpm/action-setup@v4

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build and pack braintrust
shell: bash
run: |
cd js
pnpm run build
mkdir -p artifacts
npm pack --pack-destination artifacts

- name: Build and pack @braintrust/template-nunjucks
shell: bash
run: |
cd integrations/template-nunjucks
pnpm run build
npm pack --pack-destination ../../js/artifacts

- name: Run Braintrust + template-nunjucks integration smoke test
shell: bash
run: |
cd js/smoke/tests/template-nunjucks
rm -f package-lock.json
npm install --legacy-peer-deps
npx tsx ../../install-build.ts ../../../artifacts braintrust
npx tsx ../../install-build.ts ../../../artifacts template-nunjucks
npm test
42 changes: 42 additions & 0 deletions integrations/template-nunjucks/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "@braintrust/template-nunjucks",
"version": "0.0.1",
"description": "Nunjucks templating support for the Braintrust JS SDK",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"sideEffects": true,
"exports": {
"./package.json": "./package.json",
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"module": "./dist/index.mjs",
"require": "./dist/index.js"
}
},
"files": [
"dist/**/*"
],
"scripts": {
"build": "tsup",
"watch": "tsup --watch",
"clean": "rm -r dist/*",
"prepack": "npm run build"
},
"author": "Braintrust Data Inc.",
"license": "MIT",
"dependencies": {
"nunjucks": "^3.2.4"
},
"peerDependencies": {
"braintrust": ">=0.0.141"
},
"devDependencies": {
"@types/nunjucks": "^3.2.6",
"@types/node": "^20.10.5",
"braintrust": "workspace:*",
"tsup": "^8.5.1",
"typescript": "5.5.4"
}
}
21 changes: 21 additions & 0 deletions integrations/template-nunjucks/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as nunjucks from "nunjucks";

import { registerTemplateRenderer } from "braintrust";

const createEnv = (throwOnUndefined: boolean) =>
new nunjucks.Environment(null, {
autoescape: true,
throwOnUndefined,
});

const env = createEnv(false);
const strictEnv = createEnv(true);

registerTemplateRenderer("nunjucks", {
render(template, variables, _escape, strict) {
return (strict ? strictEnv : env).renderString(template, variables);
},
lint(template, variables) {
strictEnv.renderString(template, variables);
},
});
13 changes: 13 additions & 0 deletions integrations/template-nunjucks/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"declaration": true,
"lib": ["es2022"],
"module": "esnext",
"target": "es2022",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src"]
}
10 changes: 10 additions & 0 deletions integrations/template-nunjucks/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineConfig } from "tsup";

export default defineConfig({
entry: ["src/index.ts"],
format: ["cjs", "esm"],
outDir: "dist",
dts: true,
splitting: true,
clean: true,
});
2 changes: 0 additions & 2 deletions js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@
"dependencies": {
"@ai-sdk/provider": "^1.1.3",
"@next/env": "^14.2.3",
"@types/nunjucks": "^3.2.6",
"@vercel/functions": "^1.0.2",
"argparse": "^2.0.1",
"boxen": "^8.0.1",
Expand All @@ -133,7 +132,6 @@
"http-errors": "^2.0.0",
"minimatch": "^9.0.3",
"mustache": "^4.2.0",
"nunjucks": "^3.2.4",
"pluralize": "^8.0.0",
"simple-git": "^3.21.0",
"source-map": "^0.7.4",
Expand Down
25 changes: 24 additions & 1 deletion js/smoke/install-build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from "path";
import { execSync } from "child_process";

const artifactsDir = path.resolve(process.argv[2] || "../../artifacts");
const packageToInstall = process.argv[3] || "both"; // "braintrust", "otel", or "both"
const packageToInstall = process.argv[3] || "both"; // "braintrust", "otel", "template-nunjucks", or "both"

function findLatestTarball(prefixes: string[]): string | null {
if (!fs.existsSync(artifactsDir)) {
Expand Down Expand Up @@ -44,6 +44,7 @@ if (packageToInstall === "braintrust") {
(f) =>
f.startsWith("braintrust-") &&
!f.startsWith("braintrust-otel-") &&
!f.startsWith("braintrust-template-nunjucks-") &&
f.endsWith(".tgz"),
)
.map((f) => ({
Expand Down Expand Up @@ -75,3 +76,25 @@ if (packageToInstall === "otel") {
}
installTarball("@braintrust/otel", path.join(artifactsDir, otelTar));
}

// Install @braintrust/template-nunjucks
if (packageToInstall === "template-nunjucks") {
const nunjucksTar = findLatestTarball(["braintrust-template-nunjucks-"]);
if (!nunjucksTar) {
console.error(
`No @braintrust/template-nunjucks tarball found in ${artifactsDir}.`,
);
console.error(
"Build it first: cd integrations/template-nunjucks && npm run build && npm pack --pack-destination ../../js/artifacts",
);
process.exit(1);
}
installTarball(
"@braintrust/template-nunjucks",
path.join(artifactsDir, nunjucksTar),
);
}

if (packageToInstall === "both") {
process.exit(0);
}
13 changes: 10 additions & 3 deletions js/smoke/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,18 @@ run_test() {

cd "$test_dir"

log_info "Running: npm test"
local npm_script="test"

# Allow CI to run Cloudflare Worker variants as separate pipeline jobs
if [ "$test_name" = "cloudflare-worker" ] && [ -n "${CLOUDFLARE_WORKER_MODE:-}" ]; then
npm_script="test:${CLOUDFLARE_WORKER_MODE}"
fi

log_info "Running: npm run $npm_script"

# Set BRAINTRUST_BUILD_DIR for Deno tests if not already set
if [ "$test_name" = "deno" ] && [ -z "${BRAINTRUST_BUILD_DIR:-}" ]; then
local deno_build_file="$TESTS_DIR/deno/build/braintrust/dist/browser.mjs"
local deno_build_file="$TESTS_DIR/deno/build/braintrust/dist/index.mjs"
if [ -f "$deno_build_file" ]; then
# Convert to absolute path for Deno file:// imports
local abs_dir="$(cd "$(dirname "$deno_build_file")" && pwd)"
Expand All @@ -178,7 +185,7 @@ run_test() {
local test_output
local test_exit_code

if test_output=$(npm test 2>&1); then
if test_output=$(npm run "$npm_script" 2>&1); then
test_exit_code=0
else
test_exit_code=$?
Expand Down
Loading
Loading