Skip to content

Commit 45c5166

Browse files
committed
ci: add packaging test workflow
1 parent e1e52d3 commit 45c5166

File tree

3 files changed

+151
-0
lines changed

3 files changed

+151
-0
lines changed

.github/workflows/packaging.yaml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Packaging Tests
2+
3+
on:
4+
- pull_request
5+
- push
6+
7+
env:
8+
CI: true
9+
10+
jobs:
11+
build:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v3
15+
- uses: actions/setup-node@v3
16+
with:
17+
node-version: 22.x
18+
cache: npm
19+
- run: npm ci
20+
- run: npm run build
21+
- run: npm pack
22+
- name: Upload tarball
23+
uses: actions/upload-artifact@v4
24+
with:
25+
name: package-tarball
26+
path: firebase-functions-*.tgz
27+
28+
verify:
29+
needs: build
30+
runs-on: ubuntu-latest
31+
strategy:
32+
matrix:
33+
node-version:
34+
- 18.x
35+
- 20.x
36+
- 22.x
37+
- 24.x
38+
steps:
39+
- uses: actions/checkout@v3
40+
- uses: actions/setup-node@v3
41+
with:
42+
node-version: ${{ matrix.node-version }}
43+
- name: Download tarball
44+
uses: actions/download-artifact@v4
45+
with:
46+
name: package-tarball
47+
- run: chmod +x ./scripts/test-packaging.sh && ./scripts/test-packaging.sh firebase-functions-*.tgz

scripts/test-packaging.sh

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/bin/bash
2+
set -eux
3+
4+
# Argument 1: Path to a pre-built tarball.
5+
# If not provided, the script will run 'npm run build' and 'npm pack' locally.
6+
PREBUILT_TARBALL="$1"
7+
8+
# Setup cleanup
9+
WORK_DIR=$(mktemp -d)
10+
function cleanup {
11+
rm -rf "$WORK_DIR"
12+
echo "Deleted temp working directory $WORK_DIR"
13+
}
14+
trap cleanup EXIT
15+
16+
# Save current directory to resolve relative paths later
17+
START_DIR="$(pwd)"
18+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19+
20+
if [ -n "$PREBUILT_TARBALL" ]; then
21+
echo "Using prebuilt tarball: $PREBUILT_TARBALL"
22+
# Resolve absolute path if it's relative
23+
if [[ "$PREBUILT_TARBALL" != /* ]]; then
24+
PREBUILT_TARBALL="$START_DIR/$PREBUILT_TARBALL"
25+
fi
26+
TARBALL_PATH="$PREBUILT_TARBALL"
27+
else
28+
echo "Building project..."
29+
cd "$SCRIPT_DIR/.."
30+
npm run build
31+
32+
echo "Packing project..."
33+
TARBALL=$(npm pack)
34+
mv "$TARBALL" "$WORK_DIR/"
35+
TARBALL_PATH="$WORK_DIR/$TARBALL"
36+
fi
37+
38+
echo "Setting up test project in $WORK_DIR..."
39+
pushd "$WORK_DIR" > /dev/null
40+
npm init -y > /dev/null
41+
npm install "$TARBALL_PATH" > /dev/null
42+
43+
echo "Running verification script..."
44+
cp "$SCRIPT_DIR/verify-exports.mjs" .
45+
node verify-exports.mjs
46+
47+
popd > /dev/null

scripts/verify-exports.mjs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import { createRequire } from 'module';
4+
5+
const require = createRequire(import.meta.url);
6+
7+
// Read the package.json of the INSTALLED package to verify what was actually packed
8+
const pkgPath = path.resolve(process.cwd(), 'node_modules/firebase-functions/package.json');
9+
if (!fs.existsSync(pkgPath)) {
10+
console.error(`❌ Could not find installed package at ${pkgPath}`);
11+
process.exit(1);
12+
}
13+
14+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
15+
const exports = Object.keys(pkg.exports || {});
16+
17+
// Filter out non-code entrypoints (e.g. package.json if it were exported)
18+
const entryPoints = exports.filter(e => !e.endsWith('.json'));
19+
20+
console.log(`Found ${entryPoints.length} entry points to verify.`);
21+
22+
let hasError = false;
23+
24+
async function verify() {
25+
console.log('\n--- Verifying CommonJS (require) ---');
26+
for (const exp of entryPoints) {
27+
const importPath = exp === '.' ? 'firebase-functions' : `firebase-functions/${exp.replace('./', '')}`;
28+
try {
29+
require(importPath);
30+
console.log(`✅ CJS: ${importPath}`);
31+
} catch (e) {
32+
console.error(`❌ CJS Failed: ${importPath}`, e.message);
33+
hasError = true;
34+
}
35+
}
36+
37+
console.log('\n--- Verifying ES Modules (import) ---');
38+
for (const exp of entryPoints) {
39+
const importPath = exp === '.' ? 'firebase-functions' : `firebase-functions/${exp.replace('./', '')}`;
40+
try {
41+
await import(importPath);
42+
console.log(`✅ ESM: ${importPath}`);
43+
} catch (e) {
44+
console.error(`❌ ESM Failed: ${importPath}`, e.message);
45+
hasError = true;
46+
}
47+
}
48+
49+
if (hasError) {
50+
console.error('\n❌ Verification failed with errors.');
51+
process.exit(1);
52+
} else {
53+
console.log('\n✨ All entry points verified successfully!');
54+
}
55+
}
56+
57+
verify();

0 commit comments

Comments
 (0)