Skip to content

Commit 8167233

Browse files
authored
[tests] Create tarballs of all packages in Vercel deployment (#7967)
For the Vercel deployment, run `yarn pack` in each of the packages in the monorepo and place them in the "public/tarballs" directory so that we can have npm-installable URLs of each package for every commit. The `package.json` of each package is also updated to reference the tarball when a package depends on other packages within the monorepo. Try it out like: ``` $ npm i -g https://vercel-biww73ffq.vercel.sh/tarballs/vercel.tgz # Notice how the package.json has the monorepo dependencies # updated to point to the related tarballs from the same deployment: $ cat /usr/local/lib/node_modules/vercel/package.json | grep biww "@vercel/build-utils": "https://vercel-biww73ffq.vercel.sh/tarballs/@vercel/build-utils.tgz", "@vercel/go": "https://vercel-biww73ffq.vercel.sh/tarballs/@vercel/go.tgz", "@vercel/next": "https://vercel-biww73ffq.vercel.sh/tarballs/@vercel/next.tgz", "@vercel/node": "https://vercel-biww73ffq.vercel.sh/tarballs/@vercel/node.tgz", "@vercel/python": "https://vercel-biww73ffq.vercel.sh/tarballs/@vercel/python.tgz", "@vercel/redwood": "https://vercel-biww73ffq.vercel.sh/tarballs/@vercel/redwood.tgz", "@vercel/remix": "https://vercel-biww73ffq.vercel.sh/tarballs/@vercel/remix.tgz", "@vercel/ruby": "https://vercel-biww73ffq.vercel.sh/tarballs/@vercel/ruby.tgz", "@vercel/static-build": "https://vercel-biww73ffq.vercel.sh/tarballs/@vercel/static-build.tgz", "@vercel/client": "https://vercel-biww73ffq.vercel.sh/tarballs/@vercel/client.tgz", "@vercel/frameworks": "https://vercel-biww73ffq.vercel.sh/tarballs/@vercel/frameworks.tgz", # Also notice that the "version" in `package.json` gets updated to include the commit # SHA so that we can easily identify which commit a given tarball was generated from: $ vercel --version 25.1.1-canary.1-727b290 ```
1 parent 32ee6ab commit 8167233

File tree

7 files changed

+127
-24
lines changed

7 files changed

+127
-24
lines changed

.vercelignore

+1-18
Original file line numberDiff line numberDiff line change
@@ -1,18 +1 @@
1-
*
2-
3-
# general
4-
!utils/
5-
!utils/run.js
6-
!.yarnrc
7-
!yarn.lock
8-
!package.json
9-
!turbo.json
10-
11-
# api
12-
!api/
13-
!api/**
14-
15-
# packages
16-
!packages/
17-
!packages/frameworks
18-
!packages/frameworks/**
1+
packages/*/test/**

api/_lib/script/build.ts

+28-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import fs from 'fs/promises';
2-
import { join } from 'path';
2+
import { join, dirname } from 'path';
3+
import execa from 'execa';
34
import { getExampleList } from '../examples/example-list';
45
import { mapOldToNew } from '../examples/map-old-to-new';
56

@@ -40,7 +41,32 @@ async function main() {
4041
JSON.stringify([...existingExamples, ...oldExamples])
4142
);
4243

44+
const { stdout: sha } = await execa('git', ['rev-parse', '--short', 'HEAD'], {
45+
cwd: repoRoot,
46+
});
47+
48+
const tarballsDir = join(pubDir, 'tarballs');
49+
const packagesDir = join(repoRoot, 'packages');
50+
const packages = await fs.readdir(packagesDir);
51+
for (const pkg of packages) {
52+
const fullDir = join(packagesDir, pkg);
53+
const packageJsonRaw = await fs.readFile(
54+
join(fullDir, 'package.json'),
55+
'utf-8'
56+
);
57+
const packageJson = JSON.parse(packageJsonRaw);
58+
const tarballName = `${packageJson.name
59+
.replace('@', '')
60+
.replace('/', '-')}-v${packageJson.version}-${sha.trim()}.tgz`;
61+
const destTarballPath = join(tarballsDir, `${packageJson.name}.tgz`);
62+
await fs.mkdir(dirname(destTarballPath), { recursive: true });
63+
await fs.copyFile(join(fullDir, tarballName), destTarballPath);
64+
}
65+
4366
console.log('Completed building static frontend.');
4467
}
4568

46-
main().catch(console.error);
69+
main().catch(err => {
70+
console.log('error running build:', err);
71+
process.exit(1);
72+
});

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,16 @@
4141
"publish-from-github": "./utils/publish.sh",
4242
"changelog": "node utils/changelog.js",
4343
"build": "turbo run build",
44-
"vercel-build": "yarn build && cd api && node -r ts-eager/register ./_lib/script/build.ts",
44+
"vercel-build": "yarn build && yarn run pack && cd api && node -r ts-eager/register ./_lib/script/build.ts",
4545
"pre-commit": "lint-staged",
4646
"test": "jest --rootDir=\"test\" --testPathPattern=\"\\.test.js\"",
4747
"test-unit": "yarn test && turbo run test-unit",
4848
"test-integration-cli": "turbo run test-integration-cli",
4949
"test-integration-once": "turbo run test-integration-once",
5050
"test-integration-dev": "turbo run test-integration-dev",
5151
"lint": "eslint . --ext .ts,.js",
52-
"prepare": "husky install"
52+
"prepare": "husky install",
53+
"pack": "cd utils && node -r ts-eager/register ./pack.ts"
5354
},
5455
"lint-staged": {
5556
"./{*,{api,packages,test,utils}/**/*}.{js,ts}": [

packages/cli/src/util/pkg.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
import _pkg from '../../package.json';
1+
import fs from 'fs';
2+
import { join } from 'path';
23
import { PackageJson } from '@vercel/build-utils';
34

4-
const pkg: PackageJson & typeof _pkg = _pkg;
5+
let rootDir = __dirname;
6+
while (!fs.existsSync(join(rootDir, 'package.json'))) {
7+
rootDir = join(rootDir, '..');
8+
}
59

10+
const pkgPath = join(rootDir, 'package.json');
11+
const pkg: PackageJson & typeof import('../../package.json') = JSON.parse(
12+
fs.readFileSync(pkgPath, 'utf8')
13+
);
614
export default pkg;

utils/pack.ts

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import execa from 'execa';
2+
import path from 'path';
3+
import fs from 'fs-extra';
4+
import { TurboDryRun } from './types';
5+
6+
const rootDir = path.join(__dirname, '..');
7+
8+
async function main() {
9+
const { stdout: sha } = await execa('git', ['rev-parse', '--short', 'HEAD'], {
10+
cwd: rootDir,
11+
});
12+
const { stdout: turboStdout } = await execa(
13+
'turbo',
14+
['run', 'build', '--dry=json'],
15+
{
16+
cwd: rootDir,
17+
}
18+
);
19+
const turboJson: TurboDryRun = JSON.parse(turboStdout);
20+
for (const task of turboJson.tasks) {
21+
const dir = path.join(rootDir, task.directory);
22+
const packageJsonPath = path.join(dir, 'package.json');
23+
const originalPackageObj = await fs.readJson(packageJsonPath);
24+
const packageObj = await fs.readJson(packageJsonPath);
25+
packageObj.version += `-${sha.trim()}`;
26+
27+
if (task.dependencies.length > 0) {
28+
for (const dependency of task.dependencies) {
29+
const name = dependency.split('#')[0];
30+
const tarballUrl = `https://${process.env.VERCEL_URL}/tarballs/${name}.tgz`;
31+
if (packageObj.dependencies && name in packageObj.dependencies) {
32+
packageObj.dependencies[name] = tarballUrl;
33+
}
34+
if (packageObj.devDependencies && name in packageObj.devDependencies) {
35+
packageObj.devDependencies[name] = tarballUrl;
36+
}
37+
}
38+
}
39+
await fs.writeJson(packageJsonPath, packageObj, { spaces: 2 });
40+
41+
await execa('yarn', ['pack'], {
42+
cwd: dir,
43+
stdio: 'inherit',
44+
});
45+
await fs.writeJson(packageJsonPath, originalPackageObj, { spaces: 2 });
46+
}
47+
}
48+
49+
main().catch(err => {
50+
console.log('error running pack:', err);
51+
process.exit(1);
52+
});

utils/tsconfig.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"skipLibCheck": true,
5+
"strict": false,
6+
"forceConsistentCasingInFileNames": true,
7+
"noEmit": true,
8+
"noEmitOnError": true,
9+
"esModuleInterop": true,
10+
"module": "commonjs",
11+
"moduleResolution": "node",
12+
"resolveJsonModule": true,
13+
"isolatedModules": true
14+
},
15+
"include": ["*.ts"]
16+
}

utils/types.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export interface TurboDryRun {
2+
packages: Array<string>;
3+
tasks: Array<Task>;
4+
}
5+
6+
export interface Task {
7+
taskId: string;
8+
task: string;
9+
package: string;
10+
hash: string;
11+
command: string;
12+
outputs: Array<string>;
13+
logFile: string;
14+
directory: string;
15+
dependencies: Array<string>;
16+
dependents: Array<string>;
17+
}

0 commit comments

Comments
 (0)