Compare commits

...

8 Commits

Author SHA1 Message Date
Sean Massa
90c1895949 Publish Stable
- @vercel/build-utils@5.0.6
 - vercel@27.3.1
 - @vercel/client@12.1.5
 - @vercel/fs-detectors@2.0.2
 - @vercel/go@2.0.10
 - @vercel/hydrogen@0.0.7
 - @vercel/next@3.1.10
 - @vercel/node@2.5.1
 - @vercel/python@3.1.2
 - @vercel/redwood@1.0.11
 - @vercel/remix@1.0.12
 - @vercel/ruby@1.3.18
 - @vercel/static-build@1.0.11
2022-07-28 16:01:36 -05:00
Steven
46a1f3670b [tests] Remove turbo's dependsOn to speed up tests (#8264)
Since CI is already setup to run Build and then Test, we don't need to add it as an explicit turbo dependency so this PR removes `dependsOn: ['build']` from each test task.

In fact, the `test-unit` step doesn't need `build` in most cases now that jest is configured to run the TS sources directly. 

This PR will also improve the time it takes to run the "Find Changes" job since it can ask jest for relevant files that changed without waiting for a build. This drops the time down from 2 minutes to 8 seconds.
2022-07-28 18:59:50 +00:00
Nathan Rajlich
4b025fee92 [node] Consider "browser" and "module" fields in package.json when tracing Edge Functions (#8262)
For Edge Functions, we are now considering the `"browser"` and `"module"` fields of packages to find the proper entrypoint. This PR updates `@vercel/node` to consider those same fields when using the node-file-trace tracing, so that the proper files get included in the output Edge Function.
2022-07-28 17:37:35 +00:00
Chris Barber
dc8293dc13 [cli] Add 'alias' command to help screen and alphabetize commands (#8256)
The `alias` command has been added to the `vercel --help` screen.

### Related Issues

> https://linear.app/vercel/issue/VCCLI-221/alias-command-missing-on-vc-h-help-screen

### 📋 Checklist

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-07-28 01:07:14 +00:00
Nathan Rajlich
78883dea23 [node] Remove .toString() in nft readFile() hook (#8263)
The nft `readFile()` hook accepts `Buffer` type so there's no reason to `.toString()` here.
2022-07-27 22:26:40 +00:00
Steven
b5b792e42f [tests] Update tests to run with vercel cli tarball (#8257)
This PR update the tests suite to wait for Vercel CLI tarball and then use that tarball to run E2E tests.

This is valuable because it will package all the packages in this monorepo to make the tests follow more closely what will happen in production once merged.

Since the current "Find Changes" step takes about 2 minutes, we run that first (it happens concurrently with the tarball preparation). Then once we complete "Find Changes" we wait for the tarball but it will likely be ready by that point since it also takes about 2 minutes. After both of those steps, the E2E tests continue as usual but with the `VERCEL_CLI_VERSION` set to the tarball.

- Related to #7967 
- Closes #8245 
- Closes #8227
2022-07-27 17:56:03 -04:00
Sean Massa
8993a3c4af [node] trim down values to only what is required for esbuild wrapping logic (#8260)
The edge runtime context we were providing was necessary to  have `ncc`-bundled code run, but after switching to `esbuild`, we didn't update this list.

This PR trims the values down to only what's necessary for `esbuild`-bundled code to run. It also adds comments about why these values are necessary.
2022-07-27 20:15:00 +00:00
Steven
57241aad81 [tests] Speed up vc tarball (#8261)
This updates the API that generates tarballs so that it doesn't need to generate tarballs for every Serverless Function and instead generates it one time. This cuts the time in half.
2022-07-27 19:41:48 +00:00
69 changed files with 2771 additions and 418 deletions

View File

@@ -17,6 +17,7 @@ jobs:
runs-on: ubuntu-latest
outputs:
tests: ${{ steps['set-tests'].outputs['tests'] }}
dplUrl: ${{ steps.waitForTarball.outputs.url }}
steps:
- uses: actions/checkout@v2
- run: git --version
@@ -32,6 +33,12 @@ jobs:
echo "Files to test:"
echo "$TESTS_ARRAY"
echo "::set-output name=tests::$TESTS_ARRAY"
- uses: patrickedqvist/wait-for-vercel-preview@ae34b392ef30297f2b672f9afb3c329bde9bd487
id: waitForTarball
with:
token: ${{ secrets.GITHUB_TOKEN }}
max_timeout: 360
check_interval: 5
test:
timeout-minutes: 120
@@ -69,13 +76,14 @@ jobs:
- run: yarn install --network-timeout 1000000
- name: Build ${{matrix.packageName}} and all its dependencies
run: yarn turbo run build --cache-dir=".turbo" --scope=${{matrix.packageName}} --include-dependencies --no-deps
run: node_modules/.bin/turbo run build --cache-dir=".turbo" --scope=${{matrix.packageName}} --include-dependencies --no-deps
env:
FORCE_COLOR: '1'
- name: Test ${{matrix.packageName}}
run: node_modules/.bin/turbo run test --cache-dir=".turbo" --scope=${{matrix.packageName}} --no-deps -- ${{ join(matrix.testPaths, ' ') }}
shell: bash
env:
VERCEL_CLI_VERSION: ${{ needs.setup.outputs.dplUrl }}/tarballs/vercel.tgz
VERCEL_TEAM_TOKEN: ${{ secrets.VERCEL_TEAM_TOKEN }}
VERCEL_REGISTRATION_URL: ${{ secrets.VERCEL_REGISTRATION_URL }}
FORCE_COLOR: '1'

View File

@@ -5,8 +5,7 @@
"description": "API for the vercel/vercel repo",
"main": "index.js",
"scripts": {
"//TODO": "We should add this pkg to yarn workspaces",
"vercel-build": "cd .. && yarn install && yarn vercel-build"
"//TODO": "We should add this pkg to yarn workspaces"
},
"dependencies": {
"@sentry/node": "5.11.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "5.0.5",
"version": "5.0.6",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",

View File

@@ -1,22 +1,12 @@
import path from 'path';
import fs from 'fs-extra';
import {
packAndDeploy,
testDeployment,
// @ts-ignore
} from '../../../test/lib/deployment/test-deployment';
jest.setTimeout(4 * 60 * 1000);
const builderUrl = '@canary';
let buildUtilsUrl: string;
beforeAll(async () => {
const buildUtilsPath = path.resolve(__dirname, '..');
buildUtilsUrl = await packAndDeploy(buildUtilsPath);
console.log('buildUtilsUrl', buildUtilsUrl);
});
const fixturesPath = path.resolve(__dirname, 'fixtures');
// Fixtures that have separate tests and should be skipped in the loop
@@ -42,10 +32,7 @@ for (const fixture of fs.readdirSync(fixturesPath)) {
// eslint-disable-next-line no-loop-func
it(`Should build "${fixture}"`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
)
testDeployment(path.join(fixturesPath, fixture))
).resolves.toBeDefined();
});
}
@@ -68,10 +55,7 @@ for (const builder of buildersToTestWith) {
// eslint-disable-next-line no-loop-func
it(`Should build "${builder}/${fixture}"`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath2, fixture)
)
testDeployment(path.join(fixturesPath2, fixture))
).resolves.toBeDefined();
});
}

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "27.3.0",
"version": "27.3.1",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -42,16 +42,16 @@
"node": ">= 14"
},
"dependencies": {
"@vercel/build-utils": "5.0.5",
"@vercel/go": "2.0.9",
"@vercel/hydrogen": "0.0.6",
"@vercel/next": "3.1.9",
"@vercel/node": "2.5.0",
"@vercel/python": "3.1.1",
"@vercel/redwood": "1.0.10",
"@vercel/remix": "1.0.11",
"@vercel/ruby": "1.3.17",
"@vercel/static-build": "1.0.10",
"@vercel/build-utils": "5.0.6",
"@vercel/go": "2.0.10",
"@vercel/hydrogen": "0.0.7",
"@vercel/next": "3.1.10",
"@vercel/node": "2.5.1",
"@vercel/python": "3.1.2",
"@vercel/redwood": "1.0.11",
"@vercel/remix": "1.0.12",
"@vercel/ruby": "1.3.18",
"@vercel/static-build": "1.0.11",
"update-notifier": "5.1.0"
},
"devDependencies": {
@@ -97,9 +97,9 @@
"@types/which": "1.3.2",
"@types/write-json-file": "2.2.1",
"@types/yauzl-promise": "2.1.0",
"@vercel/client": "12.1.4",
"@vercel/client": "12.1.5",
"@vercel/frameworks": "1.1.1",
"@vercel/fs-detectors": "2.0.1",
"@vercel/fs-detectors": "2.0.2",
"@vercel/fun": "1.0.4",
"@vercel/ncc": "0.34.0",
"@zeit/source-map-support": "0.6.2",

View File

@@ -16,26 +16,27 @@ export const help = () => `
dev Start a local development server
env Manages the Environment Variables for your current Project
git Manage Git provider repository for your current Project
help [cmd] Displays complete help for [cmd]
init [example] Initialize an example project
ls | list [app] Lists deployments
inspect [id] Displays information related to a deployment
link [path] Link local directory to a Vercel Project
ls | list [app] Lists deployments
login [email] Logs into your account or creates a new one
logout Logs out of your account
pull [path] Pull your Project Settings from the cloud
switch [scope] Switches between teams and your personal account
help [cmd] Displays complete help for [cmd]
${chalk.dim('Advanced')}
rm | remove [id] Removes a deployment
alias [cmd] Manages your domain aliases
bisect Use binary search to find the deployment that introduced a bug
domains [name] Manages your domain names
projects Manages your Projects
dns [name] Manages your DNS records
certs [cmd] Manages your SSL certificates
secrets [name] Manages your global Secrets, for use in Environment Variables
dns [name] Manages your DNS records
domains [name] Manages your domain names
logs [url] Displays the logs for a deployment
projects Manages your Projects
rm | remove [id] Removes a deployment
secrets [name] Manages your global Secrets, for use in Environment Variables
teams Manages your teams
whoami Shows the username of the currently logged in user

View File

@@ -0,0 +1,7 @@
{
"orgId": ".",
"projectId": ".",
"settings": {
"framework": null
}
}

View File

@@ -0,0 +1,9 @@
import describeYourself from '../packages/prefer-browser';
export const config = {
runtime: 'experimental-edge',
};
export default function () {
return new Response('response from "prefer-browser": ' + describeYourself());
}

View File

@@ -0,0 +1,9 @@
import describeYourself from '../packages/prefer-main';
export const config = {
runtime: 'experimental-edge',
};
export default function () {
return new Response('response from "prefer-main": ' + describeYourself());
}

View File

@@ -0,0 +1,9 @@
import describeYourself from '../packages/prefer-module';
export const config = {
runtime: 'experimental-edge',
};
export default function () {
return new Response('response from "prefer-module": ' + describeYourself());
}

View File

@@ -0,0 +1,9 @@
import describeYourself from '../packages/only-browser';
export const config = {
runtime: 'experimental-edge',
};
export default function () {
return new Response('response from "use-browser": ' + describeYourself());
}

View File

@@ -0,0 +1,9 @@
import describeYourself from '../packages/only-classic';
export const config = {
runtime: 'experimental-edge',
};
export default function () {
return new Response('response from "use-classic": ' + describeYourself());
}

View File

@@ -0,0 +1,9 @@
import describeYourself from '../packages/only-main';
export const config = {
runtime: 'experimental-edge',
};
export default function () {
return new Response('response from "use-main": ' + describeYourself());
}

View File

@@ -0,0 +1,9 @@
import describeYourself from '../packages/only-module';
export const config = {
runtime: 'experimental-edge',
};
export default function () {
return new Response('response from "use-module": ' + describeYourself());
}

View File

@@ -0,0 +1,3 @@
export default function () {
return 'only-browser';
}

View File

@@ -0,0 +1,5 @@
{
"name": "only-browser",
"private": true,
"browser": "dist-browser.js"
}

View File

@@ -0,0 +1,3 @@
export default function () {
return 'only-classic';
}

View File

@@ -0,0 +1,4 @@
{
"name": "only-classic",
"private": true
}

View File

@@ -0,0 +1,3 @@
export default function () {
return 'only-main';
}

View File

@@ -0,0 +1,5 @@
{
"name": "only-main",
"private": true,
"main": "dist-main.js"
}

View File

@@ -0,0 +1,3 @@
export default function () {
return 'only-module';
}

View File

@@ -0,0 +1,5 @@
{
"name": "only-module",
"private": true,
"module": "dist-module.js"
}

View File

@@ -0,0 +1,3 @@
export default function () {
return 'browser';
}

View File

@@ -0,0 +1,3 @@
export default function () {
return 'main';
}

View File

@@ -0,0 +1,3 @@
export default function () {
return 'module';
}

View File

@@ -0,0 +1,5 @@
// Should not be included in the output
export default function () {
return 'classic';
}

View File

@@ -0,0 +1,7 @@
{
"name": "only-module",
"private": true,
"main": "dist-main.js",
"module": "dist-module.js",
"browser": "dist-browser.js"
}

View File

@@ -0,0 +1,3 @@
export default function () {
return 'only-main';
}

View File

@@ -0,0 +1,5 @@
// Should not be included in the output
export default function () {
return 'classic';
}

View File

@@ -0,0 +1,5 @@
{
"name": "only-main",
"private": true,
"main": "dist-main.js"
}

View File

@@ -0,0 +1,3 @@
export default function () {
return 'main';
}

View File

@@ -0,0 +1,3 @@
export default function () {
return 'only-module';
}

View File

@@ -0,0 +1,5 @@
// Should not be included in the output
export default function () {
return 'classic';
}

View File

@@ -0,0 +1,6 @@
{
"name": "only-module",
"private": true,
"main": "dist-main.js",
"module": "dist-module.js"
}

View File

@@ -806,4 +806,119 @@ describe('build', () => {
delete process.env.__VERCEL_BUILD_RUNNING;
}
});
describe('should find packages with different main/module/browser keys', function () {
let output: string;
beforeAll(async function () {
const cwd = fixture('import-from-main-keys');
output = join(cwd, '.vercel/output');
process.chdir(cwd);
client.stderr.pipe(process.stderr);
const exitCode = await build(client);
expect(exitCode).toEqual(0);
const functions = await fs.readdir(join(output, 'functions/api'));
const sortedFunctions = functions.sort();
expect(sortedFunctions).toEqual([
'prefer-browser.func',
'prefer-main.func',
'prefer-module.func',
'use-browser.func',
'use-classic.func',
'use-main.func',
'use-module.func',
]);
});
afterAll(function () {
process.chdir(originalCwd);
delete process.env.__VERCEL_BUILD_RUNNING;
});
it('use-classic', async function () {
const packageDir = join(
output,
'functions/api',
'use-classic.func',
'packages',
'only-classic'
);
const packageDistFiles = await fs.readdir(packageDir);
expect(packageDistFiles).toContain('index.js');
});
it('use-main', async function () {
const packageDir = join(
output,
'functions/api',
'use-main.func',
'packages',
'only-main'
);
const packageDistFiles = await fs.readdir(packageDir);
expect(packageDistFiles).toContain('dist-main.js');
});
it('use-module', async function () {
const packageDir = join(
output,
'functions/api',
'use-module.func',
'packages',
'only-module'
);
const packageDistFiles = await fs.readdir(packageDir);
expect(packageDistFiles).toContain('dist-module.js');
});
it('use-browser', async function () {
const packageDir = join(
output,
'functions/api',
'use-browser.func',
'packages',
'only-browser'
);
const packageDistFiles = await fs.readdir(packageDir);
expect(packageDistFiles).toContain('dist-browser.js');
});
it('prefer-browser', async function () {
const packageDir = join(
output,
'functions/api',
'prefer-browser.func',
'packages',
'prefer-browser'
);
const packageDistFiles = await fs.readdir(packageDir);
expect(packageDistFiles).toContain('dist-browser.js');
});
it('prefer-main', async function () {
const packageDir = join(
output,
'functions/api',
'prefer-main.func',
'packages',
'prefer-main'
);
const packageDistFiles = await fs.readdir(packageDir);
expect(packageDistFiles).toContain('dist-main.js');
});
it('prefer-module', async function () {
const packageDir = join(
output,
'functions/api',
'prefer-module.func',
'packages',
'prefer-module'
);
const packageDistFiles = await fs.readdir(packageDir);
expect(packageDistFiles).toContain('dist-module.js');
});
});
});

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/client",
"version": "12.1.4",
"version": "12.1.5",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",
@@ -42,7 +42,7 @@
]
},
"dependencies": {
"@vercel/build-utils": "5.0.5",
"@vercel/build-utils": "5.0.6",
"@vercel/routing-utils": "2.0.0",
"@zeit/fetch": "5.2.0",
"async-retry": "1.2.3",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/fs-detectors",
"version": "2.0.1",
"version": "2.0.2",
"description": "Vercel filesystem detectors",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",

View File

@@ -5,22 +5,12 @@ import { detectBuilders } from '../src';
const fs = promises;
import {
packAndDeploy,
testDeployment,
// @ts-ignore
} from '../../../test/lib/deployment/test-deployment';
jest.setTimeout(4 * 60 * 1000);
const builderUrl = '@canary';
let buildUtilsUrl: string;
beforeAll(async () => {
const buildUtilsPath = path.resolve(__dirname, '..');
buildUtilsUrl = await packAndDeploy(buildUtilsPath);
console.log('buildUtilsUrl', buildUtilsUrl);
});
it('Test `detectBuilders` and `detectRoutes`', async () => {
const fixture = path.join(__dirname, 'fixtures', '01-zero-config-api');
const json = await fs.readFile(path.join(fixture, 'package.json'), 'utf8');
@@ -76,10 +66,7 @@ it('Test `detectBuilders` and `detectRoutes`', async () => {
JSON.stringify(nowConfig, null, 2)
);
const deployment = await testDeployment(
{ builderUrl, buildUtilsUrl },
fixture
);
const deployment = await testDeployment(fixture);
expect(deployment).toBeDefined();
});
@@ -158,9 +145,6 @@ it('Test `detectBuilders` with `index` files', async () => {
JSON.stringify(nowConfig, null, 2)
);
const deployment = await testDeployment(
{ builderUrl, buildUtilsUrl },
fixture
);
const deployment = await testDeployment(fixture);
expect(deployment).toBeDefined();
});

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/go",
"version": "2.0.9",
"version": "2.0.10",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
@@ -25,7 +25,7 @@
"@types/fs-extra": "^5.0.5",
"@types/node-fetch": "^2.3.0",
"@types/tar": "^4.0.0",
"@vercel/build-utils": "5.0.5",
"@vercel/build-utils": "5.0.6",
"@vercel/ncc": "0.34.0",
"async-retry": "1.3.1",
"execa": "^1.0.0",

View File

@@ -1,15 +1,8 @@
{
"version": 2,
"builds": [
{
"src": "api/v1/routes/**/*.go",
"use": "@vercel/go",
"config": { "zeroConfig": true }
}
],
"probes": [
{
"path": "/api/v1/routes/someroute.go",
"path": "/api/v1/routes/someroute",
"mustContain": "version:go1.13.15:Dependency:RANDOMNESS_PLACEHOLDER"
}
]

View File

@@ -2,24 +2,10 @@ const fs = require('fs');
const path = require('path');
const {
packAndDeploy,
testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(4 * 60 * 1000);
let buildUtilsUrl;
let builderUrl;
beforeAll(async () => {
if (!buildUtilsUrl) {
const buildUtilsPath = path.resolve(__dirname, '..', '..', 'build-utils');
buildUtilsUrl = await packAndDeploy(buildUtilsPath);
console.log('buildUtilsUrl', buildUtilsUrl);
}
const builderPath = path.resolve(__dirname, '..');
builderUrl = await packAndDeploy(builderPath);
console.log('builderUrl', builderUrl);
});
const skipFixtures = ['08-include-files'];
const fixturesPath = path.resolve(__dirname, 'fixtures');
@@ -33,10 +19,7 @@ for (const fixture of fs.readdirSync(fixturesPath)) {
// eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
)
testDeployment(path.join(fixturesPath, fixture))
).resolves.toBeDefined();
});
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/hydrogen",
"version": "0.0.6",
"version": "0.0.7",
"license": "MIT",
"main": "./dist/index.js",
"homepage": "https://vercel.com/docs",
@@ -22,7 +22,7 @@
"devDependencies": {
"@types/jest": "27.5.1",
"@types/node": "*",
"@vercel/build-utils": "5.0.5",
"@vercel/build-utils": "5.0.6",
"typescript": "4.6.4"
}
}

View File

@@ -1,23 +1,12 @@
const fs = require('fs');
const path = require('path');
const { version } = require('../package.json');
const {
packAndDeploy,
testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(12 * 60 * 1000);
let builderUrl;
const buildUtilsUrl = version.includes('canary') ? '@canary' : undefined;
beforeAll(async () => {
const builderPath = path.resolve(__dirname, '..');
builderUrl = await packAndDeploy(builderPath);
console.log('builderUrl', builderUrl);
});
const fixturesPath = path.resolve(__dirname, 'fixtures');
// eslint-disable-next-line no-restricted-syntax
@@ -25,10 +14,7 @@ for (const fixture of fs.readdirSync(fixturesPath)) {
// eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
)
testDeployment(path.join(fixturesPath, fixture))
).resolves.toBeDefined();
});
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/next",
"version": "3.1.9",
"version": "3.1.10",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
@@ -45,7 +45,7 @@
"@types/semver": "6.0.0",
"@types/text-table": "0.2.1",
"@types/webpack-sources": "3.2.0",
"@vercel/build-utils": "5.0.5",
"@vercel/build-utils": "5.0.6",
"@vercel/nft": "0.21.0",
"@vercel/routing-utils": "2.0.0",
"async-sema": "3.0.1",

View File

@@ -1,11 +1,7 @@
import type { Context, LoggerServer, Dictionary } from './types';
import type { IncomingMessage } from 'http';
import {
packAndDeploy,
testDeployment,
} from '../../../test/lib/deployment/test-deployment';
import { fetchTokenWithRetry } from '../../../test/lib/deployment/now-deploy';
import { testDeployment } from '../../../test/lib/deployment/test-deployment';
import fs from 'fs-extra';
import http from 'http';
@@ -72,56 +68,10 @@ export const createLoggerServer = async (): Promise<LoggerServer> => {
return { url, close, content };
};
let builderUrlPromise;
let builderUrlLastUpdated = 0;
const buildUtilsUrl = '@canary';
process.env.NEXT_TELEMETRY_DISABLED = '1';
export async function deployAndTest(fixtureDir) {
let builderInfo;
const builderInfoPath = path.join(__dirname, 'builder-info.json');
try {
builderInfo = await fs.readJSON(builderInfoPath);
} catch (_) {
/**/
}
let tempToken;
if (!builderUrlPromise && builderInfo) {
builderUrlPromise = Promise.resolve(builderInfo.builderUrl);
builderUrlLastUpdated = builderInfo.lastUpdated;
tempToken = builderInfo.tempToken;
}
const builderUrlIsStale = builderUrlLastUpdated < Date.now() - ms('25min');
if (!process.env.VERCEL_TOKEN && (builderUrlIsStale || !tempToken)) {
tempToken = await fetchTokenWithRetry();
}
process.env.TEMP_TOKEN = tempToken;
if (builderUrlIsStale) {
const builderPath = path.resolve(__dirname, '..');
builderUrlPromise = packAndDeploy(builderPath, false);
builderUrlLastUpdated = Date.now();
}
const builderUrl = await builderUrlPromise;
await fs.writeFile(
builderInfoPath,
JSON.stringify({
tempToken,
builderUrl,
lastUpdated: builderUrlLastUpdated,
})
);
const { deploymentId, deploymentUrl } = await testDeployment(
{ builderUrl, buildUtilsUrl },
fixtureDir
);
const { deploymentId, deploymentUrl } = await testDeployment(fixtureDir);
return {
deploymentId,

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/node",
"version": "2.5.0",
"version": "2.5.1",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
@@ -31,7 +31,7 @@
},
"dependencies": {
"@types/node": "*",
"@vercel/build-utils": "5.0.5",
"@vercel/build-utils": "5.0.6",
"@vercel/node-bridge": "3.0.0",
"@vercel/static-config": "2.0.1",
"edge-runtime": "1.0.1",

View File

@@ -245,10 +245,12 @@ async function createEdgeRuntime(params?: {
Object.assign(
context,
{
__dirname: '',
module: {
exports: {},
},
// This is required for esbuild wrapping logic to resolve
module: {},
// This is required for environment variable access.
// In production, env var access is provided by static analysis
// so that only the used values are available.
process: {
env: process.env,
},

View File

@@ -117,7 +117,8 @@ async function compile(
baseDir: string,
entrypointPath: string,
config: Config,
nodeVersion: NodeVersion
nodeVersion: NodeVersion,
isEdgeFunction: boolean
): Promise<{
preparedFiles: Files;
shouldAddSourcemapSupport: boolean;
@@ -195,30 +196,57 @@ async function compile(
ignore: config.excludeFiles,
async readFile(fsPath: string): Promise<Buffer | string | null> {
const relPath = relative(baseDir, fsPath);
// If this file has already been read then return from the cache
const cached = sourceCache.get(relPath);
if (cached) return cached.toString();
// null represents a not found
if (cached === null) return null;
if (typeof cached !== 'undefined') return cached;
try {
let entry: File | undefined;
let source: string | Buffer = readFileSync(fsPath);
const { mode } = lstatSync(fsPath);
if (isSymbolicLink(mode)) {
entry = new FileFsRef({ fsPath, mode });
}
if (isEdgeFunction && basename(fsPath) === 'package.json') {
// For Edge Functions, patch "main" field to prefer "browser" or "module"
const pkgJson = JSON.parse(source.toString());
for (const prop of ['browser', 'module']) {
const val = pkgJson[prop];
if (typeof val === 'string') {
debug(`Using "${prop}" field in ${fsPath}`);
pkgJson.main = val;
// Create the `entry` with the original so that the output is unmodified
if (!entry) {
entry = new FileBlob({ data: source, mode });
}
// Return the modified `package.json` to nft
source = JSON.stringify(pkgJson);
break;
}
}
}
if (
(fsPath.endsWith('.ts') && !fsPath.endsWith('.d.ts')) ||
fsPath.endsWith('.tsx')
) {
source = compileTypeScript(fsPath, source.toString());
}
const { mode } = lstatSync(fsPath);
let entry: File;
if (isSymbolicLink(mode)) {
entry = new FileFsRef({ fsPath, mode });
} else {
if (!entry) {
entry = new FileBlob({ data: source, mode });
}
fsCache.set(relPath, entry);
sourceCache.set(relPath, source);
return source.toString();
return source;
} catch (e) {
if (e.code === 'ENOENT' || e.code === 'EISDIR') {
// `null` represents a not found
sourceCache.set(relPath, null);
return null;
}
@@ -368,22 +396,6 @@ export const build: BuildV3 = async ({
spawnOpts
);
debug('Tracing input files...');
const traceTime = Date.now();
const { preparedFiles, shouldAddSourcemapSupport } = await compile(
workPath,
baseDir,
entrypointPath,
config,
nodeVersion
);
debug(`Trace complete [${Date.now() - traceTime}ms]`);
let routes: BuildResultV3['routes'];
let output: BuildResultV3['output'] | undefined;
const handler = renameTStoJS(relative(baseDir, entrypointPath));
const outputPath = entrypointToOutputPath(entrypoint, config.zeroConfig);
const isMiddleware = config.middleware === true;
// Will output an `EdgeFunction` for when `config.middleware = true`
@@ -404,6 +416,24 @@ export const build: BuildV3 = async ({
isEdgeFunction = staticConfig.runtime === 'experimental-edge';
}
debug('Tracing input files...');
const traceTime = Date.now();
const { preparedFiles, shouldAddSourcemapSupport } = await compile(
workPath,
baseDir,
entrypointPath,
config,
nodeVersion,
isEdgeFunction
);
debug(`Trace complete [${Date.now() - traceTime}ms]`);
let routes: BuildResultV3['routes'];
let output: BuildResultV3['output'] | undefined;
const handler = renameTStoJS(relative(baseDir, entrypointPath));
const outputPath = entrypointToOutputPath(entrypoint, config.zeroConfig);
// Add a `route` for Middleware
if (isMiddleware) {
if (!isEdgeFunction) {

View File

@@ -28,7 +28,7 @@ async function getScreenshot(url) {
module.exports = async (req, res) => {
const buffer = await getScreenshot('https://vercel.com/about');
if (buffer.length > 0) {
res.end('screenshot:RANDOMNESS_PLACEHOLDER');
res.end('/api/screenshot:RANDOMNESS_PLACEHOLDER');
} else {
res.end('buffer is empty');
}

View File

@@ -1,35 +0,0 @@
import chrome from 'chrome-aws-lambda';
import puppeteer from 'puppeteer-core';
import lighthouse from 'lighthouse';
import { URL } from 'url';
async function getOptions() {
const options = {
args: chrome.args,
executablePath: await chrome.executablePath,
headless: chrome.headless,
};
return options;
}
async function getResult(url) {
const options = await getOptions();
const browser = await puppeteer.launch(options);
const { port } = new URL(browser.wsEndpoint());
const result = await lighthouse(url, {
port,
output: 'html',
logLevel: 'error',
});
await browser.close();
return result;
}
module.exports = async (req, res) => {
const result = await getResult('https://vercel.com/docs');
if (req && result && result.lhr && result.lhr.categories) {
res.end('lighthouse:RANDOMNESS_PLACEHOLDER');
} else {
res.end('result is empty');
}
};

View File

@@ -1,4 +1,5 @@
{
"private": true,
"engines": {
"node": "14.x"
},

View File

@@ -9,7 +9,7 @@ async function tryTest({
retries = 4,
}) {
try {
const res = await fetch(`https://${deploymentUrl}/${testName}`);
const res = await fetch(`https://${deploymentUrl}${testName}`);
assert.equal(res.status, 200);
const text = await res.text();
assert.equal(text.trim(), `${testName}:${randomness}`);
@@ -32,6 +32,10 @@ async function tryTest({
}
module.exports = async ({ deploymentUrl, fetch, randomness }) => {
await tryTest({ testName: 'lighthouse', deploymentUrl, fetch, randomness });
await tryTest({ testName: 'screenshot', deploymentUrl, fetch, randomness });
await tryTest({
testName: '/api/screenshot',
deploymentUrl,
fetch,
randomness,
});
};

View File

@@ -1,17 +1,8 @@
{
"version": 2,
"builds": [
{
"src": "**/*.js",
"use": "@vercel/node",
"config": {
"functions": {
"**/*.js": {
"memory": 3008,
"maxDuration": 30
}
}
}
"functions": {
"api/**/*.js": {
"memory": 1024,
"maxDuration": 10
}
]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +1,14 @@
const fs = require('fs');
const path = require('path');
const ms = require('ms');
const { version } = require('../package.json');
const { intoChunks, NUMBER_OF_CHUNKS } = require('../../../utils/chunk-tests');
const {
packAndDeploy,
testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(12 * 60 * 1000);
module.exports = function setupTests(groupIndex) {
let builderUrl;
let builderUrlLastUpdated = 0;
const buildUtilsUrl = version.includes('canary') ? '@canary' : undefined;
beforeEach(async () => {
if (builderUrlLastUpdated < Date.now() - ms('30min')) {
const builderPath = path.resolve(__dirname, '..');
builderUrl = await packAndDeploy(builderPath);
builderUrlLastUpdated = Date.now();
console.log('builderUrl', builderUrl);
}
});
const fixturesPath = path.resolve(__dirname, 'fixtures');
const testsThatFailToBuild = new Map([
[
@@ -48,10 +32,7 @@ module.exports = function setupTests(groupIndex) {
// eslint-disable-next-line no-loop-func
it(`should fail to build ${fixture}`, async () => {
try {
await testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
);
await testDeployment(path.join(fixturesPath, fixture));
} catch (err) {
expect(err).toBeTruthy();
expect(err.deployment).toBeTruthy();
@@ -62,10 +43,7 @@ module.exports = function setupTests(groupIndex) {
}
it(`should build ${fixture}`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
)
testDeployment(path.join(fixturesPath, fixture))
).resolves.toBeDefined();
});
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/python",
"version": "3.1.1",
"version": "3.1.2",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
@@ -23,7 +23,7 @@
"devDependencies": {
"@types/execa": "^0.9.0",
"@types/jest": "27.4.1",
"@vercel/build-utils": "5.0.5",
"@vercel/build-utils": "5.0.6",
"@vercel/ncc": "0.34.0",
"execa": "^1.0.0",
"typescript": "4.3.4"

View File

@@ -6,19 +6,10 @@ const execa = require('execa');
const { spawn } = require('child_process');
const {
packAndDeploy,
testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(4 * 60 * 1000);
const buildUtilsUrl = '@canary';
let builderUrl: string;
beforeAll(async () => {
const builderPath = path.resolve(__dirname, '..');
builderUrl = await packAndDeploy(builderPath);
console.log('builderUrl', builderUrl);
});
const fixturesPath = path.resolve(__dirname, 'fixtures');
@@ -85,10 +76,7 @@ for (const fixture of fs.readdirSync(fixturesPath)) {
// eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
)
testDeployment(path.join(fixturesPath, fixture))
).resolves.toBeDefined();
});
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/redwood",
"version": "1.0.10",
"version": "1.0.11",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://vercel.com/docs",
@@ -28,6 +28,6 @@
"@types/aws-lambda": "8.10.19",
"@types/node": "*",
"@types/semver": "6.0.0",
"@vercel/build-utils": "5.0.5"
"@vercel/build-utils": "5.0.6"
}
}

View File

@@ -2,26 +2,11 @@ const fs = require('fs');
const path = require('path');
const {
packAndDeploy,
testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(12 * 60 * 1000);
let buildUtilsUrl;
let builderUrl;
beforeAll(async () => {
if (!buildUtilsUrl) {
const buildUtilsPath = path.resolve(__dirname, '..', '..', 'build-utils');
buildUtilsUrl = await packAndDeploy(buildUtilsPath);
console.log('buildUtilsUrl', buildUtilsUrl);
}
const builderPath = path.resolve(__dirname, '..');
builderUrl = await packAndDeploy(builderPath);
console.log('builderUrl', builderUrl);
});
const fixturesPath = path.resolve(__dirname, 'fixtures');
// eslint-disable-next-line no-restricted-syntax
@@ -29,10 +14,7 @@ for (const fixture of fs.readdirSync(fixturesPath)) {
// eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
)
testDeployment(path.join(fixturesPath, fixture))
).resolves.toBeDefined();
});
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/remix",
"version": "1.0.11",
"version": "1.0.12",
"license": "MIT",
"main": "./dist/index.js",
"homepage": "https://vercel.com/docs",
@@ -26,7 +26,7 @@
"devDependencies": {
"@types/jest": "27.5.1",
"@types/node": "*",
"@vercel/build-utils": "5.0.5",
"@vercel/build-utils": "5.0.6",
"typescript": "4.6.4"
}
}

View File

@@ -1,23 +1,12 @@
const fs = require('fs');
const path = require('path');
const { version } = require('../package.json');
const {
packAndDeploy,
testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(12 * 60 * 1000);
let builderUrl;
const buildUtilsUrl = version.includes('canary') ? '@canary' : undefined;
beforeAll(async () => {
const builderPath = path.resolve(__dirname, '..');
builderUrl = await packAndDeploy(builderPath);
console.log('builderUrl', builderUrl);
});
const fixturesPath = path.resolve(__dirname, 'fixtures');
// eslint-disable-next-line no-restricted-syntax
@@ -25,10 +14,7 @@ for (const fixture of fs.readdirSync(fixturesPath)) {
// eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
)
testDeployment(path.join(fixturesPath, fixture))
).resolves.toBeDefined();
});
}

View File

@@ -1,7 +1,7 @@
{
"name": "@vercel/ruby",
"author": "Nathan Cahill <nathan@nathancahill.com>",
"version": "1.3.17",
"version": "1.3.18",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/ruby",
@@ -23,7 +23,7 @@
"devDependencies": {
"@types/fs-extra": "8.0.0",
"@types/semver": "6.0.0",
"@vercel/build-utils": "5.0.5",
"@vercel/build-utils": "5.0.6",
"@vercel/ncc": "0.34.0",
"execa": "2.0.4",
"fs-extra": "^7.0.1",

View File

@@ -2,24 +2,10 @@ const fs = require('fs');
const path = require('path');
const {
packAndDeploy,
testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(5 * 60 * 1000);
let buildUtilsUrl;
let builderUrl;
beforeAll(async () => {
if (!buildUtilsUrl) {
const buildUtilsPath = path.resolve(__dirname, '..', '..', 'build-utils');
buildUtilsUrl = await packAndDeploy(buildUtilsPath);
console.log('buildUtilsUrl', buildUtilsUrl);
}
const builderPath = path.resolve(__dirname, '..');
builderUrl = await packAndDeploy(builderPath);
console.log('builderUrl', builderUrl);
});
const fixturesPath = path.resolve(__dirname, 'fixtures');
@@ -37,10 +23,7 @@ for (const fixture of fs.readdirSync(fixturesPath)) {
// eslint-disable-next-line no-loop-func
it(`should fail to build ${fixture}`, async () => {
try {
await testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
);
await testDeployment(path.join(fixturesPath, fixture));
} catch (err) {
expect(err).toBeTruthy();
expect(err.deployment).toBeTruthy();
@@ -52,10 +35,7 @@ for (const fixture of fs.readdirSync(fixturesPath)) {
// eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
)
testDeployment(path.join(fixturesPath, fixture))
).resolves.toBeDefined();
});
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/static-build",
"version": "1.0.10",
"version": "1.0.11",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/build-step",
@@ -37,7 +37,7 @@
"@types/ms": "0.7.31",
"@types/node-fetch": "2.5.4",
"@types/promise-timeout": "1.3.0",
"@vercel/build-utils": "5.0.5",
"@vercel/build-utils": "5.0.6",
"@vercel/frameworks": "1.1.1",
"@vercel/ncc": "0.34.0",
"@vercel/routing-utils": "2.0.0",

View File

@@ -1,30 +1,14 @@
const fs = require('fs');
const path = require('path');
const ms = require('ms');
const { version } = require('../package.json');
const { intoChunks, NUMBER_OF_CHUNKS } = require('../../../utils/chunk-tests');
const {
packAndDeploy,
testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(12 * 60 * 1000);
module.exports = function setupTests(groupIndex) {
let builderUrl;
let builderUrlLastUpdated = 0;
const buildUtilsUrl = version.includes('canary') ? '@canary' : undefined;
beforeEach(async () => {
if (builderUrlLastUpdated < Date.now() - ms('30min')) {
const builderPath = path.resolve(__dirname, '..');
builderUrl = await packAndDeploy(builderPath);
builderUrlLastUpdated = Date.now();
console.log('builderUrl', builderUrl);
}
});
const fixturesPath = path.resolve(__dirname, 'fixtures');
const testsThatFailToBuild = new Map([
[
@@ -61,10 +45,7 @@ module.exports = function setupTests(groupIndex) {
// eslint-disable-next-line no-loop-func
it(`should fail to build ${fixture}`, async () => {
try {
await testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
);
await testDeployment(path.join(fixturesPath, fixture));
} catch (err) {
expect(err).toBeTruthy();
expect(err.deployment).toBeTruthy();
@@ -75,10 +56,7 @@ module.exports = function setupTests(groupIndex) {
}
it(`should build ${fixture}`, async () => {
await expect(
testDeployment(
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
)
testDeployment(path.join(fixturesPath, fixture))
).resolves.toBeDefined();
});
}

View File

@@ -33,6 +33,8 @@ async function nowDeploy(bodies, randomness, uploadNowJson) {
process.env;
const nowJson = JSON.parse(bodies['vercel.json'] || bodies['now.json']);
delete nowJson.probes;
const nowDeployPayload = {
version: 2,
public: true,
@@ -50,16 +52,10 @@ async function nowDeploy(bodies, randomness, uploadNowJson) {
},
name: 'test2020',
files,
builds: nowJson.builds,
meta: {},
...nowJson,
};
for (const field of ['routes', 'rewrites', 'headers', 'redirects']) {
if (nowJson[field]) {
nowDeployPayload[field] = nowJson[field];
}
}
logWithinTest(`posting ${files.length} files`);
for (const { file: filename } of files) {
@@ -146,7 +142,7 @@ async function filePost(body, digest) {
}
async function deploymentPost(payload) {
const url = '/v6/now/deployments?forceNew=1';
const url = '/v13/deployments?skipAutoDetectionConfirmation=1&forceNew=1';
const resp = await fetchWithAuth(url, {
method: 'POST',
body: JSON.stringify(payload),
@@ -164,7 +160,7 @@ async function deploymentPost(payload) {
}
async function deploymentGet(deploymentId) {
const url = `/v12/now/deployments/${deploymentId}`;
const url = `/v13/deployments/${deploymentId}`;
logWithinTest('fetching deployment', url);
const resp = await fetchWithAuth(url);
const json = await resp.json();

View File

@@ -264,11 +264,7 @@ async function runProbe(probe, deploymentId, deploymentUrl, ctx) {
assert(hadTest, 'probe must have a test condition');
}
async function testDeployment(
{ builderUrl, buildUtilsUrl },
fixturePath,
buildDelegate
) {
async function testDeployment(fixturePath, buildDelegate) {
logWithinTest('testDeployment', fixturePath);
const globResult = await glob(`${fixturePath}/**`, {
nodir: true,
@@ -321,24 +317,6 @@ async function testDeployment(
});
for (const build of nowJson.builds || []) {
if (builderUrl) {
if (builderUrl === '@canary') {
build.use = `${build.use}@canary`;
} else {
build.use = `https://${builderUrl}`;
}
}
if (buildUtilsUrl) {
build.config = build.config || {};
const { config } = build;
if (buildUtilsUrl === '@canary') {
const buildUtils = config.useBuildUtils || '@vercel/build-utils';
config.useBuildUtils = `${buildUtils}@canary`;
} else {
config.useBuildUtils = `https://${buildUtilsUrl}`;
}
}
if (buildDelegate) {
buildDelegate(build);
}

View File

@@ -20,27 +20,27 @@
]
},
"test-unit": {
"dependsOn": ["build"],
"dependsOn": [],
"outputs": []
},
"test-integration-dev": {
"dependsOn": ["build"],
"dependsOn": [],
"outputs": []
},
"test-integration-cli": {
"dependsOn": ["build"],
"dependsOn": [],
"outputs": []
},
"test-integration-once": {
"dependsOn": ["build"],
"dependsOn": [],
"outputs": []
},
"test-next-local": {
"dependsOn": ["build"],
"dependsOn": [],
"outputs": []
},
"test": {
"dependsOn": ["build"],
"dependsOn": [],
"outputs": []
}
}

15
utils/chunk-tests.js vendored
View File

@@ -81,16 +81,19 @@ async function getChunkedTests() {
return chunkedTests;
}
/**
* Run turbo cli
* @param {string[]} args
*/
async function turbo(args) {
const chunks = [];
try {
await new Promise((resolve, reject) => {
const spawned = child_process.spawn(`yarn`, ['turbo', '--', ...args], {
cwd: path.resolve(__dirname, '..'),
env: {
...process.env,
YARN_SILENT: '1',
},
const root = path.resolve(__dirname, '..');
const turbo = path.join(root, 'node_modules', '.bin', 'turbo');
const spawned = child_process.spawn(turbo, args, {
cwd: root,
env: process.env,
});
spawned.stdout.on('data', data => {
chunks.push(data);