Compare commits

..

19 Commits

Author SHA1 Message Date
Vercel Release Bot
f39513118a Version Packages (#11413)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## vercel@34.0.0

### Major Changes

- Disables promotion of preview deployments
([#11411](https://github.com/vercel/vercel/pull/11411))

### Patch Changes

- Always set `projectSettings.nodeVersion` in `vc deploy`
([#11351](https://github.com/vercel/vercel/pull/11351))

- [cli] optional override of existing environment variables with --force
([#11348](https://github.com/vercel/vercel/pull/11348))

## @vercel/client@13.2.0

### Minor Changes

- Always use v13 of create deployment API endpoint
([#11351](https://github.com/vercel/vercel/pull/11351))

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-11 08:59:24 -05:00
Nathan Rajlich
fd188a396b [tests] Use vercel-deno for "custom-runtime" dev fixture (#11405)
This is related #11133. This `custom-runtime` tests is failing on that branch since the "macos-14" test runner uses arm64 processor, and the `static-binaries` "import" package that the "vercel-bash" runtime is using does not have binaries for arm64. Switch this test fixture to use "vercel-deno" instead, which won't have this problem.
2024-04-11 01:49:13 +00:00
Jeff See
cdfc879f69 Specify npm script to run during Find Changes step (#11409)
Add a new vitest-unit test type and specify which npm script to run for a given chunks tests. Currently the CLI unit tests are actually running as part of the Find Changes action, because vitest ignores the `--listTests` flag and just runs the tests immediately.
2024-04-11 00:26:58 +00:00
Nathan Rajlich
b58dcc5733 [remix] Add custom entry.server for Vite test (#11408)
Adds an e2e test fixture which tests that a custom `app/entry.server` file is supported.

Related to:

* https://github.com/vercel/remix/pull/85
* https://github.com/vercel/remix/pull/89
2024-04-10 23:53:49 +00:00
Sean Massa
cddf3fa00c Revert "[cli] Revert "Disallow promoting preview deployments to production (#11363)"" (#11411)
Reverts vercel/vercel#11410 to reinstate #11363
2024-04-10 22:15:33 +00:00
Nathan Rajlich
627b79fb14 [client] Always use v13 of create deployment API endpoint (#11351)
Updates `@vercel/client` to always use the v13 create-deployment endpoint, even when `builds` is present. This allows for `projectSettings.nodeVersion` to be passed when `builds` is present.
2024-04-10 20:55:28 +00:00
Mountain/\Ash
7259a324c2 [cli] optional override of existing environment variables (#11348)
## Why

Closes #11130

## Changelog

Added `--force` argument to upsert existing environment variables (#11130)

## References

- Vercel API `/v10/projects/{idOrName}/env` https://vercel.com/docs/rest-api/endpoints/projects#create-one-or-more-environment-variables
2024-04-10 20:13:53 +00:00
Nathan Rajlich
1aab599652 Version Packages (#11395)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.

- Add support for edge function environment variables
([#11390](https://github.com/vercel/vercel/pull/11390))

- fix flickering during interactive UI rerendering
([#11392](https://github.com/vercel/vercel/pull/11392))

- fix `vc ls` message to be `vc projects ls`
([#11400](https://github.com/vercel/vercel/pull/11400))

- Updated dependencies
\[[`2461b571a`](2461b571af)]:
    -   @vercel/next@4.2.0
2024-04-10 12:43:42 -07:00
Florentin / 珞辰
2461b571af [next] use middleware manifest worker environments (#11390)
This PR adds changes to the Next.js builder to pass the per-worker environment emitted from the Next.js middleware manifest to the created `EdgeFunction` resource.
2024-04-10 08:27:53 +00:00
Nathan Rajlich
1088bf2dea [cli] Revert "Disallow promoting preview deployments to production (#11363)" (#11410)
This reverts commit 4e416d7d7b.

It was erroneously merged by Kodiak with failing unit tests.
2024-04-10 07:03:12 +00:00
Austin Merrick
c5bd242a79 [cli] Fix command recommendation (#11400)
`vc rm <project-name-that-doesn't-exist>` gives the message:
<img width="749" alt="Screenshot 2024-04-08 at 2 38 03 PM" src="https://github.com/vercel/vercel/assets/8485687/e041d47e-ce66-434b-838b-3693eb6cc4a7">

`vc ls` is not correct. `vc projects ls` is the correct command.
2024-04-09 22:15:54 +00:00
Vercel Release Bot
764ba97967 [tests] Upgrade Turbo to version 1.13.2 (#11398)
This auto-generated PR updates Turbo to version 1.13.2
2024-04-09 22:12:37 +00:00
Trek Glowacki
4e416d7d7b [cli] Disallow promoting preview deployments to production (#11363)
Blocks preview deployments from being directly promoted. This relies on a new API version bump.

Copied the warning text from the UI:
![CleanShot 2024-04-01 at 11 04 00@2x](https://github.com/vercel/vercel/assets/9736/4e93ffdd-32f2-40bc-97e7-6fe98208cd76)

This is a breaking change and will require a major version bump. Please don't merge until we're ready.
2024-04-09 22:02:29 +00:00
findseat
8775ff3fcf chore: fix some typos (#11397) 2024-04-09 20:51:35 +00:00
Nathan Rajlich
bd100baa16 [tests] Fix tarball URL from deleted project (#11403)
I did some pruning of old projects on my personal account last night, and accidentally broke CI. I've created a new tarball on the `curated-tests` team so that it doesn't happen again.
2024-04-09 19:56:47 +00:00
Austin Merrick
2e6aab01cb [cli] Unify table formatting output (#11387)
This removes 'text-table' as a dependency in favor of using 'cli-table3', and simplifies table formatting logic.
2024-04-09 07:33:04 +00:00
Nathan Rajlich
3e57c4a2de [tests] Remove disableSSO() function (#11380)
The SSO Protection feature is now turned off by default for testing accounts. So this manual logic for disabling the feature on each project test fixture is no longer necessary.
2024-04-06 07:47:56 +00:00
Austin Merrick
0c3d136414 [cli] Fix flickering during UI re-rendering (#11392)
Various UI components would flicker upon re-rendering in unoptimized terminals as OSX's stock terminal app. This change bumps these components to include [this fix](https://github.com/SBoudrias/Inquirer.js/pull/1379).

## Before
https://github.com/vercel/vercel/assets/8485687/352ce43e-9a01-4290-a4c8-8826aebf859a

## After
https://github.com/vercel/vercel/assets/8485687/9e2eb071-0f7c-4d5a-adf6-735b30bcc294
2024-04-05 22:13:37 +00:00
Jeff See
238d6db17a Fix name for integration test (#11393)
I think this was a copy/paste typo from https://github.com/vercel/vercel/pull/11243
2024-04-05 21:50:27 +00:00
71 changed files with 8572 additions and 600 deletions

View File

@@ -85,7 +85,7 @@ jobs:
env:
FORCE_COLOR: '1'
- name: Test ${{matrix.packageName}}
run: node utils/gen.js && node_modules/.bin/turbo run test --summarize --cache-dir=".turbo" --log-order=stream --scope=${{matrix.packageName}} --no-deps -- ${{ join(matrix.testPaths, ' ') }}
run: node utils/gen.js && node_modules/.bin/turbo run ${{matrix.testScript}} --summarize --cache-dir=".turbo" --log-order=stream --scope=${{matrix.packageName}} --no-deps -- ${{ join(matrix.testPaths, ' ') }}
shell: bash
env:
JEST_JUNIT_OUTPUT_FILE: ${{github.workspace}}/.junit-reports/${{matrix.scriptName}}-${{matrix.packageName}}-${{matrix.chunkNumber}}-${{ matrix.runner }}.xml

View File

@@ -50,4 +50,4 @@ Ensure any segments used in the `destination` property are also used in the `sou
- [path-to-regexp](https://github.com/pillarjs/path-to-regexp/tree/v6.1.0)
- [named parameters](https://github.com/pillarjs/path-to-regexp/blob/v6.1.0/Readme.md#named-parameters)
- [un-named paramters](https://github.com/pillarjs/path-to-regexp/blob/v6.1.0/Readme.md#unnamed-parameters)
- [un-named parameters](https://github.com/pillarjs/path-to-regexp/blob/v6.1.0/Readme.md#unnamed-parameters)

View File

@@ -33,7 +33,7 @@
"source-map-support": "0.5.12",
"ts-eager": "2.0.2",
"ts-jest": "29.1.0",
"turbo": "1.13.0",
"turbo": "1.13.2",
"typescript": "4.9.5"
},
"scripts": {

View File

@@ -1,5 +1,28 @@
# vercel
## 34.0.0
### Major Changes
- Disables promotion of preview deployments ([#11411](https://github.com/vercel/vercel/pull/11411))
### Patch Changes
- Always set `projectSettings.nodeVersion` in `vc deploy` ([#11351](https://github.com/vercel/vercel/pull/11351))
- [cli] optional override of existing environment variables with --force ([#11348](https://github.com/vercel/vercel/pull/11348))
## 33.7.1
### Patch Changes
- fix flickering during interactive UI rerendering ([#11392](https://github.com/vercel/vercel/pull/11392))
- fix `vc ls` message to be `vc projects ls` ([#11400](https://github.com/vercel/vercel/pull/11400))
- Updated dependencies [[`2461b571a`](https://github.com/vercel/vercel/commit/2461b571af037fbfdf92299a272010a5a8f4898b)]:
- @vercel/next@4.2.0
## 33.7.0
### Minor Changes

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "33.7.0",
"version": "34.0.0",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -12,7 +12,8 @@
},
"scripts": {
"test": "jest --reporters=default --reporters=jest-junit --env node --verbose --bail",
"test-unit": "pnpm vitest test/unit/",
"vitest-unit-run": "pnpm vitest",
"vitest-unit": "pnpm jest test/unit/ --listTests",
"test-e2e": "rimraf test/fixtures/integration && pnpm test test/integration-1.test.ts test/integration-2.test.ts test/integration-3.test.ts",
"test-dev": "pnpm test test/dev/",
"coverage": "codecov",
@@ -35,7 +36,7 @@
"@vercel/fun": "1.1.0",
"@vercel/go": "3.1.1",
"@vercel/hydrogen": "1.0.2",
"@vercel/next": "4.1.6",
"@vercel/next": "4.2.0",
"@vercel/node": "3.0.26",
"@vercel/python": "4.1.1",
"@vercel/redwood": "2.0.8",
@@ -47,11 +48,11 @@
"devDependencies": {
"@alex_neo/jest-expect-message": "1.0.5",
"@edge-runtime/node-utils": "2.3.0",
"@inquirer/checkbox": "2.2.0",
"@inquirer/confirm": "3.1.0",
"@inquirer/expand": "2.1.0",
"@inquirer/input": "2.1.1",
"@inquirer/select": "2.2.0",
"@inquirer/checkbox": "2.2.2",
"@inquirer/confirm": "3.1.2",
"@inquirer/expand": "2.1.2",
"@inquirer/input": "2.1.2",
"@inquirer/select": "2.2.2",
"@next/env": "11.1.2",
"@sentry/node": "5.5.0",
"@sindresorhus/slugify": "0.11.0",
@@ -83,7 +84,6 @@
"@types/qs": "6.9.7",
"@types/semver": "6.0.1",
"@types/tar-fs": "1.16.1",
"@types/text-table": "0.2.0",
"@types/title": "3.4.1",
"@types/universal-analytics": "0.4.2",
"@types/update-notifier": "5.1.0",
@@ -93,7 +93,7 @@
"@vercel-internals/constants": "1.0.4",
"@vercel-internals/get-package-json": "1.0.0",
"@vercel-internals/types": "1.0.29",
"@vercel/client": "13.1.9",
"@vercel/client": "13.2.0",
"@vercel/error-utils": "2.0.2",
"@vercel/frameworks": "3.0.1",
"@vercel/fs-detectors": "5.2.2",
@@ -162,7 +162,6 @@
"strip-ansi": "6.0.1",
"supports-hyperlinks": "3.0.0",
"tar-fs": "1.16.3",
"text-table": "0.2.0",
"title": "3.4.1",
"tmp-promise": "1.0.3",
"tree-kill": "1.2.2",

View File

@@ -1,6 +1,6 @@
import chalk from 'chalk';
import ms from 'ms';
import table from 'text-table';
import table from '../../util/output/table';
import Client from '../../util/client';
import getAliases from '../../util/alias/get-aliases';
import getScope from '../../util/get-scope';
@@ -9,7 +9,6 @@ import {
getPaginationOpts,
} from '../../util/get-pagination-opts';
import stamp from '../../util/output/stamp';
import strlen from '../../util/strlen';
import getCommandFlags from '../../util/get-command-flags';
import { getCommandName } from '../../util/pkg-name';
import type { Alias } from '@vercel-internals/types';
@@ -78,10 +77,6 @@ function printAliasTable(aliases: Alias[]) {
ms(Date.now() - a.createdAt),
]),
],
{
align: ['l', 'l', 'r'],
hsep: ' '.repeat(4),
stringLength: strlen,
}
{ align: ['l', 'l', 'r'], hsep: 4 }
).replace(/^/gm, ' ')}\n\n`;
}

View File

@@ -1,11 +1,10 @@
import chalk from 'chalk';
import ms from 'ms';
import table from 'text-table';
import table from '../../util/output/table';
import Client from '../../util/client';
import getScope from '../../util/get-scope';
import removeAliasById from '../../util/alias/remove-alias-by-id';
import stamp from '../../util/output/stamp';
import strlen from '../../util/strlen';
import confirm from '../../util/input/confirm';
import findAliasByAliasOrId from '../../util/alias/find-alias-by-alias-or-id';
@@ -84,11 +83,7 @@ async function confirmAliasRemove(client: Client, alias: Alias) {
chalk.gray(`${ms(Date.now() - alias.createdAt)} ago`),
],
],
{
align: ['l', 'l', 'r'],
hsep: ' '.repeat(4),
stringLength: strlen,
}
{ hsep: 4 }
);
client.output.log(`The following alias will be removed permanently`);

View File

@@ -1,6 +1,6 @@
import chalk from 'chalk';
import ms from 'ms';
import table from 'text-table';
import table from '../../util/output/table';
import Client from '../../util/client';
import getScope from '../../util/get-scope';
import {
@@ -9,7 +9,6 @@ import {
} from '../../util/get-pagination-opts';
import stamp from '../../util/output/stamp';
import getCerts from '../../util/certs/get-certs';
import strlen from '../../util/strlen';
import type { Cert } from '@vercel-internals/types';
import getCommandFlags from '../../util/get-command-flags';
import { getCommandName } from '../../util/pkg-name';
@@ -70,11 +69,7 @@ async function ls(
function formatCertsTable(certsList: Cert[]) {
return `${table(
[formatCertsTableHead(), ...formatCertsTableBody(certsList)],
{
align: ['l', 'l', 'r', 'c', 'r'],
hsep: ' '.repeat(2),
stringLength: strlen,
}
{ align: ['l', 'l', 'r', 'c', 'r'], hsep: 2 }
).replace(/^(.*)/gm, ' $1')}\n`;
}

View File

@@ -1,7 +1,7 @@
import chalk from 'chalk';
import ms from 'ms';
import plural from 'pluralize';
import table from 'text-table';
import table from '../../util/output/table';
import type { Cert } from '@vercel-internals/types';
import * as ERRORS from '../../util/errors-ts';
import { Output } from '../../util/output';
@@ -98,7 +98,7 @@ function readConfirmation(output: Output, msg: string, certs: Cert[]) {
output.print(
`${table(certs.map(formatCertRow), {
align: ['l', 'r', 'l'],
hsep: ' '.repeat(6),
hsep: 6,
}).replace(/^(.*)/gm, ' $1')}\n`
);
output.print(

View File

@@ -520,23 +520,6 @@ export default async (client: Client): Promise<number> => {
);
}
const { packageJson } = await scanParentDirs(
join(cwd, project?.rootDirectory ?? ''),
true,
cwd
);
let nodeVersion: string | undefined;
if (packageJson?.engines?.node) {
try {
const { range } = await getSupportedNodeVersion(packageJson.engines.node);
nodeVersion = range;
} catch (error) {
if (error instanceof Error) {
output.warn(error.message);
}
}
}
try {
// if this flag is not set, use `undefined` to allow the project setting to be used
const autoAssignCustomDomains = argv['--skip-domain'] ? false : undefined;
@@ -573,7 +556,6 @@ export default async (client: Client): Promise<number> => {
createArgs.projectSettings = {
sourceFilesOutsideRootDirectory,
rootDirectory,
nodeVersion,
};
if (status === 'linked') {
@@ -584,6 +566,30 @@ export default async (client: Client): Promise<number> => {
}
}
// Read the `engines.node` field from `package.json` and send as a
// `projectSettings` property as an optimization (so that the API
// does not need to retrieve the file to do this check).
const { packageJson } = await scanParentDirs(
join(cwd, project?.rootDirectory ?? ''),
true,
cwd
);
let nodeVersion: string | undefined;
if (packageJson?.engines?.node) {
try {
const { range } = await getSupportedNodeVersion(
packageJson.engines.node
);
nodeVersion = range;
} catch (error) {
if (error instanceof Error) {
output.warn(error.message);
}
}
}
if (!createArgs.projectSettings) createArgs.projectSettings = {};
createArgs.projectSettings.nodeVersion = nodeVersion;
deployment = await createDeploy(
client,
now,

View File

@@ -1,6 +1,6 @@
import chalk from 'chalk';
import ms from 'ms';
import table from 'text-table';
import table from '../../util/output/table';
import type { DNSRecord } from '@vercel-internals/types';
import { Output } from '../../util/output';
import Client from '../../util/client';
@@ -71,7 +71,7 @@ function readConfirmation(
output.print(
`${table([getDeleteTableRow(domainName, record)], {
align: ['l', 'r', 'l'],
hsep: ' '.repeat(6),
hsep: 6,
}).replace(/^(.*)/gm, ' $1')}\n`
);
output.print(

View File

@@ -20,6 +20,7 @@ import { isAPIError } from '../../util/errors-ts';
type Options = {
'--debug': boolean;
'--sensitive': boolean;
'--force': boolean;
};
export default async function add(
@@ -81,7 +82,7 @@ export default async function add(
);
const choices = envTargetChoices.filter(c => !existing.has(c.value));
if (choices.length === 0) {
if (choices.length === 0 && !opts['--force']) {
output.error(
`The variable ${param(
envName
@@ -125,6 +126,7 @@ export default async function add(
}
const type = opts['--sensitive'] ? 'sensitive' : 'encrypted';
const upsert = opts['--force'] ? 'true' : '';
const addStamp = stamp();
try {
@@ -133,6 +135,7 @@ export default async function add(
output,
client,
project.id,
upsert,
type,
envName,
envValue,
@@ -149,9 +152,11 @@ export default async function add(
output.print(
`${prependEmoji(
`Added Environment Variable ${chalk.bold(
envName
)} to Project ${chalk.bold(project.name)} ${chalk.gray(addStamp())}`,
`${
opts['--force'] ? 'Overrode' : 'Added'
} Environment Variable ${chalk.bold(envName)} to Project ${chalk.bold(
project.name
)} ${chalk.gray(addStamp())}`,
emoji('success')
)}\n`
);

View File

@@ -43,6 +43,14 @@ export const envCommand: Command = {
deprecated: false,
multi: false,
},
{
name: 'force',
description: 'Force overwrites when a command would normally fail',
shorthand: null,
type: 'boolean',
deprecated: false,
multi: false,
},
],
examples: [],
},
@@ -126,6 +134,10 @@ export const envCommand: Command = {
`${packageName} env add DB_PASS production`,
],
},
{
name: 'Override an existing Environment Variable of same target (production, preview, deployment)',
value: `${packageName} env add API_TOKEN --force`,
},
{
name: 'Add a sensitive Environment Variable',
value: `${packageName} env add API_TOKEN --sensitive`,

View File

@@ -35,6 +35,7 @@ export default async function main(client: Client) {
'--environment': String,
'--git-branch': String,
'--sensitive': Boolean,
'--force': Boolean,
});
} catch (error) {
handleError(error);

View File

@@ -1,6 +1,7 @@
import chalk from 'chalk';
import { LOGO, NAME } from '@vercel-internals/constants';
import Table, { CellOptions } from 'cli-table3';
import { noBorderChars } from '../util/output/table';
const INDENT = ' '.repeat(2);
const NEWLINE = '\n';
@@ -39,23 +40,7 @@ type _CellOptions = CellOptions & {
};
const tableOptions = {
chars: {
top: '',
'top-mid': '',
'top-left': '',
'top-right': '',
bottom: '',
'bottom-mid': '',
'bottom-left': '',
'bottom-right': '',
left: '',
'left-mid': '',
mid: '',
'mid-mid': '',
right: '',
'right-mid': '',
middle: '',
},
chars: noBorderChars,
style: {
'padding-left': 0,
'padding-right': 0,

View File

@@ -1,12 +1,11 @@
import chalk from 'chalk';
import ms from 'ms';
import table from 'text-table';
import table from '../../util/output/table';
import title from 'title';
import Now from '../../util';
import getArgs from '../../util/get-args';
import { handleError } from '../../util/error';
import elapsed from '../../util/output/elapsed';
import strlen from '../../util/strlen';
import toHost from '../../util/to-host';
import parseMeta from '../../util/parse-meta';
import { isValidName } from '../../util/is-valid-name';
@@ -275,11 +274,7 @@ export default async function list(client: Client) {
app === null ? filterUniqueApps() : () => true
),
],
{
align: ['l', 'l', 'l', 'l', 'l'],
hsep: ' '.repeat(5),
stringLength: strlen,
}
{ hsep: 5 }
).replace(/^/gm, ' ')}\n\n`
);

View File

@@ -1,11 +1,10 @@
import chalk from 'chalk';
import ms from 'ms';
import table from 'text-table';
import table from '../../util/output/table';
import type { Project } from '@vercel-internals/types';
import Client from '../../util/client';
import getCommandFlags from '../../util/get-command-flags';
import { getCommandName } from '../../util/pkg-name';
import strlen from '../../util/strlen';
import { NODE_VERSIONS } from '@vercel/build-utils';
export default async function list(
@@ -100,11 +99,7 @@ export default async function list(
])
.flat(),
],
{
align: ['l', 'l', 'l'],
hsep: ' '.repeat(3),
stringLength: strlen,
}
{ hsep: 3 }
).replace(/^/gm, ' ');
output.print(`\n${tablePrint}\n\n`);

View File

@@ -32,15 +32,9 @@ export default async function requestPromote({
output: client.output,
});
if (deployment.target !== 'production') {
output.warn(
'Promoting a preview deployment to production is deprecated and will be removed in the next major release. This behavior will be removed entirely on 2024-05-03.'
);
}
if (deployment.target !== 'production' && !yes) {
const question =
'This deployment does not target production, therefore promotion will not apply production environment variables. Are you sure you want to continue?';
'This deployment is not a production deployment and cannot be directly promoted. A new deployment will be built using your production environment. Are you sure you want to continue?';
const answer = await confirm(client, question, false);
if (!answer) {
output.error('Canceled');
@@ -49,7 +43,7 @@ export default async function requestPromote({
}
// request the promotion
await client.fetch(`/v9/projects/${project.id}/promote/${deployment.id}`, {
await client.fetch(`/v10/projects/${project.id}/promote/${deployment.id}`, {
body: {}, // required
json: false,
method: 'POST',

View File

@@ -1,7 +1,7 @@
import chalk from 'chalk';
import ms from 'ms';
import plural from 'pluralize';
import table from 'text-table';
import table from '../../util/output/table';
import Now from '../../util';
import getAliases from '../../util/alias/get-aliases';
import elapsed from '../../util/output/elapsed';
@@ -169,7 +169,7 @@ export default async function remove(client: Client) {
`or projects matching ` +
`${ids
.map(id => chalk.bold(`"${id}"`))
.join(', ')}. Run ${getCommandName('ls')} to list.`
.join(', ')}. Run ${getCommandName('projects ls')} to list.`
);
return 1;
}
@@ -245,7 +245,7 @@ function readConfirmation(
const url = depl.url ? chalk.underline(`https://${depl.url}`) : '';
return [` ${depl.id}`, url, time];
}),
{ align: ['l', 'r', 'l'], hsep: ' '.repeat(6) }
{ align: ['l', 'r', 'l'], hsep: 6 }
);
output.print(`${deploymentTable}\n`);
}

View File

@@ -1,8 +1,7 @@
import isErrnoException from '@vercel/error-utils';
import chalk from 'chalk';
import table from 'text-table';
import table from '../../util/output/table';
import ms from 'ms';
import strlen from '../../util/strlen';
import { handleError, error } from '../../util/error';
import NowSecrets from '../../util/secrets';
import getScope from '../../util/get-scope';
@@ -124,11 +123,7 @@ async function run({ output, contextName, currentTeam, client }) {
chalk.gray(`${ms(cur - new Date(secret.created))} ago`),
])
),
{
align: ['l', 'l', 'l'],
hsep: ' '.repeat(2),
stringLength: strlen,
}
{ hsep: 2 }
);
if (out) {
@@ -285,7 +280,7 @@ async function readConfirmation(client, output, secret, contextName) {
const time = chalk.gray(`${ms(new Date() - new Date(secret.created))} ago`);
const tbl = table([[chalk.bold(secret.name), time]], {
align: ['r', 'l'],
hsep: ' '.repeat(6),
hsep: 6,
});
output.print(

View File

@@ -1,5 +1,6 @@
import chars from '../../util/output/chars';
import table from '../../util/output/table';
import { gray } from 'chalk';
import getUser from '../../util/get-user';
import getTeams from '../../util/teams/get-teams';
import { packageName } from '../../util/pkg-name';
@@ -53,7 +54,7 @@ export default async function list(client: Client): Promise<number> {
id,
name,
value: slug,
current: id === currentTeam ? chars.tick : '',
prefix: id === currentTeam ? chars.tick : ' ',
}));
if (user.version !== 'northstar') {
@@ -61,7 +62,7 @@ export default async function list(client: Client): Promise<number> {
id: user.id,
name: user.email,
value: user.username || user.email,
current: accountIsCurrent ? chars.tick : '',
prefix: accountIsCurrent ? chars.tick : ' ',
});
}
@@ -76,14 +77,22 @@ export default async function list(client: Client): Promise<number> {
output.stopSpinner();
client.stdout.write('\n'); // empty line
table(
['', 'id', 'email / name'],
teamList.map(team => [team.current, team.value, team.name]),
[1, 5],
(str: string) => {
client.stdout.write(str);
}
const teamTable = table(
[
['id', 'email / name'].map(str => gray(str)),
...teamList.map(team => [team.value, team.name]),
],
{ hsep: 5 }
);
client.stderr.write(
currentTeam
? teamTable
.split('\n')
.map((line, i) => `${i > 0 ? teamList[i - 1].prefix : ' '} ${line}`)
.join('\n')
: teamTable
);
client.stderr.write('\n');
if (pagination?.count === 20) {
const flags = getCommandFlags(argv, ['_', '--next', '-N', '-d']);

View File

@@ -10,14 +10,16 @@ export default async function addEnvRecord(
output: Output,
client: Client,
projectId: string,
upsert: string,
type: ProjectEnvType,
key: string,
value: string,
targets: ProjectEnvTarget[],
gitBranch: string
): Promise<void> {
const actionWord = upsert ? 'Overriding' : 'Adding';
output.debug(
`Adding ${type} Environment Variable ${key} to ${targets.length} targets`
`${actionWord} ${type} Environment Variable ${key} to ${targets.length} targets`
);
const body: Omit<ProjectEnvVariable, 'id'> = {
type,
@@ -26,7 +28,8 @@ export default async function addEnvRecord(
target: targets,
gitBranch: gitBranch || undefined,
};
const url = `/v8/projects/${projectId}/env`;
const args = upsert ? `?upsert=${upsert}` : '';
const url = `/v10/projects/${projectId}/env${args}`;
await client.fetch(url, {
method: 'POST',
body,

View File

@@ -48,7 +48,7 @@ export default async function getEnvRecords(
query.set('source', source);
}
const url = `/v8/projects/${projectId}/env?${query}`;
const url = `/v10/projects/${projectId}/env?${query}`;
return client.fetch<{ envs: ProjectEnvVariable[] }>(url);
}

View File

@@ -1,12 +1,34 @@
import { isErrnoException } from '@vercel/error-utils';
const knownErrorsCodes = new Set([
'PAYMENT_REQUIRED',
'BAD_REQUEST',
'SYSTEM_ENV_WITH_VALUE',
'RESERVED_ENV_VARIABLE',
'ENV_ALREADY_EXISTS',
'ENV_CONFLICT',
'ENV_SHOULD_BE_A_SECRET',
'EXISTING_KEY_AND_TARGET',
'FORBIDDEN',
'ID_NOT_FOUND',
'INVALID_KEY',
'INVALID_VALUE',
'KEY_INVALID_CHARACTERS',
'KEY_INVALID_LENGTH',
'KEY_RESERVED',
'RESERVED_ENV_VARIABLE',
'MAX_ENVS_EXCEEDED',
'MISSING_ID',
'MISSING_KEY',
'MISSING_TARGET',
'MISSING_VALUE',
'NOT_AUTHORIZED',
'NOT_DECRYPTABLE',
'SECRET_MISSING',
'SYSTEM_ENV_WITH_VALUE',
'TEAM_NOT_FOUND',
'TOO_MANY_IDS',
'TOO_MANY_KEYS',
'UNKNOWN_ERROR',
'VALUE_INVALID_LENGTH',
'VALUE_INVALID_TYPE',
]);
export function isKnownError(error: unknown) {

View File

@@ -10,9 +10,9 @@ export default async function removeEnvRecord(
): Promise<void> {
output.debug(`Removing Environment Variable ${env.key}`);
const urlProject = `/v8/projects/${projectId}/env/${env.id}`;
const url = `/v10/projects/${projectId}/env/${env.id}`;
await client.fetch<ProjectEnvVariable>(urlProject, {
await client.fetch<ProjectEnvVariable>(url, {
method: 'DELETE',
});
}

View File

@@ -1,16 +1,8 @@
import chalk from 'chalk';
import table from 'text-table';
import strlen from './strlen';
import table from './output/table';
import { gray } from 'chalk';
const HEADER = ['name', 'type', 'value'].map(v => chalk.gray(v));
const HEADER = ['name', 'type', 'value'].map(v => gray(v));
export default function formatDNSTable(
rows: string[][],
{ extraSpace = '' } = {}
) {
return table([HEADER, ...rows], {
align: ['l', 'l', 'l'],
hsep: ' '.repeat(8),
stringLength: strlen,
}).replace(/^(.*)/gm, `${extraSpace}$1`);
export default function formatDNSTable(rows: string[][]) {
return table([HEADER, ...rows], { hsep: 8 });
}

View File

@@ -1,6 +1,5 @@
import chalk from 'chalk';
import table from 'text-table';
import strlen from './strlen';
import table from './output/table';
import chars from './output/chars';
export default function formatNSTable(
@@ -35,10 +34,6 @@ export default function formatNSTable(
],
...rows,
],
{
align: ['l', 'l', 'l', 'l'],
hsep: ' '.repeat(4),
stringLength: strlen,
}
{ hsep: 4 }
).replace(/^(.*)/gm, `${extraSpace}$1`);
}

View File

@@ -1,5 +1,5 @@
import chalk from 'chalk';
import table from 'text-table';
import table from './output/table';
import strlen from './strlen';
// header:
@@ -19,9 +19,8 @@ import strlen from './strlen';
// ]
export default function formatTable(
header: string[],
align: Array<'l' | 'r' | 'c' | '.'>,
blocks: { name?: string; rows: string[][] }[],
hsep = ' '
align: Array<'l' | 'r' | 'c'>,
blocks: { name?: string; rows: string[][] }[]
) {
const nrCols = header.length;
const padding = [];
@@ -57,7 +56,7 @@ export default function formatTable(
rows[i][j] = al === 'l' ? col + pad : pad + col;
}
}
out += table(rows, { align, hsep, stringLength: strlen });
out += table(rows, { align, hsep: 4 });
}
out += '\n\n';
}

View File

@@ -1,38 +1,52 @@
import chalk from 'chalk';
import Table from 'cli-table3';
const printLine = (data: string[], sizes: number[]) =>
data.reduce((line, col, i) => line + col.padEnd(sizes[i]), '');
const defaultStyle = {
'padding-left': 0,
'padding-right': 2,
};
export const noBorderChars = {
top: '',
'top-mid': '',
'top-left': '',
'top-right': '',
bottom: '',
'bottom-mid': '',
'bottom-left': '',
'bottom-right': '',
left: '',
'left-mid': '',
mid: '',
'mid-mid': '',
right: '',
'right-mid': '',
middle: '',
};
const alignMap = {
l: 'left',
c: 'center',
r: 'right',
} as const;
/**
* Print a table.
*/
export default function table(
fieldNames: string[] = [],
data: string[][] = [],
margins: number[] = [],
print: (str: string) => void
rows: string[][],
opts?: { hsep?: number; align?: ('l' | 'c' | 'r')[] }
) {
// Compute size of each column
const sizes = data
.reduce(
(acc, row) =>
row.map((col, i) => {
const currentMaxColSize = acc[i] || 0;
const colSize = (col && col.length) || 0;
return Math.max(currentMaxColSize, colSize);
}),
fieldNames.map(col => col.length)
const table = new Table({
style: {
...defaultStyle,
'padding-right': opts?.hsep ?? defaultStyle['padding-right'],
},
chars: noBorderChars,
});
table.push(
...rows.map(row =>
row.map((cell, i) => ({
content: cell,
hAlign: alignMap[opts?.align?.[i] ?? 'l'],
}))
)
// Add margin to all columns except the last
.map((size, i) => (i < margins.length && size + margins[i]) || size);
// Print header
print(chalk.grey(printLine(fieldNames, sizes)));
print('\n');
// Print content
for (const row of data) {
print(printLine(row, sizes));
print('\n');
}
);
return table.toString();
}

View File

@@ -1,3 +0,0 @@
handler() {
echo "Hello, from Bash!"
}

View File

@@ -0,0 +1,3 @@
export default (req: Request) => {
return new Response('Hello, from Deno!');
}

View File

@@ -1,6 +0,0 @@
{
"private": true,
"engines": {
"node": "16.x"
}
}

View File

@@ -1,7 +1,7 @@
{
"functions": {
"api/user.sh": {
"runtime": "vercel-bash@3.0.8"
"api/user.ts": {
"runtime": "vercel-deno@3.1.0"
}
}
}

View File

@@ -1,3 +1,4 @@
import execa from 'execa';
import { isIP } from 'net';
const { exec, fixture, testFixture, testFixtureStdio } = require('./utils.js');
@@ -125,13 +126,24 @@ test(
})
);
test(
'[vercel dev] Use custom runtime from the "functions" property',
testFixtureStdio('custom-runtime', async (testPath: any) => {
await testPath(200, `/api/user`, /Hello, from Bash!/m);
await testPath(200, `/api/user.sh`, /Hello, from Bash!/m);
})
);
test('[vercel dev] Use custom runtime from the "functions" property', async () => {
const origPATH = process.env.PATH;
try {
// "deno" needs to be installed for this test
await execa('curl -fsSL https://deno.land/install.sh | sh', {
stdio: 'inherit',
shell: true,
});
process.env.PATH = `${process.env.HOME}/.deno/bin:${origPATH}`;
const tester = testFixtureStdio('custom-runtime', async (testPath: any) => {
await testPath(200, `/api/user`, /Hello, from Deno!/m);
await testPath(200, `/api/user.ts`, /Hello, from Deno!/m);
});
await tester();
} finally {
process.env.PATH = origPATH;
}
});
test(
'[vercel dev] Should work with nested `tsconfig.json` files',

View File

@@ -7,7 +7,6 @@ const { satisfies } = require('semver');
const stripAnsi = require('strip-ansi');
const {
fetchCachedToken,
disableSSO,
} = require('../../../../test/lib/deployment/now-deploy');
const { spawnSync, execFileSync } = require('child_process');
@@ -399,9 +398,6 @@ function testFixtureStdio(
// Expect the deploy succeeded with exit of 0;
expect(deployResult.exitCode).toBe(0);
deploymentUrl = new URL(deployResult.stdout).host;
// Disable the Project SSO Protection
await disableSSO(deployResult.stdout, true);
} finally {
if (!hasGitignore) {
await fs.remove(gitignore);

View File

@@ -0,0 +1,4 @@
{
"orgId": "team_dummy",
"projectId": "legacy-builds"
}

View File

@@ -0,0 +1 @@
module.exports = (req, res) => res.end('Vercel');

View File

@@ -0,0 +1,8 @@
{
"name": "node",
"version": "1.0.0",
"private": true,
"engines": {
"node": "18.x"
}
}

View File

@@ -0,0 +1,5 @@
{
"builds": [
{ "src": "index.js", "use": "@vercel/node" }
]
}

View File

@@ -405,6 +405,9 @@ module.exports = async function prepare(session, binaryPath, tmpFixturesDir) {
'project-sensitive-env-vars': {
'package.json': '{}',
},
'project-override-env-vars': {
'package.json': '{}',
},
'dev-proxy-headers-and-env': {
'package.json': JSON.stringify({}),
'server.js': `require('http').createServer((req, res) => {

View File

@@ -5,10 +5,7 @@ import fetch, { RequestInit } from 'node-fetch';
import retry from 'async-retry';
import fs from 'fs-extra';
import sleep from '../src/util/sleep';
import {
disableSSO,
fetchTokenWithRetry,
} from '../../../test/lib/deployment/now-deploy';
import { fetchTokenWithRetry } from '../../../test/lib/deployment/now-deploy';
import waitForPrompt from './helpers/wait-for-prompt';
import { listTmpDirs } from './helpers/get-tmp-dir';
import getGlobalDir from './helpers/get-global-dir';
@@ -405,7 +402,6 @@ test('default command should work with --cwd option', async () => {
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
const url = stdout;
await disableSSO(url, false);
const deploymentResult = await fetch(`${url}/README.md`);
const body = await deploymentResult.text();
@@ -435,7 +431,6 @@ test('should allow deploying a directory that was built with a target environmen
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
const url = stdout;
await disableSSO(url, false);
const deploymentResult = await fetch(`${url}/README.md`);
const body = await deploymentResult.text();
@@ -463,7 +458,6 @@ test('should allow deploying a directory that was prebuilt, but has no builds.js
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
const url = stdout;
await disableSSO(url, false);
const deploymentResult = await fetch(`${url}/README.md`);
const body = await deploymentResult.text();
@@ -527,7 +521,6 @@ test('deploy using only now.json with `redirects` defined', async () => {
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
const url = stdout;
await disableSSO(url, false);
const res = await fetch(`${url}/foo/bar`, { redirect: 'manual' });
const location = res.headers.get('location');
expect(location).toBe('https://example.com/foo/bar');
@@ -549,7 +542,6 @@ test('deploy using --local-config flag v2', async () => {
const { host } = new URL(stdout);
expect(host).toMatch(/secondary/gm);
await disableSSO(host, false);
const testRes = await fetch(`https://${host}/test-${contextName}.html`);
const testText = await testRes.text();
@@ -585,7 +577,7 @@ test('deploy fails using --local-config flag with non-existent path', async () =
expect(stderr).toMatch(/does-not-exist\.json/);
});
test('deploy using --local-config flag above target', async () => {
test('deploy from a nested directory', async () => {
const root = await setupE2EFixture('zero-config-next-js-nested');
const projectName = `project-link-dev-${
Math.random().toString(36).split('.')[1]
@@ -631,7 +623,6 @@ test('deploy using --local-config flag above target', async () => {
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
const { host } = new URL(stdout);
await disableSSO(host, false);
const testRes = await fetch(`https://${host}/index.html`);
const testText = await testRes.text();
@@ -853,7 +844,6 @@ test('Deploy `api-env` fixture and test `vercel env` command', async () => {
});
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
const { host } = new URL(stdout);
await disableSSO(host, false);
const apiUrl = `https://${host}/api/get-env`;
const apiRes = await fetch(apiUrl);

View File

@@ -11,10 +11,7 @@ import fs, {
mkdir,
} from 'fs-extra';
import sleep from '../src/util/sleep';
import {
disableSSO,
fetchTokenWithRetry,
} from '../../../test/lib/deployment/now-deploy';
import { fetchTokenWithRetry } from '../../../test/lib/deployment/now-deploy';
import waitForPrompt from './helpers/wait-for-prompt';
import { execCli } from './helpers/exec';
import getGlobalDir from './helpers/get-global-dir';
@@ -330,8 +327,7 @@ test('should show prompts to set up project during first deploy', async () => {
'README.txt'
).toBe(true);
const { host, href } = new URL(output.stdout);
await disableSSO(host, false);
const { href } = new URL(output.stdout);
// Send a test request to the deployment
const response = await fetch(href);
@@ -646,8 +642,7 @@ test('use `rootDirectory` from project when deploying', async () => {
const secondResult = await execCli(binaryPath, [directory, '--public']);
expect(secondResult.exitCode, formatOutput(secondResult)).toBe(0);
const { host, href } = new URL(secondResult.stdout);
await disableSSO(host, false);
const { href } = new URL(secondResult.stdout);
const pageResponse1 = await fetch(href);
expect(pageResponse1.status).toBe(200);
@@ -728,6 +723,72 @@ test('add a sensitive env var', async () => {
);
});
test('override an existing env var', async () => {
const dir = await setupE2EFixture('project-override-env-vars');
const projectName = `project-override-env-vars-${
Math.random().toString(36).split('.')[1]
}`;
// remove previously linked project if it exists
await remove(path.join(dir, '.vercel'));
const vc = execCli(binaryPath, ['link'], {
cwd: dir,
env: {
FORCE_TTY: '1',
},
});
await setupProject(vc, projectName, {
buildCommand: `mkdir -p o && echo '<h1>custom hello</h1>' > o/index.html`,
outputDirectory: 'o',
});
await vc;
const link = require(path.join(dir, '.vercel/project.json'));
const options = {
env: {
VERCEL_ORG_ID: link.orgId,
VERCEL_PROJECT_ID: link.projectId,
},
};
// 1. Initial add
const addEnvCommand = execCli(
binaryPath,
['env', 'add', 'envVarName', 'production'],
options
);
await waitForPrompt(addEnvCommand, /Whats the value of [^?]+\?/);
addEnvCommand.stdin?.write('test\n');
const output = await addEnvCommand;
expect(output.exitCode, formatOutput(output)).toBe(0);
expect(output.stderr).toContain(
'Added Environment Variable envVarName to Project'
);
// 2. Override
const overrideEnvCommand = execCli(
binaryPath,
['env', 'add', 'envVarName', 'production', '--force'],
options
);
await waitForPrompt(overrideEnvCommand, /Whats the value of [^?]+\?/);
overrideEnvCommand.stdin?.write('test\n');
const outputOverride = await overrideEnvCommand;
expect(outputOverride.exitCode, formatOutput(outputOverride)).toBe(0);
expect(outputOverride.stderr).toContain(
'Overrode Environment Variable envVarName to Project'
);
});
test('whoami with `VERCEL_ORG_ID` should favor `--scope` and should error', async () => {
if (!token) {
throw new Error('Shared state "token" not set.');
@@ -778,7 +839,6 @@ test('deploys with only now.json and README.md', async () => {
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
const { host } = new URL(stdout);
await disableSSO(host, false);
const res = await fetch(`https://${host}/README.md`);
const text = await res.text();
expect(text).toMatch(/readme contents/);
@@ -801,7 +861,6 @@ test('deploys with only vercel.json and README.md', async () => {
);
const { host } = new URL(stdout);
await disableSSO(host, false);
const res = await fetch(`https://${host}/README.md`);
const text = await res.text();
expect(text).toMatch(/readme contents/);
@@ -887,7 +946,6 @@ test('deploy pnpm twice using pnp and symlink=false', async () => {
'--public',
'--yes',
]);
await disableSSO(res.stdout, false);
return res;
}
@@ -1344,8 +1402,6 @@ test('vercel.json configuration overrides in a new project prompt user and merge
const deployment = await vc;
expect(deployment.exitCode, formatOutput(deployment)).toBe(0);
// assert the command were executed
await disableSSO(deployment.stdout, false);
let page = await fetch(deployment.stdout);
let text = await page.text();
expect(text).toBe('1\n');
@@ -1376,8 +1432,7 @@ test('vercel.json configuration overrides in an existing project do not prompt u
// auto-confirm this deployment
let deployment = await deploy(true);
const { host, href } = new URL(deployment.stdout);
await disableSSO(host, false);
const { href } = new URL(deployment.stdout);
let page = await fetch(href);
let text = await page.text();
expect(text).toBe('0');

View File

@@ -14,10 +14,7 @@ import { logo } from '../src/util/pkg-name';
import sleep from '../src/util/sleep';
import humanizePath from '../src/util/humanize-path';
import pkg from '../package.json';
import {
disableSSO,
fetchTokenWithRetry,
} from '../../../test/lib/deployment/now-deploy';
import { fetchTokenWithRetry } from '../../../test/lib/deployment/now-deploy';
import waitForPrompt from './helpers/wait-for-prompt';
import { getNewTmpDir, listTmpDirs } from './helpers/get-tmp-dir';
import getGlobalDir from './helpers/get-global-dir';
@@ -312,7 +309,6 @@ test('should add secret with hyphen prefix', async () => {
expect(targetCall.exitCode, formatOutput(targetCall)).toBe(0);
const { host } = new URL(targetCall.stdout);
await disableSSO(host, false);
const response = await fetch(`https://${host}`);
expect(response.status).toBe(200);
expect(await response.text()).toBe(`${value}\n`);
@@ -341,7 +337,6 @@ test('ignore files specified in .nowignore', async () => {
});
const { host } = new URL(targetCall.stdout);
await disableSSO(host, false);
const ignoredFile = await fetch(`https://${host}/ignored.txt`);
expect(ignoredFile.status).toBe(404);
@@ -358,7 +353,6 @@ test('ignore files specified in .nowignore via allowlist', async () => {
});
const { host } = new URL(targetCall.stdout);
await disableSSO(host, false);
const ignoredFile = await fetch(`https://${host}/ignored.txt`);
expect(ignoredFile.status).toBe(404);
@@ -375,7 +369,7 @@ test('list the scopes', async () => {
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
const include = new RegExp(`${contextName}\\s+${email}`);
expect(stdout).toMatch(include);
expect(stderr).toMatch(include);
});
test('domains inspect', async () => {
@@ -555,7 +549,6 @@ test('ensure we render a warning for deployments with no files', async () => {
// Ensure the exit code is right
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
await disableSSO(host, false);
// Send a test request to the deployment
const res = await fetch(href);
@@ -907,7 +900,6 @@ test('try to revert a deployment and assign the automatic aliases', async () =>
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
await disableSSO(deploymentUrl, false);
await waitForDeployment(deploymentUrl);
await sleep(20000);
@@ -922,7 +914,6 @@ test('try to revert a deployment and assign the automatic aliases', async () =>
'--yes',
]);
const deploymentUrl = stdout;
await disableSSO(deploymentUrl, false);
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
@@ -942,7 +933,6 @@ test('try to revert a deployment and assign the automatic aliases', async () =>
'--yes',
]);
const deploymentUrl = stdout;
await disableSSO(deploymentUrl, false);
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
@@ -1214,7 +1204,6 @@ test('deploy a Lambda with 128MB of memory', async () => {
expect(output.exitCode, formatOutput(output)).toBe(0);
const { host: url } = new URL(output.stdout);
await disableSSO(url, false);
const response = await fetch('https://' + url + '/api/memory');
expect(response.status).toBe(200);
@@ -1241,7 +1230,6 @@ test('deploy a Lambda with 3 seconds of maxDuration', async () => {
expect(output.exitCode, formatOutput(output)).toBe(0);
const url = new URL(output.stdout);
await disableSSO(url.host, false);
// Should time out
url.pathname = '/api/wait-for/5';
@@ -1280,7 +1268,6 @@ test('deploy a Lambda with a specific runtime', async () => {
expect(output.exitCode, formatOutput(output)).toBe(0);
const url = new URL(output.stdout);
await disableSSO(url.host, false);
const res = await fetch(`${url}/api/test`);
const text = await res.text();
expect(text).toBe('Hello from PHP');
@@ -1311,7 +1298,6 @@ test('use build-env', async () => {
// Test if the output is really a URL
const deploymentUrl = pickUrl(stdout);
const { href } = new URL(deploymentUrl);
await disableSSO(deploymentUrl, false);
await waitForDeployment(href);

View File

@@ -270,7 +270,7 @@ export function useProject(
});
}
);
client.scenario.get(`/v8/projects/${project.id}/env`, (req, res) => {
client.scenario.get(`/v10/projects/${project.id}/env`, (req, res) => {
const target: ProjectEnvTarget | undefined =
typeof req.query.target === 'string'
? parseEnvironment(req.query.target)
@@ -291,14 +291,14 @@ export function useProject(
res.json({ envs: targetEnvs });
});
client.scenario.post(`/v8/projects/${project.id}/env`, (req, res) => {
client.scenario.post(`/v10/projects/${project.id}/env`, (req, res) => {
const envObj = req.body;
envObj.id = envObj.key;
envs.push(envObj);
res.json({ envs });
});
client.scenario.delete(
`/v8/projects/${project.id}/env/:envId`,
`/v10/projects/${project.id}/env/:envId`,
(req, res) => {
const envId = req.params.envId;
for (const [i, env] of envs.entries()) {

View File

@@ -466,6 +466,54 @@ describe('deploy', () => {
});
});
it('should send `projectSettings.nodeVersion` based on `engines.node` package.json field with `builds` in `vercel.json`', async () => {
const user = useUser();
useTeams('team_dummy');
useProject({
...defaultProject,
name: 'legacy-builds',
id: 'QmbKpqpiUqbcke',
});
let body: any;
client.scenario.post(`/v13/deployments`, (req, res) => {
body = req.body;
res.json({
creator: {
uid: user.id,
username: user.username,
},
id: 'dpl_',
});
});
client.scenario.get(`/v13/deployments/dpl_`, (req, res) => {
res.json({
creator: {
uid: user.id,
username: user.username,
},
id: 'dpl_',
readyState: 'READY',
aliasAssigned: true,
alias: [],
});
});
const repoRoot = setupUnitFixture('commands/deploy/legacy-builds');
client.cwd = repoRoot;
client.setArgv('deploy');
const exitCode = await deploy(client);
expect(exitCode).toEqual(0);
expect(body).toMatchObject({
source: 'cli',
version: 2,
projectSettings: {
nodeVersion: '18.x',
sourceFilesOutsideRootDirectory: true,
},
});
});
it('should send latest supported node version when given a >low-node-version based on `engines.node` package.json field', async () => {
const user = useUser();
useTeams('team_dummy');

View File

@@ -115,7 +115,9 @@ describe('promote', () => {
`Fetching deployment "${previousDeployment.url}" in ${previousDeployment.creator?.username}`
);
await expect(client.stderr).toOutput(
'? This deployment does not target production, therefore promotion will not apply\n production environment variables. Are you sure you want to continue?'
'? This deployment is not a production deployment and cannot be directly \n' +
'promoted. A new deployment will be built using your production environment. Are \n' +
'you sure you want to continue? (y/N)'
);
// say "no" to the prompt
@@ -138,7 +140,9 @@ describe('promote', () => {
`Fetching deployment "${previousDeployment.url}" in ${previousDeployment.creator?.username}`
);
await expect(client.stderr).toOutput(
'? This deployment does not target production, therefore promotion will not apply\n production environment variables. Are you sure you want to continue?'
'? This deployment is not a production deployment and cannot be directly \n' +
'promoted. A new deployment will be built using your production environment. Are \n' +
'you sure you want to continue? (y/N)'
);
// say "yes" to the prompt

View File

@@ -11,7 +11,7 @@ describe('teams', () => {
const user = useUser();
useTeams(undefined, { apiVersion: 2 });
const exitCodePromise = teamsList(client);
await expect(client.stdout).toOutput(user.username);
await expect(client.stderr).toOutput(user.username);
await expect(exitCodePromise).resolves.toEqual(0);
});
});

View File

@@ -123,7 +123,7 @@ describe('importBuilders()', () => {
const cwd = await getWriteableDirectory();
try {
const spec = 'vercel-deno@2.0.1';
const tarballSpec = 'https://test2020-h5hdll5dz-tootallnate.vercel.app';
const tarballSpec = 'https://files-njlxk3l0r-curated-tests.vercel.app';
const specs = new Set([spec, tarballSpec]);
const builders = await importBuilders(specs, cwd, client.output);
expect(builders.size).toEqual(2);
@@ -142,7 +142,7 @@ describe('importBuilders()', () => {
'function'
);
await expect(client.stderr).toOutput(
'> Installing Builders: vercel-deno@2.0.1, https://test2020-h5hdll5dz-tootallnate.vercel.app'
'> Installing Builders: vercel-deno@2.0.1, https://files-njlxk3l0r-curated-tests.vercel.app'
);
} finally {
await remove(cwd);

View File

@@ -1,5 +1,11 @@
# @vercel/client
## 13.2.0
### Minor Changes
- Always use v13 of create deployment API endpoint ([#11351](https://github.com/vercel/vercel/pull/11351))
## 13.1.9
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/client",
"version": "13.1.9",
"version": "13.2.0",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",

View File

@@ -31,10 +31,7 @@ export async function* checkDeploymentStatus(
let deploymentState = deployment;
const apiDeployments = getApiDeploymentsUrl({
builds: deployment.builds,
functions: deployment.functions,
});
const apiDeployments = getApiDeploymentsUrl();
// If the deployment is ready, we don't want any of this to run
if (isDone(deploymentState) && isAliasAssigned(deploymentState)) {

View File

@@ -27,7 +27,11 @@ async function* postDeployment(
}> {
const debug = createDebug(clientOptions.debug);
const preparedFiles = prepareFiles(files, clientOptions);
const apiDeployments = getApiDeploymentsUrl(deploymentOptions);
const apiDeployments = getApiDeploymentsUrl();
if (deploymentOptions?.builds && !deploymentOptions.functions) {
clientOptions.skipAutoDetectionConfirmation = true;
}
debug('Sending deployment creation API request');
try {

View File

@@ -6,7 +6,7 @@ import { URL } from 'url';
import ignore from 'ignore';
import { pkgVersion } from '../pkg';
import { NowBuildError } from '@vercel/build-utils';
import { VercelClientOptions, DeploymentOptions, VercelConfig } from '../types';
import { VercelClientOptions, VercelConfig } from '../types';
import { Sema } from 'async-sema';
import { readFile } from 'fs-extra';
import readdir from './readdir-recursive';
@@ -46,13 +46,7 @@ const EVENTS_ARRAY = [
export type DeploymentEventType = typeof EVENTS_ARRAY[number];
export const EVENTS = new Set(EVENTS_ARRAY);
export function getApiDeploymentsUrl(
metadata?: Pick<DeploymentOptions, 'builds' | 'functions'>
) {
if (metadata && metadata.builds && !metadata.functions) {
return '/v10/deployments';
}
export function getApiDeploymentsUrl() {
return '/v13/deployments';
}

View File

@@ -4,8 +4,6 @@ import { generateNewToken } from './common';
import { fetch, getApiDeploymentsUrl } from '../src/utils';
import { Deployment } from './types';
import { createDeployment } from '../src/index';
// @ts-expect-error non-TS
import { disableSSO } from '../../../test/lib/deployment/now-deploy';
describe('create v2 deployment', () => {
let deployment: Deployment;
@@ -45,7 +43,6 @@ describe('create v2 deployment', () => {
if (event.type === 'ready') {
deployment = event.payload;
await disableSSO(deployment.id);
break;
}
}
@@ -68,7 +65,6 @@ describe('create v2 deployment', () => {
if (event.type === 'ready') {
deployment = event.payload;
await disableSSO(deployment.id);
break;
}
}
@@ -87,7 +83,6 @@ describe('create v2 deployment', () => {
)) {
if (event.type === 'ready') {
deployment = event.payload;
await disableSSO(deployment.id);
expect(deployment.readyState).toEqual('READY');
break;
}
@@ -114,7 +109,6 @@ describe('create v2 deployment', () => {
)) {
if (event.type === 'ready') {
deployment = event.payload;
await disableSSO(deployment.id);
break;
} else if (event.type === 'error') {
error = event.payload;
@@ -154,7 +148,6 @@ describe('create v2 deployment', () => {
)) {
if (event.type === 'ready') {
deployment = event.payload;
await disableSSO(deployment.id);
break;
} else if (event.type === 'error') {
error = event.payload;

View File

@@ -1,5 +1,11 @@
# @vercel/next
## 4.2.0
### Minor Changes
- Add support for edge function environment variables ([#11390](https://github.com/vercel/vercel/pull/11390))
## 4.1.6
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/next",
"version": "4.1.6",
"version": "4.2.0",
"license": "Apache-2.0",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",

View File

@@ -2753,7 +2753,10 @@ export type FunctionsConfigManifestV1 = {
>;
};
type MiddlewareManifest = MiddlewareManifestV1 | MiddlewareManifestV2;
type MiddlewareManifest =
| MiddlewareManifestV1
| MiddlewareManifestV2
| MiddlewareManifestV3;
interface MiddlewareManifestV1 {
version: 1;
@@ -2769,6 +2772,13 @@ interface MiddlewareManifestV2 {
functions?: { [page: string]: EdgeFunctionInfoV2 };
}
interface MiddlewareManifestV3 {
version: 3;
sortedMiddleware: string[];
middleware: { [page: string]: EdgeFunctionInfoV3 };
functions?: { [page: string]: EdgeFunctionInfoV3 };
}
type Regions = 'home' | 'global' | 'auto' | string[] | 'all' | 'default';
interface BaseEdgeFunctionInfo {
@@ -2788,6 +2798,11 @@ interface EdgeFunctionInfoV2 extends BaseEdgeFunctionInfo {
matchers: EdgeFunctionMatcher[];
}
interface EdgeFunctionInfoV3 extends BaseEdgeFunctionInfo {
matchers: EdgeFunctionMatcher[];
environments: Record<string, string>;
}
interface EdgeFunctionMatcher {
regexp: string;
has?: HasField;
@@ -3020,6 +3035,7 @@ export async function getMiddlewareBundle({
slug: 'nextjs',
version: nextVersion,
},
environment: edgeFunction.environments,
});
})(),
routeMatchers: getRouteMatchers(edgeFunction, routesManifest),
@@ -3160,7 +3176,7 @@ export async function getFunctionsConfigManifest(
export async function getMiddlewareManifest(
entryPath: string,
outputDirectory: string
): Promise<MiddlewareManifestV2 | undefined> {
): Promise<MiddlewareManifestV3 | undefined> {
const middlewareManifestPath = path.join(
entryPath,
outputDirectory,
@@ -3179,19 +3195,27 @@ export async function getMiddlewareManifest(
const manifest = (await fs.readJSON(
middlewareManifestPath
)) as MiddlewareManifest;
return manifest.version === 1
? upgradeMiddlewareManifest(manifest)
: manifest;
if (manifest.version === 1) {
return upgradeMiddlewareManifestV1(manifest);
}
if (manifest.version === 2) {
return upgradeMiddlewareManifestV2(manifest);
}
return manifest;
}
export function upgradeMiddlewareManifest(
export function upgradeMiddlewareManifestV1(
v1: MiddlewareManifestV1
): MiddlewareManifestV2 {
function updateInfo(v1Info: EdgeFunctionInfoV1): EdgeFunctionInfoV2 {
): MiddlewareManifestV3 {
function updateInfo(v1Info: EdgeFunctionInfoV1): EdgeFunctionInfoV3 {
const { regexp, ...rest } = v1Info;
return {
...rest,
matchers: [{ regexp }],
environments: {},
};
}
@@ -3206,7 +3230,35 @@ export function upgradeMiddlewareManifest(
return {
...v1,
version: 2,
version: 3,
middleware,
functions,
};
}
export function upgradeMiddlewareManifestV2(
v2: MiddlewareManifestV2
): MiddlewareManifestV3 {
function updateInfo(v2Info: EdgeFunctionInfoV2): EdgeFunctionInfoV3 {
const { ...rest } = v2Info;
return {
...rest,
environments: {},
};
}
const middleware = Object.fromEntries(
Object.entries(v2.middleware).map(([p, info]) => [p, updateInfo(info)])
);
const functions = v2.functions
? Object.fromEntries(
Object.entries(v2.functions).map(([p, info]) => [p, updateInfo(info)])
)
: undefined;
return {
...v2,
version: 3,
middleware,
functions,
};

View File

@@ -0,0 +1,5 @@
node_modules
/build
.env
.vercel

View File

@@ -0,0 +1,38 @@
# Remix
This directory is a brief example of a [Remix](https://remix.run/docs) site that can be deployed to Vercel with zero configuration.
To get started, run the Remix cli with this template
```sh
npx create-remix@latest --template vercel/vercel/examples/remix
```
## Deploy Your Own
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/examples/remix&template=remix)
_Live Example: https://remix-run-template.vercel.app_
You can also deploy using the [Vercel CLI](https://vercel.com/docs/cli):
```sh
npm i -g vercel
vercel
```
## Development
To run your Remix app locally, make sure your project's local dependencies are installed:
```sh
npm install
```
Afterwards, start the Remix development server like so:
```sh
npm run dev
```
Open up [http://localhost:5173](http://localhost:5173) and you should be ready to go!

View File

@@ -0,0 +1,5 @@
export default function handleRequest(
request: Request,
) {
return new Response("This is a custom entry.server response");
}

View File

@@ -0,0 +1,31 @@
import {
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from "@remix-run/react";
import { Analytics } from "@vercel/analytics/react";
export function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
{children}
<ScrollRestoration />
<Scripts />
<Analytics />
</body>
</html>
);
}
export default function App() {
return <Outlet />;
}

View File

@@ -0,0 +1,41 @@
import type { MetaFunction } from "@vercel/remix";
export const meta: MetaFunction = () => {
return [
{ title: "New Remix App" },
{ name: "description", content: "Welcome to Remix!" },
];
};
export default function Index() {
return (
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
<h1>Welcome to Remix</h1>
<ul>
<li>
<a
target="_blank"
href="https://remix.run/tutorials/blog"
rel="noreferrer"
>
15m Quickstart Blog Tutorial
</a>
</li>
<li>
<a
target="_blank"
href="https://remix.run/tutorials/jokes"
rel="noreferrer"
>
Deep Dive Jokes App Tutorial
</a>
</li>
<li>
<a target="_blank" href="https://remix.run/docs" rel="noreferrer">
Remix Docs
</a>
</li>
</ul>
</div>
);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
{
"name": "my-remix-app",
"private": true,
"sideEffects": false,
"type": "module",
"scripts": {
"build": "remix vite:build",
"dev": "remix vite:dev",
"typecheck": "tsc"
},
"dependencies": {
"@remix-run/node": "^2.8.1",
"@remix-run/react": "^2.8.1",
"@remix-run/server-runtime": "^2.8.1",
"@vercel/analytics": "^1.2.2",
"@vercel/remix": "^2.8.1-patch.2",
"isbot": "^4",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@remix-run/dev": "^2.8.1",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"typescript": "^5.1.6",
"vite": "^5.1.0",
"vite-tsconfig-paths": "^4.2.1"
},
"engines": {
"node": ">=18.0.0"
}
}

View File

@@ -0,0 +1,12 @@
{
"probes": [
{
"path": "/",
"mustContain": "This is a custom entry.server response"
},
{
"path": "/does-not-exist",
"mustContain": "This is a custom entry.server response"
}
]
}

View File

@@ -0,0 +1,25 @@
{
"include": ["**/*.ts", "**/*.tsx"],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"types": ["@vercel/remix", "node", "vite/client"],
"isolatedModules": true,
"esModuleInterop": true,
"jsx": "react-jsx",
"module": "ESNext",
"moduleResolution": "Bundler",
"resolveJsonModule": true,
"target": "ES2022",
"strict": true,
"allowJs": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"paths": {
"~/*": ["./app/*"]
},
// Vite takes care of building everything, not tsc.
"noEmit": true
}
}

View File

@@ -0,0 +1,11 @@
import { vitePlugin as remix } from "@remix-run/dev";
import { installGlobals } from "@remix-run/node";
import { defineConfig } from "vite";
import { vercelPreset } from '@vercel/remix/vite';
import tsconfigPaths from "vite-tsconfig-paths";
installGlobals();
export default defineConfig({
plugins: [remix({ presets: [vercelPreset()] }), tsconfigPaths()],
});

295
pnpm-lock.yaml generated
View File

@@ -89,8 +89,8 @@ importers:
specifier: 29.1.0
version: 29.1.0(@babel/core@7.5.0)(esbuild@0.19.2)(jest@29.5.0)(typescript@4.9.5)
turbo:
specifier: 1.13.0
version: 1.13.0
specifier: 1.13.2
version: 1.13.2
typescript:
specifier: 4.9.5
version: 4.9.5
@@ -325,7 +325,7 @@ importers:
specifier: 1.0.2
version: link:../hydrogen
'@vercel/next':
specifier: 4.1.6
specifier: 4.2.0
version: link:../next
'@vercel/node':
specifier: 3.0.26
@@ -356,20 +356,20 @@ importers:
specifier: 2.3.0
version: 2.3.0
'@inquirer/checkbox':
specifier: 2.2.0
version: 2.2.0
specifier: 2.2.2
version: 2.2.2
'@inquirer/confirm':
specifier: 3.1.0
version: 3.1.0
specifier: 3.1.2
version: 3.1.2
'@inquirer/expand':
specifier: 2.1.0
version: 2.1.0
specifier: 2.1.2
version: 2.1.2
'@inquirer/input':
specifier: 2.1.1
version: 2.1.1
specifier: 2.1.2
version: 2.1.2
'@inquirer/select':
specifier: 2.2.0
version: 2.2.0
specifier: 2.2.2
version: 2.2.2
'@next/env':
specifier: 11.1.2
version: 11.1.2
@@ -463,9 +463,6 @@ importers:
'@types/tar-fs':
specifier: 1.16.1
version: 1.16.1
'@types/text-table':
specifier: 0.2.0
version: 0.2.0
'@types/title':
specifier: 3.4.1
version: 3.4.1
@@ -494,7 +491,7 @@ importers:
specifier: 1.0.29
version: link:../../internals/types
'@vercel/client':
specifier: 13.1.9
specifier: 13.2.0
version: link:../client
'@vercel/error-utils':
specifier: 2.0.2
@@ -700,9 +697,6 @@ importers:
tar-fs:
specifier: 1.16.3
version: 1.16.3
text-table:
specifier: 0.2.0
version: 0.2.0
title:
specifier: 3.4.1
version: 3.4.1
@@ -1609,14 +1603,6 @@ packages:
resolution: {integrity: sha512-1eBykZCd0pPGl5qKtV6Z5ARA6yuhXzHsVN2h5GH5/H6svYa37Jr7vMio5OFpiw1LBHtscrZs7amSkZkcwm0cvQ==}
dev: true
/@ampproject/remapping@2.2.1:
resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
engines: {node: '>=6.0.0'}
dependencies:
'@jridgewell/gen-mapping': 0.3.5
'@jridgewell/trace-mapping': 0.3.25
dev: true
/@ampproject/remapping@2.3.0:
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'}
@@ -1628,16 +1614,8 @@ packages:
/@babel/code-frame@7.18.6:
resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/highlight': 7.22.20
dev: true
/@babel/code-frame@7.22.13:
resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/highlight': 7.24.2
chalk: 2.4.2
dev: true
/@babel/code-frame@7.24.2:
@@ -1657,16 +1635,16 @@ packages:
resolution: {integrity: sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@ampproject/remapping': 2.2.1
'@babel/code-frame': 7.22.13
'@babel/generator': 7.23.0
'@babel/helper-compilation-targets': 7.21.5(@babel/core@7.21.8)
'@babel/helper-module-transforms': 7.21.5
'@babel/helpers': 7.21.5
'@babel/parser': 7.23.0
'@babel/template': 7.22.15
'@babel/traverse': 7.23.2
'@babel/types': 7.23.0
'@ampproject/remapping': 2.3.0
'@babel/code-frame': 7.24.2
'@babel/generator': 7.24.1
'@babel/helper-compilation-targets': 7.23.6
'@babel/helper-module-transforms': 7.23.3(@babel/core@7.21.8)
'@babel/helpers': 7.24.1
'@babel/parser': 7.24.1
'@babel/template': 7.24.0
'@babel/traverse': 7.24.1
'@babel/types': 7.24.0
convert-source-map: 1.8.0
debug: 4.3.4
gensync: 1.0.0-beta.2
@@ -1744,16 +1722,6 @@ packages:
jsesc: 2.5.2
dev: true
/@babel/generator@7.23.0:
resolution: {integrity: sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.24.0
'@jridgewell/gen-mapping': 0.3.5
'@jridgewell/trace-mapping': 0.3.25
jsesc: 2.5.2
dev: true
/@babel/generator@7.24.1:
resolution: {integrity: sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==}
engines: {node: '>=6.9.0'}
@@ -1771,20 +1739,6 @@ packages:
'@babel/types': 7.24.0
dev: true
/@babel/helper-compilation-targets@7.21.5(@babel/core@7.21.8):
resolution: {integrity: sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/compat-data': 7.24.1
'@babel/core': 7.21.8
'@babel/helper-validator-option': 7.23.5
browserslist: 4.23.0
lru-cache: 5.1.1
semver: 6.3.1
dev: true
/@babel/helper-compilation-targets@7.23.6:
resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==}
engines: {node: '>=6.9.0'}
@@ -1873,20 +1827,18 @@ packages:
- supports-color
dev: true
/@babel/helper-module-transforms@7.21.5:
resolution: {integrity: sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==}
/@babel/helper-module-transforms@7.23.3(@babel/core@7.21.8):
resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/core': 7.21.8
'@babel/helper-environment-visitor': 7.22.20
'@babel/helper-module-imports': 7.24.3
'@babel/helper-simple-access': 7.22.5
'@babel/helper-split-export-declaration': 7.22.6
'@babel/helper-validator-identifier': 7.22.20
'@babel/template': 7.24.0
'@babel/traverse': 7.24.1
'@babel/types': 7.24.0
transitivePeerDependencies:
- supports-color
dev: true
/@babel/helper-module-transforms@7.23.3(@babel/core@7.24.3):
@@ -1995,17 +1947,6 @@ packages:
- supports-color
dev: true
/@babel/helpers@7.21.5:
resolution: {integrity: sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/template': 7.24.0
'@babel/traverse': 7.24.1
'@babel/types': 7.24.0
transitivePeerDependencies:
- supports-color
dev: true
/@babel/helpers@7.24.1:
resolution: {integrity: sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==}
engines: {node: '>=6.9.0'}
@@ -2017,15 +1958,6 @@ packages:
- supports-color
dev: true
/@babel/highlight@7.22.20:
resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-validator-identifier': 7.22.20
chalk: 2.4.2
js-tokens: 4.0.0
dev: true
/@babel/highlight@7.24.2:
resolution: {integrity: sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==}
engines: {node: '>=6.9.0'}
@@ -2043,14 +1975,6 @@ packages:
'@babel/types': 7.24.0
dev: true
/@babel/parser@7.23.0:
resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==}
engines: {node: '>=6.0.0'}
hasBin: true
dependencies:
'@babel/types': 7.24.0
dev: true
/@babel/parser@7.24.1:
resolution: {integrity: sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==}
engines: {node: '>=6.0.0'}
@@ -2271,15 +2195,6 @@ packages:
'@babel/types': 7.24.0
dev: true
/@babel/template@7.22.15:
resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.24.2
'@babel/parser': 7.24.1
'@babel/types': 7.24.0
dev: true
/@babel/template@7.24.0:
resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==}
engines: {node: '>=6.9.0'}
@@ -2307,24 +2222,6 @@ packages:
- supports-color
dev: true
/@babel/traverse@7.23.2:
resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.24.2
'@babel/generator': 7.24.1
'@babel/helper-environment-visitor': 7.22.20
'@babel/helper-function-name': 7.23.0
'@babel/helper-hoist-variables': 7.22.5
'@babel/helper-split-export-declaration': 7.22.6
'@babel/parser': 7.24.1
'@babel/types': 7.24.0
debug: 4.3.4
globals: 11.12.0
transitivePeerDependencies:
- supports-color
dev: true
/@babel/traverse@7.24.1:
resolution: {integrity: sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==}
engines: {node: '>=6.9.0'}
@@ -2352,15 +2249,6 @@ packages:
to-fast-properties: 2.0.0
dev: true
/@babel/types@7.23.0:
resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-string-parser': 7.24.1
'@babel/helper-validator-identifier': 7.22.20
to-fast-properties: 2.0.0
dev: true
/@babel/types@7.24.0:
resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==}
engines: {node: '>=6.9.0'}
@@ -3483,52 +3371,32 @@ packages:
/@iarna/toml@2.2.3:
resolution: {integrity: sha512-FmuxfCuolpLl0AnQ2NHSzoUKWEJDFl63qXjzdoWBVyFCXzMGm1spBzk7LeHNoVCiWCF7mRVms9e6jEV9+MoPbg==}
/@inquirer/checkbox@2.2.0:
resolution: {integrity: sha512-L+owhbEm98dnP15XtT/8D1+nNvQecf8HngVFYTJaDR0jlfIeOHFHRbjhLKoVYxks85yY8mLaYXVZQLU46KTkXg==}
/@inquirer/checkbox@2.2.2:
resolution: {integrity: sha512-EyPKpHIJ4bOw7S+Gbbwdy1V/kR3L5I2lLa/b9L/lOQDhdbk7Q1d0ET2k2kU8DNPu7FgQ8xvdzEUf92tSomrpzQ==}
engines: {node: '>=18'}
dependencies:
'@inquirer/core': 7.1.0
'@inquirer/core': 7.1.2
'@inquirer/type': 1.2.1
ansi-escapes: 4.3.2
chalk: 4.1.2
figures: 3.2.0
dev: true
/@inquirer/confirm@3.1.0:
resolution: {integrity: sha512-nH5mxoTEoqk6WpoBz80GMpDSm9jH5V9AF8n+JZAZfMzd9gHeEG9w1o3KawPRR72lfzpP+QxBHLkOKLEApwhDiQ==}
/@inquirer/confirm@3.1.2:
resolution: {integrity: sha512-xQeRxRpVOQdBinIyOHX9+/nTrvt84NnaP8hym5ARdLr6a5T1ckowx70sEaItgULBHlxSIJL970BoRfFxlzO2IA==}
engines: {node: '>=18'}
dependencies:
'@inquirer/core': 7.1.0
'@inquirer/core': 7.1.2
'@inquirer/type': 1.2.1
dev: true
/@inquirer/core@7.1.0:
resolution: {integrity: sha512-FRCiDiU54XHt5B/D8hX4twwZuzSP244ANHbu3R7CAsJfiv1dUOz24ePBgCZjygEjDUi6BWIJuk4eWLKJ7LATUw==}
/@inquirer/core@7.1.2:
resolution: {integrity: sha512-ne5VhDqruYYzx8mmjDZ9F58ymrLJGxmSHJUcJGiW3tifzvl3goAm6gNX11w6+zUnGE54vgQ6ALDXL3IOSezMRw==}
engines: {node: '>=18'}
dependencies:
'@inquirer/type': 1.2.1
'@types/mute-stream': 0.0.4
'@types/node': 20.11.30
'@types/wrap-ansi': 3.0.0
ansi-escapes: 4.3.2
chalk: 4.1.2
cli-spinners: 2.9.2
cli-width: 4.1.0
figures: 3.2.0
mute-stream: 1.0.0
run-async: 3.0.0
signal-exit: 4.1.0
strip-ansi: 6.0.1
wrap-ansi: 6.2.0
dev: true
/@inquirer/core@7.1.1:
resolution: {integrity: sha512-rD1UI3eARN9qJBcLRXPOaZu++Bg+xsk0Tuz1EUOXEW+UbYif1sGjr0Tw7lKejHzKD9IbXE1CEtZ+xR/DrNlQGQ==}
engines: {node: '>=18'}
dependencies:
'@inquirer/type': 1.2.1
'@types/mute-stream': 0.0.4
'@types/node': 20.11.30
'@types/node': 20.12.4
'@types/wrap-ansi': 3.0.0
ansi-escapes: 4.3.2
chalk: 4.1.2
@@ -3541,29 +3409,28 @@ packages:
wrap-ansi: 6.2.0
dev: true
/@inquirer/expand@2.1.0:
resolution: {integrity: sha512-jQgF7ImxxsX4MM8BUk33ffOvx3YOlaEqNCLTxBk7eZ5KOqOshmUq9FnOMnacUXpu7MJtkV/DJHubFiC/q4NF6g==}
/@inquirer/expand@2.1.2:
resolution: {integrity: sha512-QTcmxuKBXvsitEmHrz7Nrr30OPTYQWZf+hWrPUHoLSs1Qg1CLIUxFUfKDguiHZGubXmMydKB9m6TJZlAmU+WTA==}
engines: {node: '>=18'}
dependencies:
'@inquirer/core': 7.1.0
'@inquirer/core': 7.1.2
'@inquirer/type': 1.2.1
chalk: 4.1.2
figures: 3.2.0
dev: true
/@inquirer/input@2.1.1:
resolution: {integrity: sha512-Ag5PDh3/V3B68WGD/5LKXDqbdWKlF7zyfPAlstzu0NoZcZGBbZFjfgXlZIcb6Gs+AfdSi7wNf7soVAaMGH7moQ==}
/@inquirer/input@2.1.2:
resolution: {integrity: sha512-Szr9POj/NxbKSmbOx81ZD76b6xmvXXUY56QLWBXRv8zIGTIKtj03V4zAsw3MTiL6Qoo+IaRLwTLr3bI+qIblzA==}
engines: {node: '>=18'}
dependencies:
'@inquirer/core': 7.1.1
'@inquirer/core': 7.1.2
'@inquirer/type': 1.2.1
dev: true
/@inquirer/select@2.2.0:
resolution: {integrity: sha512-Pml3DhVM1LnfqasUMIzaBtw+s5UjM5k0bzDeWrWOgqAMWe16AOg0DcAhXHf+SYbnj2CFBeP/TvkvedL4aAEWww==}
/@inquirer/select@2.2.2:
resolution: {integrity: sha512-WaoleV3O/7iDAHFC0GArOkl7Yg/7wQ/UptxEkfM+bG67h65v0troAjkNASBbNiz9vvoNZxOGhVrug0LNDftCoQ==}
engines: {node: '>=18'}
dependencies:
'@inquirer/core': 7.1.0
'@inquirer/core': 7.1.2
'@inquirer/type': 1.2.1
ansi-escapes: 4.3.2
chalk: 4.1.2
@@ -5267,8 +5134,8 @@ packages:
/@types/node@16.18.11:
resolution: {integrity: sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==}
/@types/node@20.11.30:
resolution: {integrity: sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==}
/@types/node@20.12.4:
resolution: {integrity: sha512-E+Fa9z3wSQpzgYQdYmme5X3OTuejnnTx88A6p6vkkJosR3KBz+HpE3kqNm98VE6cfLFcISx7zW7MsJkH6KwbTw==}
dependencies:
undici-types: 5.26.5
dev: true
@@ -5398,10 +5265,6 @@ packages:
minipass: 4.2.8
dev: true
/@types/text-table@0.2.0:
resolution: {integrity: sha512-om4hNWnI01IKUFCjGQG33JqFcnmt0W5C3WX0G1FVBaucr7oRnL29aAz2hnxpbZnE2t9f8/BR5VOtgcOtsonpLA==}
dev: true
/@types/text-table@0.2.1:
resolution: {integrity: sha512-dchbFCWfVgUSWEvhOkXGS7zjm+K7jCUvGrQkAHPk2Fmslfofp4HQTH2pqnQ3Pw5GPYv0zWa2AQjKtsfZThuemQ==}
dev: true
@@ -6358,14 +6221,6 @@ packages:
acorn: 8.11.3
dev: true
/acorn-jsx@5.3.2(acorn@8.8.2):
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
acorn: 8.8.2
dev: true
/acorn-walk@8.2.0:
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
engines: {node: '>=0.4.0'}
@@ -6389,6 +6244,7 @@ packages:
resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==}
engines: {node: '>=0.4.0'}
hasBin: true
dev: false
/agent-base@4.3.0:
resolution: {integrity: sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==}
@@ -9106,8 +8962,8 @@ packages:
resolution: {integrity: sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
acorn: 8.8.2
acorn-jsx: 5.3.2(acorn@8.8.2)
acorn: 8.11.3
acorn-jsx: 5.3.2(acorn@8.11.3)
eslint-visitor-keys: 3.4.1
dev: true
@@ -11282,7 +11138,7 @@ packages:
resolution: {integrity: sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@babel/code-frame': 7.22.13
'@babel/code-frame': 7.24.2
'@jest/types': 29.5.0
'@types/stack-utils': 2.0.1
chalk: 4.1.0
@@ -14327,11 +14183,6 @@ packages:
fsevents: 2.3.3
dev: true
/run-async@3.0.0:
resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==}
engines: {node: '>=0.12.0'}
dev: true
/run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
dependencies:
@@ -15576,64 +15427,64 @@ packages:
safe-buffer: 5.2.1
dev: true
/turbo-darwin-64@1.13.0:
resolution: {integrity: sha512-ctHeJXtQgBcgxnCXwrJTGiq57HtwF7zWz5NTuSv//5yeU01BtQIt62ArKfjudOhRefWJbX3Z5srn88XTb9hfww==}
/turbo-darwin-64@1.13.2:
resolution: {integrity: sha512-CCSuD8CfmtncpohCuIgq7eAzUas0IwSbHfI8/Q3vKObTdXyN8vAo01gwqXjDGpzG9bTEVedD0GmLbD23dR0MLA==}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/turbo-darwin-arm64@1.13.0:
resolution: {integrity: sha512-/Q9/pNFkF9w83tNxwMpgapwLYdQ12p8mpty2YQRoUiS9ClWkcqe136jR0mtuMqzlNlpREOFZaoyIthjt6Sdo0g==}
/turbo-darwin-arm64@1.13.2:
resolution: {integrity: sha512-0HySm06/D2N91rJJ89FbiI/AodmY8B3WDSFTVEpu2+8spUw7hOJ8okWOT0e5iGlyayUP9gr31eOeL3VFZkpfCw==}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/turbo-linux-64@1.13.0:
resolution: {integrity: sha512-hgbT7o020BGV4L7Sd8hhFTd5zVKPKxbsr0dPfel/9NkdTmptz2aGZ0Vb2MAa18SY3XaCQpDxmdYuOzvvRpo5ZA==}
/turbo-linux-64@1.13.2:
resolution: {integrity: sha512-7HnibgbqZrjn4lcfIouzlPu8ZHSBtURG4c7Bedu7WJUDeZo+RE1crlrQm8wuwO54S0siYqUqo7GNHxu4IXbioQ==}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/turbo-linux-arm64@1.13.0:
resolution: {integrity: sha512-WK01i2wDZARrV+HEs495A3hNeGMwQR5suYk7G+ceqqW7b+dOTlQdvUjnI3sg7wAnZPgjafFs/hoBaZdJjVa/nw==}
/turbo-linux-arm64@1.13.2:
resolution: {integrity: sha512-sUq4dbpk6SNKg/Hkwn256Vj2AEYSQdG96repio894h5/LEfauIK2QYiC/xxAeW3WBMc6BngmvNyURIg7ltrePg==}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/turbo-windows-64@1.13.0:
resolution: {integrity: sha512-hJgSZJZwlWHNwLEthaqJqJWGm4NqF5X/I7vE0sPE4i/jeDl8f0n1hcOkgJkJiNXVxhj+qy/9+4dzbPLKT9imaQ==}
/turbo-windows-64@1.13.2:
resolution: {integrity: sha512-DqzhcrciWq3dpzllJR2VVIyOhSlXYCo4mNEWl98DJ3FZ08PEzcI3ceudlH6F0t/nIcfSItK1bDP39cs7YoZHEA==}
cpu: [x64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/turbo-windows-arm64@1.13.0:
resolution: {integrity: sha512-L/ErxYoXeq8tmjU/AIGicC9VyBN1zdYw8JlM4yPmMI0pJdY8E4GaYK1IiIazqq7M72lmQhU/WW7fV9FqEktwrw==}
/turbo-windows-arm64@1.13.2:
resolution: {integrity: sha512-WnPMrwfCXxK69CdDfS1/j2DlzcKxSmycgDAqV0XCYpK/812KB0KlvsVAt5PjEbZGXkY88pCJ1BLZHAjF5FcbqA==}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/turbo@1.13.0:
resolution: {integrity: sha512-r02GtNmkOPcQvUzVE6lg474QVLyU02r3yh3lUGqrFHf5h5ZEjgDGWILsAUqplVqjri1Y/oOkTssks4CObTAaiw==}
/turbo@1.13.2:
resolution: {integrity: sha512-rX/d9f4MgRT3yK6cERPAkfavIxbpBZowDQpgvkYwGMGDQ0Nvw1nc0NVjruE76GrzXQqoxR1UpnmEP54vBARFHQ==}
hasBin: true
optionalDependencies:
turbo-darwin-64: 1.13.0
turbo-darwin-arm64: 1.13.0
turbo-linux-64: 1.13.0
turbo-linux-arm64: 1.13.0
turbo-windows-64: 1.13.0
turbo-windows-arm64: 1.13.0
turbo-darwin-64: 1.13.2
turbo-darwin-arm64: 1.13.2
turbo-linux-64: 1.13.2
turbo-linux-arm64: 1.13.2
turbo-windows-64: 1.13.2
turbo-windows-arm64: 1.13.2
dev: true
/tweetnacl@0.14.5:

View File

@@ -104,85 +104,9 @@ async function nowDeploy(projectName, bodies, randomness, uploadNowJson, opts) {
await new Promise(r => setTimeout(r, 1000));
}
await disableSSO(deploymentId);
return { deploymentId, deploymentUrl };
}
async function disableSSO(deploymentId, useTeam = true) {
if (deploymentId.startsWith('https://')) {
deploymentId = new URL(deploymentId).hostname;
}
const deployRes = await fetchWithAuth(
`https://vercel.com/api/v13/deployments/${encodeURIComponent(
deploymentId
)}`,
{
method: 'GET',
}
);
const text = await deployRes.text();
if (!deployRes.ok) {
throw new Error(
`Failed to get deployment info (status: ${deployRes.status}, body: ${text})`
);
}
let info;
try {
info = JSON.parse(text);
} catch (err) {
throw new Error('Failed to parse deployment info JSON', { cause: err });
}
const { projectId, url: deploymentUrl } = info;
if (!deploymentUrl || typeof deploymentUrl !== 'string') {
throw new Error(
`Failed to get deployment URL (status: ${deployRes.status}, body: ${text})`
);
}
const settingRes = await fetchWithAuth(
`https://vercel.com/api/v5/projects/${encodeURIComponent(projectId)}`,
{
method: 'PATCH',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
ssoProtection: null,
}),
...(useTeam
? {}
: {
skipTeam: true,
}),
}
);
if (settingRes.ok) {
for (let i = 0; i < 10; i++) {
const res = await fetch(`https://${deploymentUrl}`);
if (res.status !== 401) {
break;
}
await new Promise(resolve => setTimeout(resolve, 5 * 1000));
}
console.log(
`Disabled deployment protection for deploymentId: ${deploymentId} projectId: ${projectId}`
);
} else {
console.error(settingRes.status, await settingRes.text(), text);
throw new Error(
`Failed to disable deployment protection projectId: ${projectId} deploymentId ${deploymentId}`
);
}
}
function digestOfFile(body) {
return createHash('sha1').update(body).digest('hex');
}
@@ -386,5 +310,4 @@ module.exports = {
fetchCachedToken,
fetchTokenWithRetry,
fileModeSymbol,
disableSSO,
};

View File

@@ -12,6 +12,14 @@
"outputMode": "new-only",
"outputs": ["dist/**"]
},
"vitest-unit": {
"dependsOn": ["build"],
"outputMode": "new-only"
},
"vitest-unit-run": {
"dependsOn": ["build"],
"outputMode": "new-only"
},
"test-unit": {
"dependsOn": ["build"],
"outputMode": "new-only"

58
utils/chunk-tests.js vendored
View File

@@ -3,24 +3,58 @@ const child_process = require('child_process');
const path = require('path');
const runnersMap = new Map([
[
'vitest-unit',
{
min: 1,
max: 1,
testScript: 'vitest-unit-run',
runners: ['ubuntu-latest', 'macos-latest', 'windows-latest'],
},
],
[
'test-unit',
{
min: 1,
max: 1,
testScript: 'test',
runners: ['ubuntu-latest', 'macos-latest', 'windows-latest'],
},
],
['test-e2e', { min: 1, max: 7, runners: ['ubuntu-latest'] }],
[
'test-e2e',
{ min: 1, max: 7, testScript: 'test', runners: ['ubuntu-latest'] },
],
[
'test-next-local',
{ min: 1, max: 5, runners: ['ubuntu-latest'], nodeVersion: '18' },
{
min: 1,
max: 5,
runners: ['ubuntu-latest'],
testScript: 'test',
nodeVersion: '18',
},
],
[
'test-next-local-legacy',
{ min: 1, max: 5, runners: ['ubuntu-latest'], nodeVersion: '16' },
{
min: 1,
max: 5,
runners: ['ubuntu-latest'],
testScript: 'test',
nodeVersion: '16',
},
],
[
'test-dev',
{
min: 1,
max: 7,
testScript: 'test',
runners: ['ubuntu-latest', 'macos-latest'],
},
],
['test-dev', { min: 1, max: 7, runners: ['ubuntu-latest', 'macos-latest'] }],
]);
const packageOptionsOverrides = {
@@ -36,13 +70,12 @@ function getRunnerOptions(scriptName, packageName) {
packageOptionsOverrides[packageName]
);
}
return (
runnerOptions || {
min: 1,
max: 1,
runners: ['ubuntu-latest'],
}
);
if (!runnerOptions) {
throw new Error(
`Unable to find runner options for package "${packageName}" and script ${scriptName}`
);
}
return runnerOptions;
}
async function getChunkedTests() {
@@ -98,7 +131,7 @@ async function getChunkedTests() {
const [packagePath, packageName] = packagePathAndName.split(',');
return Object.entries(scriptNames).flatMap(([scriptName, testPaths]) => {
const runnerOptions = getRunnerOptions(scriptName, packageName);
const { runners, min, max, nodeVersion } = runnerOptions;
const { runners, min, max, testScript, nodeVersion } = runnerOptions;
const sortedTestPaths = testPaths.sort((a, b) => a.localeCompare(b));
return intoChunks(min, max, sortedTestPaths).flatMap(
@@ -109,6 +142,7 @@ async function getChunkedTests() {
packagePath,
packageName,
scriptName,
testScript,
nodeVersion,
testPaths: chunk.map(testFile =>
path.relative(