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

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,26 +16,27 @@ export const help = () => `
dev Start a local development server dev Start a local development server
env Manages the Environment Variables for your current Project env Manages the Environment Variables for your current Project
git Manage Git provider repository 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 init [example] Initialize an example project
ls | list [app] Lists deployments
inspect [id] Displays information related to a deployment inspect [id] Displays information related to a deployment
link [path] Link local directory to a Vercel Project 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 login [email] Logs into your account or creates a new one
logout Logs out of your account logout Logs out of your account
pull [path] Pull your Project Settings from the cloud pull [path] Pull your Project Settings from the cloud
switch [scope] Switches between teams and your personal account switch [scope] Switches between teams and your personal account
help [cmd] Displays complete help for [cmd]
${chalk.dim('Advanced')} ${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 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 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 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 teams Manages your teams
whoami Shows the username of the currently logged in user 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; 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", "name": "@vercel/client",
"version": "12.1.4", "version": "12.1.5",
"main": "dist/index.js", "main": "dist/index.js",
"typings": "dist/index.d.ts", "typings": "dist/index.d.ts",
"homepage": "https://vercel.com", "homepage": "https://vercel.com",
@@ -42,7 +42,7 @@
] ]
}, },
"dependencies": { "dependencies": {
"@vercel/build-utils": "5.0.5", "@vercel/build-utils": "5.0.6",
"@vercel/routing-utils": "2.0.0", "@vercel/routing-utils": "2.0.0",
"@zeit/fetch": "5.2.0", "@zeit/fetch": "5.2.0",
"async-retry": "1.2.3", "async-retry": "1.2.3",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,23 +1,12 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const { version } = require('../package.json');
const { const {
packAndDeploy,
testDeployment, testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js'); } = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(12 * 60 * 1000); 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'); const fixturesPath = path.resolve(__dirname, 'fixtures');
// eslint-disable-next-line no-restricted-syntax // 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 // eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => { it(`should build ${fixture}`, async () => {
await expect( await expect(
testDeployment( testDeployment(path.join(fixturesPath, fixture))
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
)
).resolves.toBeDefined(); ).resolves.toBeDefined();
}); });
} }

View File

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

View File

@@ -1,11 +1,7 @@
import type { Context, LoggerServer, Dictionary } from './types'; import type { Context, LoggerServer, Dictionary } from './types';
import type { IncomingMessage } from 'http'; import type { IncomingMessage } from 'http';
import { import { testDeployment } from '../../../test/lib/deployment/test-deployment';
packAndDeploy,
testDeployment,
} from '../../../test/lib/deployment/test-deployment';
import { fetchTokenWithRetry } from '../../../test/lib/deployment/now-deploy';
import fs from 'fs-extra'; import fs from 'fs-extra';
import http from 'http'; import http from 'http';
@@ -72,56 +68,10 @@ export const createLoggerServer = async (): Promise<LoggerServer> => {
return { url, close, content }; return { url, close, content };
}; };
let builderUrlPromise;
let builderUrlLastUpdated = 0;
const buildUtilsUrl = '@canary';
process.env.NEXT_TELEMETRY_DISABLED = '1'; process.env.NEXT_TELEMETRY_DISABLED = '1';
export async function deployAndTest(fixtureDir) { export async function deployAndTest(fixtureDir) {
let builderInfo; const { deploymentId, deploymentUrl } = await testDeployment(fixtureDir);
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
);
return { return {
deploymentId, deploymentId,

View File

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

View File

@@ -245,10 +245,12 @@ async function createEdgeRuntime(params?: {
Object.assign( Object.assign(
context, context,
{ {
__dirname: '', // This is required for esbuild wrapping logic to resolve
module: { module: {},
exports: {},
}, // 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: { process: {
env: process.env, env: process.env,
}, },

View File

@@ -117,7 +117,8 @@ async function compile(
baseDir: string, baseDir: string,
entrypointPath: string, entrypointPath: string,
config: Config, config: Config,
nodeVersion: NodeVersion nodeVersion: NodeVersion,
isEdgeFunction: boolean
): Promise<{ ): Promise<{
preparedFiles: Files; preparedFiles: Files;
shouldAddSourcemapSupport: boolean; shouldAddSourcemapSupport: boolean;
@@ -195,30 +196,57 @@ async function compile(
ignore: config.excludeFiles, ignore: config.excludeFiles,
async readFile(fsPath: string): Promise<Buffer | string | null> { async readFile(fsPath: string): Promise<Buffer | string | null> {
const relPath = relative(baseDir, fsPath); const relPath = relative(baseDir, fsPath);
// If this file has already been read then return from the cache
const cached = sourceCache.get(relPath); const cached = sourceCache.get(relPath);
if (cached) return cached.toString(); if (typeof cached !== 'undefined') return cached;
// null represents a not found
if (cached === null) return null;
try { try {
let entry: File | undefined;
let source: string | Buffer = readFileSync(fsPath); 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 ( if (
(fsPath.endsWith('.ts') && !fsPath.endsWith('.d.ts')) || (fsPath.endsWith('.ts') && !fsPath.endsWith('.d.ts')) ||
fsPath.endsWith('.tsx') fsPath.endsWith('.tsx')
) { ) {
source = compileTypeScript(fsPath, source.toString()); source = compileTypeScript(fsPath, source.toString());
} }
const { mode } = lstatSync(fsPath);
let entry: File; if (!entry) {
if (isSymbolicLink(mode)) {
entry = new FileFsRef({ fsPath, mode });
} else {
entry = new FileBlob({ data: source, mode }); entry = new FileBlob({ data: source, mode });
} }
fsCache.set(relPath, entry); fsCache.set(relPath, entry);
sourceCache.set(relPath, source); sourceCache.set(relPath, source);
return source.toString(); return source;
} catch (e) { } catch (e) {
if (e.code === 'ENOENT' || e.code === 'EISDIR') { if (e.code === 'ENOENT' || e.code === 'EISDIR') {
// `null` represents a not found
sourceCache.set(relPath, null); sourceCache.set(relPath, null);
return null; return null;
} }
@@ -368,22 +396,6 @@ export const build: BuildV3 = async ({
spawnOpts 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; const isMiddleware = config.middleware === true;
// Will output an `EdgeFunction` for when `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'; 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 // Add a `route` for Middleware
if (isMiddleware) { if (isMiddleware) {
if (!isEdgeFunction) { if (!isEdgeFunction) {

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/redwood", "name": "@vercel/redwood",
"version": "1.0.10", "version": "1.0.11",
"main": "./dist/index.js", "main": "./dist/index.js",
"license": "MIT", "license": "MIT",
"homepage": "https://vercel.com/docs", "homepage": "https://vercel.com/docs",
@@ -28,6 +28,6 @@
"@types/aws-lambda": "8.10.19", "@types/aws-lambda": "8.10.19",
"@types/node": "*", "@types/node": "*",
"@types/semver": "6.0.0", "@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 path = require('path');
const { const {
packAndDeploy,
testDeployment, testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js'); } = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(12 * 60 * 1000); 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'); const fixturesPath = path.resolve(__dirname, 'fixtures');
// eslint-disable-next-line no-restricted-syntax // 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 // eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => { it(`should build ${fixture}`, async () => {
await expect( await expect(
testDeployment( testDeployment(path.join(fixturesPath, fixture))
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
)
).resolves.toBeDefined(); ).resolves.toBeDefined();
}); });
} }

View File

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

View File

@@ -1,23 +1,12 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const { version } = require('../package.json');
const { const {
packAndDeploy,
testDeployment, testDeployment,
} = require('../../../test/lib/deployment/test-deployment.js'); } = require('../../../test/lib/deployment/test-deployment.js');
jest.setTimeout(12 * 60 * 1000); 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'); const fixturesPath = path.resolve(__dirname, 'fixtures');
// eslint-disable-next-line no-restricted-syntax // 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 // eslint-disable-next-line no-loop-func
it(`should build ${fixture}`, async () => { it(`should build ${fixture}`, async () => {
await expect( await expect(
testDeployment( testDeployment(path.join(fixturesPath, fixture))
{ builderUrl, buildUtilsUrl },
path.join(fixturesPath, fixture)
)
).resolves.toBeDefined(); ).resolves.toBeDefined();
}); });
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -33,6 +33,8 @@ async function nowDeploy(bodies, randomness, uploadNowJson) {
process.env; process.env;
const nowJson = JSON.parse(bodies['vercel.json'] || bodies['now.json']); const nowJson = JSON.parse(bodies['vercel.json'] || bodies['now.json']);
delete nowJson.probes;
const nowDeployPayload = { const nowDeployPayload = {
version: 2, version: 2,
public: true, public: true,
@@ -50,16 +52,10 @@ async function nowDeploy(bodies, randomness, uploadNowJson) {
}, },
name: 'test2020', name: 'test2020',
files, files,
builds: nowJson.builds,
meta: {}, meta: {},
...nowJson,
}; };
for (const field of ['routes', 'rewrites', 'headers', 'redirects']) {
if (nowJson[field]) {
nowDeployPayload[field] = nowJson[field];
}
}
logWithinTest(`posting ${files.length} files`); logWithinTest(`posting ${files.length} files`);
for (const { file: filename } of files) { for (const { file: filename } of files) {
@@ -146,7 +142,7 @@ async function filePost(body, digest) {
} }
async function deploymentPost(payload) { async function deploymentPost(payload) {
const url = '/v6/now/deployments?forceNew=1'; const url = '/v13/deployments?skipAutoDetectionConfirmation=1&forceNew=1';
const resp = await fetchWithAuth(url, { const resp = await fetchWithAuth(url, {
method: 'POST', method: 'POST',
body: JSON.stringify(payload), body: JSON.stringify(payload),
@@ -164,7 +160,7 @@ async function deploymentPost(payload) {
} }
async function deploymentGet(deploymentId) { async function deploymentGet(deploymentId) {
const url = `/v12/now/deployments/${deploymentId}`; const url = `/v13/deployments/${deploymentId}`;
logWithinTest('fetching deployment', url); logWithinTest('fetching deployment', url);
const resp = await fetchWithAuth(url); const resp = await fetchWithAuth(url);
const json = await resp.json(); 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'); assert(hadTest, 'probe must have a test condition');
} }
async function testDeployment( async function testDeployment(fixturePath, buildDelegate) {
{ builderUrl, buildUtilsUrl },
fixturePath,
buildDelegate
) {
logWithinTest('testDeployment', fixturePath); logWithinTest('testDeployment', fixturePath);
const globResult = await glob(`${fixturePath}/**`, { const globResult = await glob(`${fixturePath}/**`, {
nodir: true, nodir: true,
@@ -321,24 +317,6 @@ async function testDeployment(
}); });
for (const build of nowJson.builds || []) { 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) { if (buildDelegate) {
buildDelegate(build); buildDelegate(build);
} }

View File

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

15
utils/chunk-tests.js vendored
View File

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