mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-06 04:22:01 +00:00
[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 ```
This commit is contained in:
@@ -1,18 +1 @@
|
||||
*
|
||||
|
||||
# general
|
||||
!utils/
|
||||
!utils/run.js
|
||||
!.yarnrc
|
||||
!yarn.lock
|
||||
!package.json
|
||||
!turbo.json
|
||||
|
||||
# api
|
||||
!api/
|
||||
!api/**
|
||||
|
||||
# packages
|
||||
!packages/
|
||||
!packages/frameworks
|
||||
!packages/frameworks/**
|
||||
packages/*/test/**
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import fs from 'fs/promises';
|
||||
import { join } from 'path';
|
||||
import { join, dirname } from 'path';
|
||||
import execa from 'execa';
|
||||
import { getExampleList } from '../examples/example-list';
|
||||
import { mapOldToNew } from '../examples/map-old-to-new';
|
||||
|
||||
@@ -40,7 +41,32 @@ async function main() {
|
||||
JSON.stringify([...existingExamples, ...oldExamples])
|
||||
);
|
||||
|
||||
const { stdout: sha } = await execa('git', ['rev-parse', '--short', 'HEAD'], {
|
||||
cwd: repoRoot,
|
||||
});
|
||||
|
||||
const tarballsDir = join(pubDir, 'tarballs');
|
||||
const packagesDir = join(repoRoot, 'packages');
|
||||
const packages = await fs.readdir(packagesDir);
|
||||
for (const pkg of packages) {
|
||||
const fullDir = join(packagesDir, pkg);
|
||||
const packageJsonRaw = await fs.readFile(
|
||||
join(fullDir, 'package.json'),
|
||||
'utf-8'
|
||||
);
|
||||
const packageJson = JSON.parse(packageJsonRaw);
|
||||
const tarballName = `${packageJson.name
|
||||
.replace('@', '')
|
||||
.replace('/', '-')}-v${packageJson.version}-${sha.trim()}.tgz`;
|
||||
const destTarballPath = join(tarballsDir, `${packageJson.name}.tgz`);
|
||||
await fs.mkdir(dirname(destTarballPath), { recursive: true });
|
||||
await fs.copyFile(join(fullDir, tarballName), destTarballPath);
|
||||
}
|
||||
|
||||
console.log('Completed building static frontend.');
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
main().catch(err => {
|
||||
console.log('error running build:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"publish-from-github": "./utils/publish.sh",
|
||||
"changelog": "node utils/changelog.js",
|
||||
"build": "turbo run build",
|
||||
"vercel-build": "yarn build && cd api && node -r ts-eager/register ./_lib/script/build.ts",
|
||||
"vercel-build": "yarn build && yarn run pack && cd api && node -r ts-eager/register ./_lib/script/build.ts",
|
||||
"pre-commit": "lint-staged",
|
||||
"test": "jest --rootDir=\"test\" --testPathPattern=\"\\.test.js\"",
|
||||
"test-unit": "yarn test && turbo run test-unit",
|
||||
@@ -49,7 +49,8 @@
|
||||
"test-integration-once": "turbo run test-integration-once",
|
||||
"test-integration-dev": "turbo run test-integration-dev",
|
||||
"lint": "eslint . --ext .ts,.js",
|
||||
"prepare": "husky install"
|
||||
"prepare": "husky install",
|
||||
"pack": "cd utils && node -r ts-eager/register ./pack.ts"
|
||||
},
|
||||
"lint-staged": {
|
||||
"./{*,{api,packages,test,utils}/**/*}.{js,ts}": [
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import _pkg from '../../package.json';
|
||||
import fs from 'fs';
|
||||
import { join } from 'path';
|
||||
import { PackageJson } from '@vercel/build-utils';
|
||||
|
||||
const pkg: PackageJson & typeof _pkg = _pkg;
|
||||
let rootDir = __dirname;
|
||||
while (!fs.existsSync(join(rootDir, 'package.json'))) {
|
||||
rootDir = join(rootDir, '..');
|
||||
}
|
||||
|
||||
const pkgPath = join(rootDir, 'package.json');
|
||||
const pkg: PackageJson & typeof import('../../package.json') = JSON.parse(
|
||||
fs.readFileSync(pkgPath, 'utf8')
|
||||
);
|
||||
export default pkg;
|
||||
|
||||
52
utils/pack.ts
vendored
Normal file
52
utils/pack.ts
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
import execa from 'execa';
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import { TurboDryRun } from './types';
|
||||
|
||||
const rootDir = path.join(__dirname, '..');
|
||||
|
||||
async function main() {
|
||||
const { stdout: sha } = await execa('git', ['rev-parse', '--short', 'HEAD'], {
|
||||
cwd: rootDir,
|
||||
});
|
||||
const { stdout: turboStdout } = await execa(
|
||||
'turbo',
|
||||
['run', 'build', '--dry=json'],
|
||||
{
|
||||
cwd: rootDir,
|
||||
}
|
||||
);
|
||||
const turboJson: TurboDryRun = JSON.parse(turboStdout);
|
||||
for (const task of turboJson.tasks) {
|
||||
const dir = path.join(rootDir, task.directory);
|
||||
const packageJsonPath = path.join(dir, 'package.json');
|
||||
const originalPackageObj = await fs.readJson(packageJsonPath);
|
||||
const packageObj = await fs.readJson(packageJsonPath);
|
||||
packageObj.version += `-${sha.trim()}`;
|
||||
|
||||
if (task.dependencies.length > 0) {
|
||||
for (const dependency of task.dependencies) {
|
||||
const name = dependency.split('#')[0];
|
||||
const tarballUrl = `https://${process.env.VERCEL_URL}/tarballs/${name}.tgz`;
|
||||
if (packageObj.dependencies && name in packageObj.dependencies) {
|
||||
packageObj.dependencies[name] = tarballUrl;
|
||||
}
|
||||
if (packageObj.devDependencies && name in packageObj.devDependencies) {
|
||||
packageObj.devDependencies[name] = tarballUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
await fs.writeJson(packageJsonPath, packageObj, { spaces: 2 });
|
||||
|
||||
await execa('yarn', ['pack'], {
|
||||
cwd: dir,
|
||||
stdio: 'inherit',
|
||||
});
|
||||
await fs.writeJson(packageJsonPath, originalPackageObj, { spaces: 2 });
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.log('error running pack:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
16
utils/tsconfig.json
vendored
Normal file
16
utils/tsconfig.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"noEmitOnError": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true
|
||||
},
|
||||
"include": ["*.ts"]
|
||||
}
|
||||
17
utils/types.ts
vendored
Normal file
17
utils/types.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
export interface TurboDryRun {
|
||||
packages: Array<string>;
|
||||
tasks: Array<Task>;
|
||||
}
|
||||
|
||||
export interface Task {
|
||||
taskId: string;
|
||||
task: string;
|
||||
package: string;
|
||||
hash: string;
|
||||
command: string;
|
||||
outputs: Array<string>;
|
||||
logFile: string;
|
||||
directory: string;
|
||||
dependencies: Array<string>;
|
||||
dependents: Array<string>;
|
||||
}
|
||||
Reference in New Issue
Block a user