[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:
Nathan Rajlich
2022-06-15 10:44:23 -07:00
committed by GitHub
parent 32ee6aba92
commit 8167233c56
7 changed files with 127 additions and 24 deletions

View File

@@ -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/**

View File

@@ -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);
});

View File

@@ -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}": [

View File

@@ -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
View 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
View 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
View 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>;
}