mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 12:57:46 +00:00
Compare commits
14 Commits
@vercel/py
...
@vercel/ne
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d3774ee7e | ||
|
|
50f8eec7cb | ||
|
|
45374e2f90 | ||
|
|
fd9142b6f3 | ||
|
|
8cf67b549b | ||
|
|
5dc6f48e44 | ||
|
|
66c8544e8f | ||
|
|
0140db38fa | ||
|
|
e5421c27e8 | ||
|
|
5afc527233 | ||
|
|
de9518b010 | ||
|
|
c322d1dbba | ||
|
|
18c19ead76 | ||
|
|
9d80c27382 |
@@ -11,7 +11,7 @@
|
||||
"dependencies": {
|
||||
"@sentry/node": "5.11.1",
|
||||
"got": "10.2.1",
|
||||
"node-fetch": "2.6.1",
|
||||
"node-fetch": "2.6.7",
|
||||
"parse-github-url": "1.0.2",
|
||||
"tar-fs": "2.0.0",
|
||||
"unzip-stream": "0.3.0"
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"jest": "28.0.2",
|
||||
"json5": "2.1.1",
|
||||
"lint-staged": "9.2.5",
|
||||
"node-fetch": "2.6.1",
|
||||
"node-fetch": "2.6.7",
|
||||
"npm-package-arg": "6.1.0",
|
||||
"prettier": "2.6.2",
|
||||
"ts-eager": "2.0.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/build-utils",
|
||||
"version": "5.0.3",
|
||||
"version": "5.0.4",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
@@ -44,7 +44,7 @@
|
||||
"js-yaml": "3.13.1",
|
||||
"minimatch": "3.0.4",
|
||||
"multistream": "2.1.1",
|
||||
"node-fetch": "2.6.1",
|
||||
"node-fetch": "2.6.7",
|
||||
"semver": "6.1.1",
|
||||
"typescript": "4.3.4",
|
||||
"yazl": "2.5.1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "27.1.5",
|
||||
"version": "27.2.0",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -42,16 +42,16 @@
|
||||
"node": ">= 14"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "5.0.3",
|
||||
"@vercel/go": "2.0.7",
|
||||
"@vercel/hydrogen": "0.0.4",
|
||||
"@vercel/next": "3.1.7",
|
||||
"@vercel/node": "2.4.4",
|
||||
"@vercel/python": "3.0.7",
|
||||
"@vercel/redwood": "1.0.8",
|
||||
"@vercel/remix": "1.0.9",
|
||||
"@vercel/ruby": "1.3.15",
|
||||
"@vercel/static-build": "1.0.8",
|
||||
"@vercel/build-utils": "5.0.4",
|
||||
"@vercel/go": "2.0.8",
|
||||
"@vercel/hydrogen": "0.0.5",
|
||||
"@vercel/next": "3.1.8",
|
||||
"@vercel/node": "2.4.5",
|
||||
"@vercel/python": "3.1.0",
|
||||
"@vercel/redwood": "1.0.9",
|
||||
"@vercel/remix": "1.0.10",
|
||||
"@vercel/ruby": "1.3.16",
|
||||
"@vercel/static-build": "1.0.9",
|
||||
"update-notifier": "5.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -96,11 +96,11 @@
|
||||
"@types/which": "1.3.2",
|
||||
"@types/write-json-file": "2.2.1",
|
||||
"@types/yauzl-promise": "2.1.0",
|
||||
"@vercel/client": "12.1.2",
|
||||
"@vercel/client": "12.1.3",
|
||||
"@vercel/frameworks": "1.1.1",
|
||||
"@vercel/fs-detectors": "2.0.1",
|
||||
"@vercel/fun": "1.0.4",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@zeit/fun": "0.11.2",
|
||||
"@zeit/source-map-support": "0.6.2",
|
||||
"ajv": "6.12.2",
|
||||
"alpha-sort": "2.0.1",
|
||||
@@ -147,7 +147,7 @@
|
||||
"minimatch": "3.0.4",
|
||||
"mri": "1.1.5",
|
||||
"ms": "2.1.2",
|
||||
"node-fetch": "2.6.1",
|
||||
"node-fetch": "2.6.7",
|
||||
"npm-package-arg": "6.1.0",
|
||||
"open": "8.4.0",
|
||||
"ora": "3.4.0",
|
||||
|
||||
@@ -56,11 +56,11 @@ async function main() {
|
||||
args.push('src/index.ts');
|
||||
await execa('yarn', args, { stdio: 'inherit', cwd: dirRoot });
|
||||
|
||||
// `ncc` has some issues with `@zeit/fun`'s runtime files:
|
||||
// `ncc` has some issues with `@vercel/fun`'s runtime files:
|
||||
// - Executable bits on the `bootstrap` files appear to be lost:
|
||||
// https://github.com/zeit/ncc/pull/182
|
||||
// https://github.com/vercel/ncc/pull/182
|
||||
// - The `bootstrap.js` asset does not get copied into the output dir:
|
||||
// https://github.com/zeit/ncc/issues/278
|
||||
// https://github.com/vercel/ncc/issues/278
|
||||
//
|
||||
// Aside from those issues, all the same files from the `runtimes` directory
|
||||
// should be copied into the output runtimes dir, specifically the `index.js`
|
||||
@@ -70,7 +70,7 @@ async function main() {
|
||||
// with `fun`'s cache invalidation mechanism and they need to be shasum'd.
|
||||
const runtimes = join(
|
||||
dirRoot,
|
||||
'../../node_modules/@zeit/fun/dist/src/runtimes'
|
||||
'../../node_modules/@vercel/fun/dist/src/runtimes'
|
||||
);
|
||||
await cpy('**/*', join(distRoot, 'runtimes'), {
|
||||
parents: true,
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
MergeRoutesProps,
|
||||
Route,
|
||||
} from '@vercel/routing-utils';
|
||||
import { VercelConfig } from '@vercel/client';
|
||||
import type { VercelConfig } from '@vercel/client';
|
||||
|
||||
import pull from './pull';
|
||||
import { staticFiles as getFiles } from '../util/get-files';
|
||||
@@ -36,7 +36,10 @@ import * as cli from '../util/pkg-name';
|
||||
import cliPkg from '../util/pkg';
|
||||
import readJSONFile from '../util/read-json-file';
|
||||
import { CantParseJSONFile } from '../util/errors-ts';
|
||||
import { readProjectSettings } from '../util/projects/project-settings';
|
||||
import {
|
||||
ProjectLinkAndSettings,
|
||||
readProjectSettings,
|
||||
} from '../util/projects/project-settings';
|
||||
import { VERCEL_DIR } from '../util/projects/link';
|
||||
import confirm from '../util/input/confirm';
|
||||
import { emoji, prependEmoji } from '../util/emoji';
|
||||
@@ -46,19 +49,31 @@ import {
|
||||
PathOverride,
|
||||
writeBuildResult,
|
||||
} from '../util/build/write-build-result';
|
||||
import { importBuilders, BuilderWithPkg } from '../util/build/import-builders';
|
||||
import { importBuilders } from '../util/build/import-builders';
|
||||
import { initCorepack, cleanupCorepack } from '../util/build/corepack';
|
||||
import { sortBuilders } from '../util/build/sort-builders';
|
||||
import { toEnumerableError } from '../util/error';
|
||||
|
||||
type BuildResult = BuildResultV2 | BuildResultV3;
|
||||
|
||||
interface SerializedBuilder extends Builder {
|
||||
error?: Error;
|
||||
error?: any;
|
||||
require?: string;
|
||||
requirePath?: string;
|
||||
apiVersion: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contents of the `builds.json` file.
|
||||
*/
|
||||
interface BuildsManifest {
|
||||
'//': string;
|
||||
target: string;
|
||||
argv: string[];
|
||||
error?: any;
|
||||
builds?: SerializedBuilder[];
|
||||
}
|
||||
|
||||
const help = () => {
|
||||
return console.log(`
|
||||
${chalk.bold(`${cli.logo} ${cli.name} build`)}
|
||||
@@ -175,7 +190,6 @@ export default async function main(client: Client): Promise<number> {
|
||||
}
|
||||
|
||||
// TODO: load env vars from the API, fall back to local files if that fails
|
||||
|
||||
const envPath = await checkExists([
|
||||
join(cwd, VERCEL_DIR, `.env.${target}.local`),
|
||||
join(cwd, `.env`),
|
||||
@@ -189,6 +203,48 @@ export default async function main(client: Client): Promise<number> {
|
||||
process.env.VERCEL = '1';
|
||||
process.env.NOW_BUILDER = '1';
|
||||
|
||||
// Delete output directory from potential previous build
|
||||
const outputDir = argv['--output']
|
||||
? resolve(argv['--output'])
|
||||
: join(cwd, OUTPUT_DIR);
|
||||
await fs.remove(outputDir);
|
||||
|
||||
const buildsJson: BuildsManifest = {
|
||||
'//': 'This file was generated by the `vercel build` command. It is not part of the Build Output API.',
|
||||
target,
|
||||
argv: process.argv,
|
||||
};
|
||||
|
||||
try {
|
||||
return await doBuild(client, project, buildsJson, cwd, outputDir);
|
||||
} catch (err: any) {
|
||||
output.prettyError(err);
|
||||
|
||||
// Write error to `builds.json` file
|
||||
buildsJson.error = toEnumerableError(err);
|
||||
const buildsJsonPath = join(outputDir, 'builds.json');
|
||||
const configJsonPath = join(outputDir, 'config.json');
|
||||
await fs.outputJSON(buildsJsonPath, buildsJson, {
|
||||
spaces: 2,
|
||||
});
|
||||
await fs.writeJSON(configJsonPath, { version: 3 }, { spaces: 2 });
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the Project's builders. If this function throws an error,
|
||||
* then it will be serialized into the `builds.json` manifest file.
|
||||
*/
|
||||
async function doBuild(
|
||||
client: Client,
|
||||
project: ProjectLinkAndSettings,
|
||||
buildsJson: BuildsManifest,
|
||||
cwd: string,
|
||||
outputDir: string
|
||||
): Promise<number> {
|
||||
const { output } = client;
|
||||
const workPath = join(cwd, project.settings.rootDirectory || '.');
|
||||
|
||||
// Load `package.json` and `vercel.json` files
|
||||
@@ -208,17 +264,16 @@ export default async function main(client: Client): Promise<number> {
|
||||
|
||||
const routesResult = getTransformedRoutes(vercelConfig || {});
|
||||
if (routesResult.error) {
|
||||
output.prettyError(routesResult.error);
|
||||
return 1;
|
||||
throw routesResult.error;
|
||||
}
|
||||
|
||||
if (vercelConfig?.builds && vercelConfig.functions) {
|
||||
output.prettyError({
|
||||
throw new NowBuildError({
|
||||
code: 'bad_request',
|
||||
message:
|
||||
'The `functions` property cannot be used in conjunction with the `builds` property. Please remove one of them.',
|
||||
link: 'https://vercel.link/functions-and-builds',
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
|
||||
let builds = vercelConfig?.builds || [];
|
||||
@@ -236,12 +291,12 @@ export default async function main(client: Client): Promise<number> {
|
||||
const detectedBuilders = await detectBuilders(files, pkg, {
|
||||
...vercelConfig,
|
||||
projectSettings: project.settings,
|
||||
ignoreBuildScript: true,
|
||||
featHandleMiss: true,
|
||||
});
|
||||
|
||||
if (detectedBuilders.errors && detectedBuilders.errors.length > 0) {
|
||||
output.prettyError(detectedBuilders.errors[0]);
|
||||
return 1;
|
||||
throw detectedBuilders.errors[0];
|
||||
}
|
||||
|
||||
for (const w of detectedBuilders.warnings) {
|
||||
@@ -274,13 +329,7 @@ export default async function main(client: Client): Promise<number> {
|
||||
|
||||
const builderSpecs = new Set(builds.map(b => b.use));
|
||||
|
||||
let buildersWithPkgs: Map<string, BuilderWithPkg>;
|
||||
try {
|
||||
buildersWithPkgs = await importBuilders(builderSpecs, cwd, output);
|
||||
} catch (err: any) {
|
||||
output.prettyError(err);
|
||||
return 1;
|
||||
}
|
||||
const buildersWithPkgs = await importBuilders(builderSpecs, cwd, output);
|
||||
|
||||
// Populate Files -> FileFsRef mapping
|
||||
const filesMap: Files = {};
|
||||
@@ -290,12 +339,6 @@ export default async function main(client: Client): Promise<number> {
|
||||
filesMap[path] = new FileFsRef({ mode, fsPath });
|
||||
}
|
||||
|
||||
// Delete output directory from potential previous build
|
||||
const outputDir = argv['--output']
|
||||
? resolve(argv['--output'])
|
||||
: join(cwd, OUTPUT_DIR);
|
||||
await fs.remove(outputDir);
|
||||
|
||||
const buildStamp = stamp();
|
||||
|
||||
// Create fresh new output directory
|
||||
@@ -322,12 +365,7 @@ export default async function main(client: Client): Promise<number> {
|
||||
];
|
||||
})
|
||||
);
|
||||
const buildsJson = {
|
||||
'//': 'This file was generated by the `vercel build` command. It is not part of the Build Output API.',
|
||||
target,
|
||||
argv: process.argv,
|
||||
builds: Array.from(buildsJsonBuilds.values()),
|
||||
};
|
||||
buildsJson.builds = Array.from(buildsJsonBuilds.values());
|
||||
const buildsJsonPath = join(outputDir, 'builds.json');
|
||||
const writeBuildsJsonPromise = fs.writeJSON(buildsJsonPath, buildsJson, {
|
||||
spaces: 2,
|
||||
@@ -406,25 +444,17 @@ export default async function main(client: Client): Promise<number> {
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
const configJson = {
|
||||
version: 3,
|
||||
};
|
||||
const configJsonPromise = fs.writeJSON(
|
||||
const writeConfigJsonPromise = fs.writeJSON(
|
||||
join(outputDir, 'config.json'),
|
||||
configJson,
|
||||
{ version: 3 },
|
||||
{ spaces: 2 }
|
||||
);
|
||||
|
||||
await Promise.all([writeBuildsJsonPromise, configJsonPromise]);
|
||||
await Promise.all([writeBuildsJsonPromise, writeConfigJsonPromise]);
|
||||
|
||||
const buildJsonBuild = buildsJsonBuilds.get(build);
|
||||
if (buildJsonBuild) {
|
||||
buildJsonBuild.error = {
|
||||
name: err.name,
|
||||
message: err.message,
|
||||
stack: err.stack,
|
||||
...err,
|
||||
};
|
||||
buildJsonBuild.error = toEnumerableError(err);
|
||||
|
||||
await fs.writeJSON(buildsJsonPath, buildsJson, {
|
||||
spaces: 2,
|
||||
@@ -441,15 +471,12 @@ export default async function main(client: Client): Promise<number> {
|
||||
|
||||
// Wait for filesystem operations to complete
|
||||
// TODO render progress bar?
|
||||
let hadError = false;
|
||||
const errors = await Promise.all(ops);
|
||||
for (const error of errors) {
|
||||
if (error) {
|
||||
hadError = true;
|
||||
output.prettyError(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
if (hadError) return 1;
|
||||
|
||||
// Merge existing `config.json` file into the one that will be produced
|
||||
const configPath = join(outputDir, 'config.json');
|
||||
|
||||
@@ -428,7 +428,7 @@ export default async (client: Client) => {
|
||||
parseMeta(argv['--meta'])
|
||||
);
|
||||
|
||||
const gitMetadata = await createGitMeta(path, output);
|
||||
const gitMetadata = await createGitMeta(path, output, project);
|
||||
|
||||
// Merge dotenv config, `env` from vercel.json, and `--env` / `-e` arguments
|
||||
const deploymentEnv = Object.assign(
|
||||
|
||||
21
packages/cli/src/commands/env/index.ts
vendored
21
packages/cli/src/commands/env/index.ts
vendored
@@ -1,7 +1,9 @@
|
||||
import chalk from 'chalk';
|
||||
import { ProjectEnvTarget } from '../../types';
|
||||
import Client from '../../util/client';
|
||||
import { getEnvTargetPlaceholder } from '../../util/env/env-target';
|
||||
import {
|
||||
getEnvTargetPlaceholder,
|
||||
isValidEnvTarget,
|
||||
} from '../../util/env/env-target';
|
||||
import getArgs from '../../util/get-args';
|
||||
import getInvalidSubcommand from '../../util/get-invalid-subcommand';
|
||||
import getSubcommand from '../../util/get-subcommand';
|
||||
@@ -29,6 +31,7 @@ const help = () => {
|
||||
${chalk.dim('Options:')}
|
||||
|
||||
-h, --help Output usage information
|
||||
--environment Set the Environment (development, preview, production) when pulling Environment Variables
|
||||
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
|
||||
'FILE'
|
||||
)} Path to the local ${'`vercel.json`'} file
|
||||
@@ -111,6 +114,7 @@ export default async function main(client: Client) {
|
||||
argv = getArgs(client.argv.slice(2), {
|
||||
'--yes': Boolean,
|
||||
'-y': '--yes',
|
||||
'--environment': String,
|
||||
});
|
||||
} catch (error) {
|
||||
handleError(error);
|
||||
@@ -126,6 +130,17 @@ export default async function main(client: Client) {
|
||||
const subArgs = argv._.slice(1);
|
||||
const { subcommand, args } = getSubcommand(subArgs, COMMAND_CONFIG);
|
||||
const { output, config } = client;
|
||||
|
||||
const target = argv['--environment']?.toLowerCase() || 'development';
|
||||
if (!isValidEnvTarget(target)) {
|
||||
output.error(
|
||||
`Invalid environment \`${chalk.cyan(
|
||||
target
|
||||
)}\`. Valid options: ${getEnvTargetPlaceholder()}`
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const link = await getLinkedProject(client, cwd);
|
||||
if (link.status === 'error') {
|
||||
return link.exitCode;
|
||||
@@ -150,7 +165,7 @@ export default async function main(client: Client) {
|
||||
return pull(
|
||||
client,
|
||||
project,
|
||||
ProjectEnvTarget.Development,
|
||||
target,
|
||||
argv,
|
||||
args,
|
||||
output,
|
||||
|
||||
@@ -2,8 +2,9 @@ import chalk from 'chalk';
|
||||
import { join } from 'path';
|
||||
import { Org, Project } from '../../types';
|
||||
import Client from '../../util/client';
|
||||
import { parseGitConfig, pluckRemoteUrl } from '../../util/create-git-meta';
|
||||
import { parseGitConfig, pluckRemoteUrls } from '../../util/create-git-meta';
|
||||
import confirm from '../../util/input/confirm';
|
||||
import list, { ListChoice } from '../../util/input/list';
|
||||
import { Output } from '../../util/output';
|
||||
import link from '../../util/output/link';
|
||||
import { getCommandName } from '../../util/pkg-name';
|
||||
@@ -64,20 +65,37 @@ export default async function connect(
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
const remoteUrl = pluckRemoteUrl(gitConfig);
|
||||
if (!remoteUrl) {
|
||||
const remoteUrls = pluckRemoteUrls(gitConfig);
|
||||
if (!remoteUrls) {
|
||||
output.error(
|
||||
`No remote origin URL found in your Git config. Make sure you've configured a remote repo in your local Git config. Run ${chalk.cyan(
|
||||
`No remote URLs found in your Git config. Make sure you've configured a remote repo in your local Git config. Run ${chalk.cyan(
|
||||
'`git remote --help`'
|
||||
)} for more details.`
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
output.log(`Identified Git remote "origin": ${link(remoteUrl)}`);
|
||||
|
||||
let remoteUrl: string;
|
||||
|
||||
if (Object.keys(remoteUrls).length > 1) {
|
||||
output.log(`Found multiple remote URLs.`);
|
||||
remoteUrl = await selectRemoteUrl(client, remoteUrls);
|
||||
} else {
|
||||
// If only one is found, get it — usually "origin"
|
||||
remoteUrl = Object.values(remoteUrls)[0];
|
||||
}
|
||||
|
||||
if (remoteUrl === '') {
|
||||
output.log('Aborted.');
|
||||
return 0;
|
||||
}
|
||||
|
||||
output.log(`Connecting Git remote: ${link(remoteUrl)}`);
|
||||
|
||||
const parsedUrl = parseRepoUrl(remoteUrl);
|
||||
if (!parsedUrl) {
|
||||
output.error(
|
||||
`Failed to parse Git repo data from the following remote URL in your Git config: ${link(
|
||||
`Failed to parse Git repo data from the following remote URL: ${link(
|
||||
remoteUrl
|
||||
)}`
|
||||
);
|
||||
@@ -166,3 +184,22 @@ async function confirmRepoConnect(
|
||||
}
|
||||
return shouldReplaceProject;
|
||||
}
|
||||
|
||||
async function selectRemoteUrl(
|
||||
client: Client,
|
||||
remoteUrls: { [key: string]: string }
|
||||
): Promise<string> {
|
||||
let choices: ListChoice[] = [];
|
||||
for (const [urlKey, urlValue] of Object.entries(remoteUrls)) {
|
||||
choices.push({
|
||||
name: `${urlValue} ${chalk.gray(`(${urlKey})`)}`,
|
||||
value: urlValue,
|
||||
short: urlKey,
|
||||
});
|
||||
}
|
||||
|
||||
return await list(client, {
|
||||
message: 'Which remote do you want to connect?',
|
||||
choices,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -750,9 +750,7 @@ const main = async () => {
|
||||
|
||||
// Otherwise it is an unexpected error and we should show the trace
|
||||
// and an unexpected error message
|
||||
output.error(
|
||||
`An unexpected error occurred in ${subcommand}: ${err.stack}`
|
||||
);
|
||||
output.error(`An unexpected error occurred in ${subcommand}: ${err}`);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -3,76 +3,42 @@ import { join } from 'path';
|
||||
import ini from 'ini';
|
||||
import git from 'git-last-commit';
|
||||
import { exec } from 'child_process';
|
||||
import { GitMetadata } from '../types';
|
||||
import { GitMetadata, Project } from '../types';
|
||||
import { Output } from './output';
|
||||
|
||||
export function isDirty(directory: string, output: Output): Promise<boolean> {
|
||||
return new Promise(resolve => {
|
||||
exec('git status -s', { cwd: directory }, function (err, stdout, stderr) {
|
||||
let debugMessage = `Failed to determine if Git repo has been modified:`;
|
||||
if (err || stderr) {
|
||||
if (err) debugMessage += `\n${err}`;
|
||||
if (stderr) debugMessage += `\n${stderr.trim()}`;
|
||||
output.debug(debugMessage);
|
||||
return resolve(false);
|
||||
}
|
||||
resolve(stdout.trim().length > 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getLastCommit(directory: string): Promise<git.Commit> {
|
||||
return new Promise((resolve, reject) => {
|
||||
git.getLastCommit(
|
||||
(err, commit) => {
|
||||
if (err) return reject(err);
|
||||
resolve(commit);
|
||||
},
|
||||
{ dst: directory }
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export async function parseGitConfig(configPath: string, output: Output) {
|
||||
try {
|
||||
return ini.parse(await fs.readFile(configPath, 'utf-8'));
|
||||
} catch (error) {
|
||||
output.debug(`Error while parsing repo data: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function pluckRemoteUrl(gitConfig: {
|
||||
[key: string]: any;
|
||||
}): string | undefined {
|
||||
// Assuming "origin" is the remote url that the user would want to use
|
||||
return gitConfig['remote "origin"']?.url;
|
||||
}
|
||||
|
||||
export async function getRemoteUrl(
|
||||
configPath: string,
|
||||
output: Output
|
||||
): Promise<string | null> {
|
||||
let gitConfig = await parseGitConfig(configPath, output);
|
||||
if (!gitConfig) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const originUrl = pluckRemoteUrl(gitConfig);
|
||||
if (originUrl) {
|
||||
return originUrl;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function createGitMeta(
|
||||
directory: string,
|
||||
output: Output
|
||||
output: Output,
|
||||
project?: Project | null
|
||||
): Promise<GitMetadata | undefined> {
|
||||
const remoteUrl = await getRemoteUrl(join(directory, '.git/config'), output);
|
||||
// If a Git repository is already connected via `vc git`, use that remote url
|
||||
let remoteUrl;
|
||||
if (project?.link) {
|
||||
// in the form of org/repo
|
||||
const { repo } = project.link;
|
||||
|
||||
const remoteUrls = await getRemoteUrls(
|
||||
join(directory, '.git/config'),
|
||||
output
|
||||
);
|
||||
if (remoteUrls) {
|
||||
for (const urlValue of Object.values(remoteUrls)) {
|
||||
if (urlValue.includes(repo)) {
|
||||
remoteUrl = urlValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we couldn't get a remote url from the connected repo, default to the origin url
|
||||
if (!remoteUrl) {
|
||||
remoteUrl = await getOriginUrl(join(directory, '.git/config'), output);
|
||||
}
|
||||
// If we can't get the repo URL, then don't return any metadata
|
||||
if (!remoteUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [commit, dirty] = await Promise.all([
|
||||
getLastCommit(directory).catch(err => {
|
||||
output.debug(
|
||||
@@ -96,3 +62,97 @@ export async function createGitMeta(
|
||||
dirty,
|
||||
};
|
||||
}
|
||||
|
||||
function getLastCommit(directory: string): Promise<git.Commit> {
|
||||
return new Promise((resolve, reject) => {
|
||||
git.getLastCommit(
|
||||
(err, commit) => {
|
||||
if (err) return reject(err);
|
||||
resolve(commit);
|
||||
},
|
||||
{ dst: directory }
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function isDirty(directory: string, output: Output): Promise<boolean> {
|
||||
return new Promise(resolve => {
|
||||
exec('git status -s', { cwd: directory }, function (err, stdout, stderr) {
|
||||
let debugMessage = `Failed to determine if Git repo has been modified:`;
|
||||
if (err || stderr) {
|
||||
if (err) debugMessage += `\n${err}`;
|
||||
if (stderr) debugMessage += `\n${stderr.trim()}`;
|
||||
output.debug(debugMessage);
|
||||
return resolve(false);
|
||||
}
|
||||
resolve(stdout.trim().length > 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function parseGitConfig(configPath: string, output: Output) {
|
||||
try {
|
||||
return ini.parse(await fs.readFile(configPath, 'utf-8'));
|
||||
} catch (error) {
|
||||
output.debug(`Error while parsing repo data: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function pluckRemoteUrls(gitConfig: {
|
||||
[key: string]: any;
|
||||
}): { [key: string]: string } | undefined {
|
||||
let remoteUrls: { [key: string]: string } = {};
|
||||
|
||||
for (const key of Object.keys(gitConfig)) {
|
||||
if (key.includes('remote')) {
|
||||
// ex. remote "origin" — matches origin
|
||||
const remoteName = key.match(/(?<=").*(?=")/g)?.[0];
|
||||
const remoteUrl = gitConfig[key]?.url;
|
||||
if (remoteName && remoteUrl) {
|
||||
remoteUrls[remoteName] = remoteUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(remoteUrls).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
return remoteUrls;
|
||||
}
|
||||
|
||||
export async function getRemoteUrls(
|
||||
configPath: string,
|
||||
output: Output
|
||||
): Promise<{ [key: string]: string } | undefined> {
|
||||
const config = await parseGitConfig(configPath, output);
|
||||
if (!config) {
|
||||
return;
|
||||
}
|
||||
|
||||
const remoteUrls = pluckRemoteUrls(config);
|
||||
return remoteUrls;
|
||||
}
|
||||
|
||||
export function pluckOriginUrl(gitConfig: {
|
||||
[key: string]: any;
|
||||
}): string | undefined {
|
||||
// Assuming "origin" is the remote url that the user would want to use
|
||||
return gitConfig['remote "origin"']?.url;
|
||||
}
|
||||
|
||||
export async function getOriginUrl(
|
||||
configPath: string,
|
||||
output: Output
|
||||
): Promise<string | null> {
|
||||
let gitConfig = await parseGitConfig(configPath, output);
|
||||
if (!gitConfig) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const originUrl = pluckOriginUrl(gitConfig);
|
||||
if (originUrl) {
|
||||
return originUrl;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -11,14 +11,11 @@ import cliPkg from '../pkg';
|
||||
|
||||
import cmd from '../output/cmd';
|
||||
import { Output } from '../output';
|
||||
import { getDistTag } from '../get-dist-tag';
|
||||
import { NoBuilderCacheError } from '../errors-ts';
|
||||
|
||||
import * as staticBuilder from './static-builder';
|
||||
import { BuilderWithPackage } from './types';
|
||||
|
||||
type CliPackageJson = typeof cliPkg;
|
||||
|
||||
const require_: typeof require = eval('require');
|
||||
|
||||
const registryTypes = new Set(['version', 'tag', 'range']);
|
||||
@@ -37,8 +34,6 @@ const localBuilders: { [key: string]: BuilderWithPackage } = {
|
||||
'@vercel/static': createStaticBuilder('vercel'),
|
||||
};
|
||||
|
||||
const distTag = getDistTag(cliPkg.version);
|
||||
|
||||
export const cacheDirPromise = prepareCacheDir();
|
||||
export const builderDirPromise = prepareBuilderDir();
|
||||
|
||||
@@ -102,9 +97,8 @@ function parseVersionSafe(rawSpec: string) {
|
||||
|
||||
export function filterPackage(
|
||||
builderSpec: string,
|
||||
distTag: string,
|
||||
buildersPkg: PackageJson,
|
||||
cliPkg: Partial<CliPackageJson>
|
||||
cliPkg: Partial<PackageJson>
|
||||
) {
|
||||
if (builderSpec in localBuilders) return false;
|
||||
const parsed = npa(builderSpec);
|
||||
@@ -126,31 +120,6 @@ export function filterPackage(
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip install of already installed Runtime with tag compatible match
|
||||
if (
|
||||
parsed.name &&
|
||||
parsed.type === 'tag' &&
|
||||
parsed.fetchSpec === distTag &&
|
||||
buildersPkg.dependencies
|
||||
) {
|
||||
const parsedInstalled = npa(
|
||||
`${parsed.name}@${buildersPkg.dependencies[parsed.name]}`
|
||||
);
|
||||
if (parsedInstalled.type !== 'version') {
|
||||
return true;
|
||||
}
|
||||
const semverInstalled = semver.parse(parsedInstalled.rawSpec);
|
||||
if (!semverInstalled) {
|
||||
return true;
|
||||
}
|
||||
if (semverInstalled.prerelease.length > 0) {
|
||||
return semverInstalled.prerelease[0] !== distTag;
|
||||
}
|
||||
if (distTag === 'latest') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -183,7 +152,7 @@ export async function installBuilders(
|
||||
|
||||
// Filter out any packages that come packaged with Vercel CLI
|
||||
const packagesToInstall = packages.filter(p =>
|
||||
filterPackage(p, distTag, buildersPkgBefore, cliPkg)
|
||||
filterPackage(p, buildersPkgBefore, cliPkg)
|
||||
);
|
||||
|
||||
if (packagesToInstall.length === 0) {
|
||||
@@ -392,20 +361,13 @@ export function isBundledBuilder(
|
||||
return false;
|
||||
}
|
||||
|
||||
const bundledVersion = dependencies[parsed.name];
|
||||
if (bundledVersion) {
|
||||
if (parsed.type === 'tag') {
|
||||
if (parsed.fetchSpec === 'canary') {
|
||||
return bundledVersion.includes('canary');
|
||||
} else if (parsed.fetchSpec === 'latest') {
|
||||
return !bundledVersion.includes('canary');
|
||||
}
|
||||
} else if (parsed.type === 'version') {
|
||||
return parsed.fetchSpec === bundledVersion;
|
||||
}
|
||||
}
|
||||
const inCliDependencyList = !!dependencies[parsed.name];
|
||||
const inScope = parsed.scope === '@vercel';
|
||||
const isVersionedReference = ['tag', 'version', 'range'].includes(
|
||||
parsed.type
|
||||
);
|
||||
|
||||
return false;
|
||||
return inCliDependencyList && inScope && isVersionedReference;
|
||||
}
|
||||
|
||||
function getPackageName(
|
||||
|
||||
@@ -4,7 +4,7 @@ import ms from 'ms';
|
||||
import bytes from 'bytes';
|
||||
import { delimiter, dirname, join } from 'path';
|
||||
import { fork, ChildProcess } from 'child_process';
|
||||
import { createFunction } from '@zeit/fun';
|
||||
import { createFunction } from '@vercel/fun';
|
||||
import {
|
||||
Builder,
|
||||
BuildOptions,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import http from 'http';
|
||||
import { ChildProcess } from 'child_process';
|
||||
import { Lambda as FunLambda } from '@zeit/fun';
|
||||
import { Lambda as FunLambda } from '@vercel/fun';
|
||||
import {
|
||||
Builder as BuildConfig,
|
||||
BuildOptions,
|
||||
|
||||
@@ -87,3 +87,18 @@ export async function responseErrorMessage(
|
||||
|
||||
return `${message} (${res.status})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Object with enumberable properties that match
|
||||
* the provided `err` instance, for use with `JSON.stringify()`.
|
||||
*/
|
||||
export function toEnumerableError<E extends Partial<Error>>(err: E) {
|
||||
const enumerable: {
|
||||
[K in keyof E]?: E[K];
|
||||
} = {};
|
||||
enumerable.name = err.name;
|
||||
for (const key of Object.getOwnPropertyNames(err) as (keyof E)[]) {
|
||||
enumerable[key] = err[key];
|
||||
}
|
||||
return enumerable;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ interface ListSeparator {
|
||||
separator: string;
|
||||
}
|
||||
|
||||
type ListChoice = ListEntry | ListSeparator | typeof inquirer.Separator;
|
||||
export type ListChoice = ListEntry | ListSeparator | typeof inquirer.Separator;
|
||||
|
||||
interface ListOptions {
|
||||
message: string;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export const config = {
|
||||
runtime: 'experimental-edge',
|
||||
};
|
||||
|
||||
export default async function edge(request, event) {
|
||||
// nothing returned
|
||||
}
|
||||
@@ -17,6 +17,7 @@ export default async function edge(request, event) {
|
||||
decamelized: decamelize('someCamelCaseThing'),
|
||||
uppercase: upper('someThing'),
|
||||
optionalChaining: request?.doesnotexist ?? 'fallback',
|
||||
ENV_VAR_IN_EDGE: process.env.ENV_VAR_IN_EDGE,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export default function serverless(request, response) {
|
||||
return response.send('hello from a serverless function');
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export const config = {
|
||||
runtime: 'experimental-edge',
|
||||
};
|
||||
|
||||
export default async function edge(request, event) {
|
||||
// no response
|
||||
}
|
||||
@@ -16,7 +16,11 @@ const {
|
||||
|
||||
test('[vercel dev] should support edge functions', async () => {
|
||||
const dir = fixture('edge-function');
|
||||
const { dev, port, readyResolver } = await testFixture(dir);
|
||||
const { dev, port, readyResolver } = await testFixture(dir, {
|
||||
env: {
|
||||
ENV_VAR_IN_EDGE: '1',
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await readyResolver;
|
||||
@@ -42,6 +46,7 @@ test('[vercel dev] should support edge functions', async () => {
|
||||
decamelized: 'some_camel_case_thing',
|
||||
uppercase: 'SOMETHING',
|
||||
optionalChaining: 'fallback',
|
||||
ENV_VAR_IN_EDGE: '1',
|
||||
});
|
||||
} finally {
|
||||
await dev.kill('SIGTERM');
|
||||
@@ -56,6 +61,31 @@ test(
|
||||
})
|
||||
);
|
||||
|
||||
test('[vercel dev] throws an error when an edge function has no response', async () => {
|
||||
const dir = fixture('edge-function-error');
|
||||
const { dev, port, readyResolver } = await testFixture(dir);
|
||||
|
||||
try {
|
||||
await readyResolver;
|
||||
|
||||
let res = await fetch(`http://localhost:${port}/api/edge-no-response`);
|
||||
validateResponseHeaders(res);
|
||||
|
||||
const { stdout, stderr } = await dev.kill('SIGTERM');
|
||||
|
||||
expect(await res.status).toBe(500);
|
||||
expect(await res.text()).toMatch('FUNCTION_INVOCATION_FAILED');
|
||||
expect(stdout).toMatch(
|
||||
/Unhandled rejection: Edge Function "api\/edge-no-response.js" did not return a response./g
|
||||
);
|
||||
expect(stderr).toMatch(
|
||||
/Failed to complete request to \/api\/edge-no-response: Error: socket hang up/g
|
||||
);
|
||||
} finally {
|
||||
await dev.kill('SIGTERM');
|
||||
}
|
||||
});
|
||||
|
||||
test('[vercel dev] should support edge functions returning intentional 500 responses', async () => {
|
||||
const dir = fixture('edge-function');
|
||||
const { dev, port, readyResolver } = await testFixture(dir);
|
||||
|
||||
@@ -442,6 +442,17 @@ test(
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[vercel dev] Middleware that has no response',
|
||||
testFixtureStdio('middleware-no-response', async (testPath: any) => {
|
||||
await testPath(
|
||||
500,
|
||||
'/api/hello',
|
||||
'A server error has occurred\n\nEDGE_FUNCTION_INVOCATION_FAILED'
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[vercel dev] Middleware that does basic rewrite',
|
||||
testFixtureStdio('middleware-rewrite', async (testPath: any) => {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"orgId": ".",
|
||||
"projectId": ".",
|
||||
"settings": {
|
||||
"framework": null
|
||||
}
|
||||
}
|
||||
1
packages/cli/test/fixtures/unit/commands/build/error-vercel-json-validation/index.html
vendored
Normal file
1
packages/cli/test/fixtures/unit/commands/build/error-vercel-json-validation/index.html
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<h1>Vercel</h1>
|
||||
5
packages/cli/test/fixtures/unit/commands/build/error-vercel-json-validation/vercel.json
vendored
Normal file
5
packages/cli/test/fixtures/unit/commands/build/error-vercel-json-validation/vercel.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"functions": {
|
||||
"invalid.js": {}
|
||||
}
|
||||
}
|
||||
9
packages/cli/test/fixtures/unit/commands/build/static-with-pkg/.vercel/project.json
vendored
Normal file
9
packages/cli/test/fixtures/unit/commands/build/static-with-pkg/.vercel/project.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"orgId": ".",
|
||||
"projectId": ".",
|
||||
"settings": {
|
||||
"framework": null,
|
||||
"buildCommand": null,
|
||||
"outputDirectory": "out"
|
||||
}
|
||||
}
|
||||
1
packages/cli/test/fixtures/unit/commands/build/static-with-pkg/index.html
vendored
Normal file
1
packages/cli/test/fixtures/unit/commands/build/static-with-pkg/index.html
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<h1>Vercel</h1>
|
||||
5
packages/cli/test/fixtures/unit/commands/build/static-with-pkg/package.json
vendored
Normal file
5
packages/cli/test/fixtures/unit/commands/build/static-with-pkg/package.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
}
|
||||
}
|
||||
1
packages/cli/test/fixtures/unit/commands/git/connect/multiple-remotes/.gitignore
generated
vendored
Normal file
1
packages/cli/test/fixtures/unit/commands/git/connect/multiple-remotes/.gitignore
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!.vercel
|
||||
4
packages/cli/test/fixtures/unit/commands/git/connect/multiple-remotes/.vercel/project.json
generated
vendored
Normal file
4
packages/cli/test/fixtures/unit/commands/git/connect/multiple-remotes/.vercel/project.json
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"orgId": "team_dummy",
|
||||
"projectId": "multiple-remotes"
|
||||
}
|
||||
1
packages/cli/test/fixtures/unit/commands/git/connect/multiple-remotes/git/HEAD
generated
vendored
Normal file
1
packages/cli/test/fixtures/unit/commands/git/connect/multiple-remotes/git/HEAD
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
ref: refs/heads/master
|
||||
13
packages/cli/test/fixtures/unit/commands/git/connect/multiple-remotes/git/config
generated
vendored
Normal file
13
packages/cli/test/fixtures/unit/commands/git/connect/multiple-remotes/git/config
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
ignorecase = true
|
||||
precomposeunicode = true
|
||||
[remote "origin"]
|
||||
url = https://github.com/user/repo.git
|
||||
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||
[remote "secondary"]
|
||||
url = https://github.com/user/repo2.git
|
||||
fetch = +refs/heads/*:refs/remotes/secondary/*
|
||||
1
packages/cli/test/fixtures/unit/commands/git/connect/multiple-remotes/git/description
generated
vendored
Normal file
1
packages/cli/test/fixtures/unit/commands/git/connect/multiple-remotes/git/description
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
||||
1
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/.gitignore
vendored
Normal file
1
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!.vercel
|
||||
4
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/.vercel/project.json
vendored
Normal file
4
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/.vercel/project.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"orgId": "team_dummy",
|
||||
"projectId": "connected-repo"
|
||||
}
|
||||
1
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/COMMIT_EDITMSG
generated
vendored
Normal file
1
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/COMMIT_EDITMSG
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
add hi
|
||||
1
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/HEAD
generated
vendored
Normal file
1
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/HEAD
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
ref: refs/heads/master
|
||||
13
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/config
generated
vendored
Normal file
13
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/config
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
ignorecase = true
|
||||
precomposeunicode = true
|
||||
[remote "origin"]
|
||||
url = https://github.com/user/repo
|
||||
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||
[remote "secondary"]
|
||||
url = https://github.com/user/repo2
|
||||
fetch = +refs/heads/*:refs/remotes/secondary/*
|
||||
1
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/description
generated
vendored
Normal file
1
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/description
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
||||
BIN
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057
generated
vendored
Normal file
BIN
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057
generated
vendored
Normal file
Binary file not shown.
BIN
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/objects/80/50816205303e5957b2909083c50677930d5b29
generated
vendored
Normal file
BIN
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/objects/80/50816205303e5957b2909083c50677930d5b29
generated
vendored
Normal file
Binary file not shown.
BIN
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/objects/b2/e4d98c09ed53967b0a8f67c293c04ca4173438
generated
vendored
Normal file
BIN
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/objects/b2/e4d98c09ed53967b0a8f67c293c04ca4173438
generated
vendored
Normal file
Binary file not shown.
1
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/refs/heads/master
generated
vendored
Normal file
1
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/git/refs/heads/master
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
8050816205303e5957b2909083c50677930d5b29
|
||||
1
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/index.txt
vendored
Normal file
1
packages/cli/test/fixtures/unit/create-git-meta/connected-repo/index.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
hi
|
||||
1
packages/cli/test/fixtures/unit/create-git-meta/multiple-remotes/git/HEAD
generated
vendored
Normal file
1
packages/cli/test/fixtures/unit/create-git-meta/multiple-remotes/git/HEAD
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
ref: refs/heads/master
|
||||
13
packages/cli/test/fixtures/unit/create-git-meta/multiple-remotes/git/config
generated
vendored
Normal file
13
packages/cli/test/fixtures/unit/create-git-meta/multiple-remotes/git/config
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
[core]
|
||||
repositoryformatversion = 0
|
||||
filemode = true
|
||||
bare = false
|
||||
logallrefupdates = true
|
||||
ignorecase = true
|
||||
precomposeunicode = true
|
||||
[remote "origin"]
|
||||
url = https://github.com/user/repo
|
||||
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||
[remote "secondary"]
|
||||
url = https://github.com/user/repo2
|
||||
fetch = +refs/heads/*:refs/remotes/secondary/*
|
||||
1
packages/cli/test/fixtures/unit/create-git-meta/multiple-remotes/git/description
generated
vendored
Normal file
1
packages/cli/test/fixtures/unit/create-git-meta/multiple-remotes/git/description
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Unnamed repository; edit this file 'description' to name the repository.
|
||||
@@ -622,6 +622,32 @@ describe('build', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('should store `detectBuilders()` error in `builds.json`', async () => {
|
||||
const cwd = fixture('error-vercel-json-validation');
|
||||
const output = join(cwd, '.vercel/output');
|
||||
try {
|
||||
process.chdir(cwd);
|
||||
const exitCode = await build(client);
|
||||
expect(exitCode).toEqual(1);
|
||||
|
||||
// `builds.json` contains top-level "error" property
|
||||
const builds = await fs.readJSON(join(output, 'builds.json'));
|
||||
expect(builds.builds).toBeUndefined();
|
||||
|
||||
expect(builds.error.code).toEqual('invalid_function');
|
||||
expect(builds.error.message).toEqual(
|
||||
'Function must contain at least one property.'
|
||||
);
|
||||
|
||||
// `config.json` contains `version`
|
||||
const configJson = await fs.readJSON(join(output, 'config.json'));
|
||||
expect(configJson.version).toBe(3);
|
||||
} finally {
|
||||
process.chdir(originalCwd);
|
||||
delete process.env.__VERCEL_BUILD_RUNNING;
|
||||
}
|
||||
});
|
||||
|
||||
it('should store Builder error in `builds.json`', async () => {
|
||||
const cwd = fixture('node-error');
|
||||
const output = join(cwd, '.vercel/output');
|
||||
@@ -643,7 +669,7 @@ describe('build', () => {
|
||||
expect(errorBuilds[0].error.hideStackTrace).toEqual(true);
|
||||
expect(errorBuilds[0].error.code).toEqual('NODE_TYPESCRIPT_ERROR');
|
||||
|
||||
// `config.json`` contains `version`
|
||||
// `config.json` contains `version`
|
||||
const configJson = await fs.readJSON(join(output, 'config.json'));
|
||||
expect(configJson.version).toBe(3);
|
||||
} finally {
|
||||
@@ -651,4 +677,35 @@ describe('build', () => {
|
||||
delete process.env.__VERCEL_BUILD_RUNNING;
|
||||
}
|
||||
});
|
||||
|
||||
it('should allow for missing "build" script', async () => {
|
||||
const cwd = fixture('static-with-pkg');
|
||||
const output = join(cwd, '.vercel/output');
|
||||
try {
|
||||
process.chdir(cwd);
|
||||
const exitCode = await build(client);
|
||||
expect(exitCode).toEqual(0);
|
||||
|
||||
// `builds.json` says that "@vercel/static" was run
|
||||
const builds = await fs.readJSON(join(output, 'builds.json'));
|
||||
expect(builds).toMatchObject({
|
||||
target: 'preview',
|
||||
builds: [
|
||||
{
|
||||
require: '@vercel/static',
|
||||
apiVersion: 2,
|
||||
src: '**',
|
||||
use: '@vercel/static',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// "static" directory contains static files
|
||||
const files = await fs.readdir(join(output, 'static'));
|
||||
expect(files.sort()).toEqual(['index.html', 'package.json']);
|
||||
} finally {
|
||||
process.chdir(originalCwd);
|
||||
delete process.env.__VERCEL_BUILD_RUNNING;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -57,6 +57,69 @@ describe('env', () => {
|
||||
expect(devFileHasDevEnv).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should use given environment', async () => {
|
||||
const cwd = setupFixture('vercel-env-pull');
|
||||
useUser();
|
||||
useTeams('team_dummy');
|
||||
useProject({
|
||||
...defaultProject,
|
||||
id: 'vercel-env-pull',
|
||||
name: 'vercel-env-pull',
|
||||
});
|
||||
|
||||
client.setArgv(
|
||||
'env',
|
||||
'pull',
|
||||
'.env.production',
|
||||
'--environment',
|
||||
'production',
|
||||
'--cwd',
|
||||
cwd
|
||||
);
|
||||
const exitCodePromise = env(client);
|
||||
await expect(client.stderr).toOutput(
|
||||
`Downloading "production" Environment Variables for Project vercel-env-pull`
|
||||
);
|
||||
await expect(client.stderr).toOutput('Created .env.production file');
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
|
||||
const rawProdEnv = await fs.readFile(path.join(cwd, '.env.production'));
|
||||
|
||||
// check for development env value
|
||||
const envFileHasEnv = rawProdEnv
|
||||
.toString()
|
||||
.includes('REDIS_CONNECTION_STRING');
|
||||
expect(envFileHasEnv).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should throw an error when it does not recognize given environment', async () => {
|
||||
const cwd = setupFixture('vercel-env-pull');
|
||||
useUser();
|
||||
useTeams('team_dummy');
|
||||
useProject({
|
||||
...defaultProject,
|
||||
id: 'vercel-env-pull',
|
||||
name: 'vercel-env-pull',
|
||||
});
|
||||
|
||||
client.setArgv(
|
||||
'env',
|
||||
'pull',
|
||||
'.env.production',
|
||||
'--environment',
|
||||
'something-invalid',
|
||||
'--cwd',
|
||||
cwd
|
||||
);
|
||||
|
||||
const exitCodePromise = env(client);
|
||||
await expect(client.stderr).toOutput(
|
||||
`Invalid environment \`something-invalid\`. Valid options: <production | preview | development>`
|
||||
);
|
||||
|
||||
await expect(exitCodePromise).resolves.toEqual(1);
|
||||
});
|
||||
|
||||
it('should expose production system env variables', async () => {
|
||||
const cwd = setupFixture('vercel-env-pull');
|
||||
useUser();
|
||||
|
||||
@@ -25,7 +25,7 @@ describe('git', () => {
|
||||
id: 'unlinked',
|
||||
name: 'unlinked',
|
||||
});
|
||||
client.setArgv('projects', 'connect');
|
||||
client.setArgv('git', 'connect');
|
||||
const gitPromise = git(client);
|
||||
|
||||
await expect(client.stderr).toOutput('Set up');
|
||||
@@ -40,7 +40,7 @@ describe('git', () => {
|
||||
client.stdin.write('y\n');
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
`Identified Git remote "origin": https://github.com/user/repo.git`
|
||||
`Connecting Git remote: https://github.com/user/repo.git`
|
||||
);
|
||||
|
||||
const exitCode = await gitPromise;
|
||||
@@ -76,7 +76,7 @@ describe('git', () => {
|
||||
id: 'no-git-config',
|
||||
name: 'no-git-config',
|
||||
});
|
||||
client.setArgv('projects', 'connect', '--confirm');
|
||||
client.setArgv('git', 'connect', '--confirm');
|
||||
const exitCode = await git(client);
|
||||
expect(exitCode).toEqual(1);
|
||||
await expect(client.stderr).toOutput(
|
||||
@@ -98,11 +98,11 @@ describe('git', () => {
|
||||
id: 'no-remote-url',
|
||||
name: 'no-remote-url',
|
||||
});
|
||||
client.setArgv('projects', 'connect', '--confirm');
|
||||
client.setArgv('git', 'connect', '--confirm');
|
||||
const exitCode = await git(client);
|
||||
expect(exitCode).toEqual(1);
|
||||
await expect(client.stderr).toOutput(
|
||||
`Error! No remote origin URL found in your Git config. Make sure you've configured a remote repo in your local Git config. Run \`git remote --help\` for more details.`
|
||||
`Error! No remote URLs found in your Git config. Make sure you've configured a remote repo in your local Git config. Run \`git remote --help\` for more details.`
|
||||
);
|
||||
} finally {
|
||||
await fs.rename(join(cwd, '.git'), join(cwd, 'git'));
|
||||
@@ -121,15 +121,15 @@ describe('git', () => {
|
||||
id: 'bad-remote-url',
|
||||
name: 'bad-remote-url',
|
||||
});
|
||||
client.setArgv('projects', 'connect', '--confirm');
|
||||
client.setArgv('git', 'connect', '--confirm');
|
||||
const exitCode = await git(client);
|
||||
expect(exitCode).toEqual(1);
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
`Identified Git remote "origin": bababooey`
|
||||
`Connecting Git remote: bababooey`
|
||||
);
|
||||
await expect(client.stderr).toOutput(
|
||||
`Error! Failed to parse Git repo data from the following remote URL in your Git config: bababooey\n`
|
||||
`Error! Failed to parse Git repo data from the following remote URL: bababooey\n`
|
||||
);
|
||||
} finally {
|
||||
await fs.rename(join(cwd, '.git'), join(cwd, 'git'));
|
||||
@@ -148,11 +148,11 @@ describe('git', () => {
|
||||
id: 'new-connection',
|
||||
name: 'new-connection',
|
||||
});
|
||||
client.setArgv('projects', 'connect', '--confirm');
|
||||
client.setArgv('git', 'connect', '--confirm');
|
||||
const gitPromise = git(client);
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
`Identified Git remote "origin": https://github.com/user/repo`
|
||||
`Connecting Git remote: https://github.com/user/repo`
|
||||
);
|
||||
await expect(client.stderr).toOutput(
|
||||
`> Connected GitHub repository user/repo!\n`
|
||||
@@ -201,11 +201,11 @@ describe('git', () => {
|
||||
updatedAt: 1656109539791,
|
||||
};
|
||||
|
||||
client.setArgv('projects', 'connect', '--confirm');
|
||||
client.setArgv('git', 'connect', '--confirm');
|
||||
const gitPromise = git(client);
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
`Identified Git remote "origin": https://github.com/user2/repo2`
|
||||
`Connecting Git remote: https://github.com/user2/repo2`
|
||||
);
|
||||
await expect(client.stderr).toOutput(
|
||||
`> Connected GitHub repository user2/repo2!\n`
|
||||
@@ -253,11 +253,11 @@ describe('git', () => {
|
||||
createdAt: 1656109539791,
|
||||
updatedAt: 1656109539791,
|
||||
};
|
||||
client.setArgv('projects', 'connect', '--confirm');
|
||||
client.setArgv('git', 'connect', '--confirm');
|
||||
const gitPromise = git(client);
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
`Identified Git remote "origin": https://github.com/user/repo`
|
||||
`Connecting Git remote: https://github.com/user/repo`
|
||||
);
|
||||
await expect(client.stderr).toOutput(
|
||||
`> user/repo is already connected to your project.\n`
|
||||
@@ -283,11 +283,11 @@ describe('git', () => {
|
||||
name: 'invalid-repo',
|
||||
});
|
||||
|
||||
client.setArgv('projects', 'connect', '--confirm');
|
||||
client.setArgv('git', 'connect', '--confirm');
|
||||
const gitPromise = git(client);
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
`Identified Git remote "origin": https://github.com/laksfj/asdgklsadkl`
|
||||
`Connecting Git remote: https://github.com/laksfj/asdgklsadkl`
|
||||
);
|
||||
await expect(client.stderr).toOutput(
|
||||
`Failed to link laksfj/asdgklsadkl. Make sure there aren't any typos and that you have access to the repository if it's private.`
|
||||
@@ -300,6 +300,56 @@ describe('git', () => {
|
||||
process.chdir(originalCwd);
|
||||
}
|
||||
});
|
||||
it('should connect the default option of multiple remotes', async () => {
|
||||
const cwd = fixture('multiple-remotes');
|
||||
try {
|
||||
process.chdir(cwd);
|
||||
await fs.rename(join(cwd, 'git'), join(cwd, '.git'));
|
||||
useUser();
|
||||
useTeams('team_dummy');
|
||||
useProject({
|
||||
...defaultProject,
|
||||
id: 'multiple-remotes',
|
||||
name: 'multiple-remotes',
|
||||
});
|
||||
|
||||
client.setArgv('git', 'connect');
|
||||
const gitPromise = git(client);
|
||||
|
||||
await expect(client.stderr).toOutput('Found multiple remote URLs.');
|
||||
await expect(client.stderr).toOutput(
|
||||
'Which remote do you want to connect?'
|
||||
);
|
||||
|
||||
client.stdin.write('\r');
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
'Connecting Git remote: https://github.com/user/repo.git'
|
||||
);
|
||||
await expect(client.stderr).toOutput(
|
||||
'Connected GitHub repository user/repo!'
|
||||
);
|
||||
|
||||
const exitCode = await gitPromise;
|
||||
expect(exitCode).toEqual(0);
|
||||
|
||||
const project: Project = await client.fetch(
|
||||
`/v8/projects/multiple-remotes`
|
||||
);
|
||||
expect(project.link).toMatchObject({
|
||||
type: 'github',
|
||||
repo: 'user/repo',
|
||||
repoId: 1010,
|
||||
gitCredentialId: '',
|
||||
sourceless: true,
|
||||
createdAt: 1656109539791,
|
||||
updatedAt: 1656109539791,
|
||||
});
|
||||
} finally {
|
||||
await fs.rename(join(cwd, '.git'), join(cwd, 'git'));
|
||||
process.chdir(originalCwd);
|
||||
}
|
||||
});
|
||||
});
|
||||
describe('disconnect', () => {
|
||||
const originalCwd = process.cwd();
|
||||
|
||||
@@ -4,31 +4,58 @@ import os from 'os';
|
||||
import { getWriteableDirectory } from '@vercel/build-utils';
|
||||
import {
|
||||
createGitMeta,
|
||||
getRemoteUrl,
|
||||
getOriginUrl,
|
||||
getRemoteUrls,
|
||||
isDirty,
|
||||
} from '../../../../src/util/create-git-meta';
|
||||
import { client } from '../../../mocks/client';
|
||||
import { parseRepoUrl } from '../../../../src/util/projects/connect-git-provider';
|
||||
import { readOutputStream } from '../../../helpers/read-output-stream';
|
||||
import { useUser } from '../../../mocks/user';
|
||||
import { defaultProject, useProject } from '../../../mocks/project';
|
||||
import { Project } from '../../../../src/types';
|
||||
|
||||
const fixture = (name: string) =>
|
||||
join(__dirname, '../../../fixtures/unit/create-git-meta', name);
|
||||
|
||||
describe('getRemoteUrl', () => {
|
||||
describe('getOriginUrl', () => {
|
||||
it('does not provide data for no-origin', async () => {
|
||||
const configPath = join(fixture('no-origin'), 'git/config');
|
||||
const data = await getRemoteUrl(configPath, client.output);
|
||||
const data = await getOriginUrl(configPath, client.output);
|
||||
expect(data).toBeNull();
|
||||
});
|
||||
it('displays debug message when repo data cannot be parsed', async () => {
|
||||
const dir = await getWriteableDirectory();
|
||||
client.output.debugEnabled = true;
|
||||
const data = await getRemoteUrl(join(dir, 'git/config'), client.output);
|
||||
const data = await getOriginUrl(join(dir, 'git/config'), client.output);
|
||||
expect(data).toBeNull();
|
||||
await expect(client.stderr).toOutput('Error while parsing repo data');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRemoteUrls', () => {
|
||||
it('does not provide data when there are no remote urls', async () => {
|
||||
const configPath = join(fixture('no-origin'), 'git/config');
|
||||
const data = await getRemoteUrls(configPath, client.output);
|
||||
expect(data).toBeUndefined();
|
||||
});
|
||||
it('returns an object when multiple urls are present', async () => {
|
||||
const configPath = join(fixture('multiple-remotes'), 'git/config');
|
||||
const data = await getRemoteUrls(configPath, client.output);
|
||||
expect(data).toMatchObject({
|
||||
origin: 'https://github.com/user/repo',
|
||||
secondary: 'https://github.com/user/repo2',
|
||||
});
|
||||
});
|
||||
it('returns an object for origin url', async () => {
|
||||
const configPath = join(fixture('test-github'), 'git/config');
|
||||
const data = await getRemoteUrls(configPath, client.output);
|
||||
expect(data).toMatchObject({
|
||||
origin: 'https://github.com/user/repo.git',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseRepoUrl', () => {
|
||||
it('should be null when a url does not match the regex', () => {
|
||||
const parsedUrl = parseRepoUrl('https://examplecom/foo');
|
||||
@@ -244,4 +271,45 @@ describe('createGitMeta', () => {
|
||||
await fs.remove(tmpDir);
|
||||
}
|
||||
});
|
||||
it('uses the repo url for a connected project', async () => {
|
||||
const originalCwd = process.cwd();
|
||||
const directory = fixture('connected-repo');
|
||||
try {
|
||||
process.chdir(directory);
|
||||
await fs.rename(join(directory, 'git'), join(directory, '.git'));
|
||||
|
||||
useUser();
|
||||
const project = useProject({
|
||||
...defaultProject,
|
||||
id: 'connected-repo',
|
||||
name: 'connected-repo',
|
||||
});
|
||||
project.project.link = {
|
||||
type: 'github',
|
||||
repo: 'user/repo2',
|
||||
repoId: 1010,
|
||||
gitCredentialId: '',
|
||||
sourceless: true,
|
||||
createdAt: 1656109539791,
|
||||
updatedAt: 1656109539791,
|
||||
};
|
||||
|
||||
const data = await createGitMeta(
|
||||
directory,
|
||||
client.output,
|
||||
project.project as Project
|
||||
);
|
||||
expect(data).toMatchObject({
|
||||
remoteUrl: 'https://github.com/user/repo2',
|
||||
commitAuthorName: 'Matthew Stanciu',
|
||||
commitMessage: 'add hi',
|
||||
commitRef: 'master',
|
||||
commitSha: '8050816205303e5957b2909083c50677930d5b29',
|
||||
dirty: true,
|
||||
});
|
||||
} finally {
|
||||
await fs.rename(join(directory, '.git'), join(directory, 'git'));
|
||||
process.chdir(originalCwd);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,19 +6,25 @@ import {
|
||||
} from '../../../../src/util/dev/builder-cache';
|
||||
|
||||
describe('filterPackage', () => {
|
||||
it('should filter install "latest", cached canary', () => {
|
||||
const cliPkg = {
|
||||
dependencies: {
|
||||
'@vercel/build-utils': '0.0.1',
|
||||
},
|
||||
};
|
||||
|
||||
it('should filter package that does not appear in CLI package.json', () => {
|
||||
const result = filterPackage('@vercel/other', {}, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it('should not filter "latest", cached canary', () => {
|
||||
const buildersPkg = {
|
||||
dependencies: {
|
||||
'@vercel/build-utils': '0.0.1-canary.0',
|
||||
},
|
||||
};
|
||||
const result = filterPackage(
|
||||
'@vercel/build-utils',
|
||||
'canary',
|
||||
buildersPkg,
|
||||
{}
|
||||
);
|
||||
expect(result).toEqual(true);
|
||||
const result = filterPackage('@vercel/build-utils', buildersPkg, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should filter install "canary", cached stable', () => {
|
||||
@@ -29,11 +35,10 @@ describe('filterPackage', () => {
|
||||
};
|
||||
const result = filterPackage(
|
||||
'@vercel/build-utils@canary',
|
||||
'latest',
|
||||
buildersPkg,
|
||||
{}
|
||||
cliPkg
|
||||
);
|
||||
expect(result).toEqual(true);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should filter install "latest", cached stable', () => {
|
||||
@@ -42,12 +47,7 @@ describe('filterPackage', () => {
|
||||
'@vercel/build-utils': '0.0.1',
|
||||
},
|
||||
};
|
||||
const result = filterPackage(
|
||||
'@vercel/build-utils',
|
||||
'latest',
|
||||
buildersPkg,
|
||||
{}
|
||||
);
|
||||
const result = filterPackage('@vercel/build-utils', buildersPkg, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
@@ -59,9 +59,8 @@ describe('filterPackage', () => {
|
||||
};
|
||||
const result = filterPackage(
|
||||
'@vercel/build-utils@canary',
|
||||
'canary',
|
||||
buildersPkg,
|
||||
{}
|
||||
cliPkg
|
||||
);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
@@ -72,12 +71,7 @@ describe('filterPackage', () => {
|
||||
'@vercel/build-utils': '0.0.1',
|
||||
},
|
||||
};
|
||||
const result = filterPackage(
|
||||
'https://tarball.now.sh',
|
||||
'latest',
|
||||
buildersPkg,
|
||||
{}
|
||||
);
|
||||
const result = filterPackage('https://tarball.now.sh', buildersPkg, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
@@ -87,27 +81,7 @@ describe('filterPackage', () => {
|
||||
'@vercel/build-utils': '0.0.1-canary.0',
|
||||
},
|
||||
};
|
||||
const result = filterPackage(
|
||||
'https://tarball.now.sh',
|
||||
'canary',
|
||||
buildersPkg,
|
||||
{}
|
||||
);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it('should filter install "latest", cached URL - stable', () => {
|
||||
const buildersPkg = {
|
||||
dependencies: {
|
||||
'@vercel/build-utils': 'https://tarball.now.sh',
|
||||
},
|
||||
};
|
||||
const result = filterPackage(
|
||||
'@vercel/build-utils',
|
||||
'latest',
|
||||
buildersPkg,
|
||||
{}
|
||||
);
|
||||
const result = filterPackage('https://tarball.now.sh', buildersPkg, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
@@ -117,13 +91,8 @@ describe('filterPackage', () => {
|
||||
'@vercel/build-utils': 'https://tarball.now.sh',
|
||||
},
|
||||
};
|
||||
const result = filterPackage(
|
||||
'@vercel/build-utils',
|
||||
'canary',
|
||||
buildersPkg,
|
||||
{}
|
||||
);
|
||||
expect(result).toEqual(true);
|
||||
const result = filterPackage('@vercel/build-utils', buildersPkg, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should filter install not bundled version, cached same version', () => {
|
||||
@@ -134,9 +103,8 @@ describe('filterPackage', () => {
|
||||
};
|
||||
const result = filterPackage(
|
||||
'not-bundled-package@0.0.1',
|
||||
'_',
|
||||
buildersPkg,
|
||||
{}
|
||||
cliPkg
|
||||
);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
@@ -149,9 +117,8 @@ describe('filterPackage', () => {
|
||||
};
|
||||
const result = filterPackage(
|
||||
'not-bundled-package@0.0.1',
|
||||
'_',
|
||||
buildersPkg,
|
||||
{}
|
||||
cliPkg
|
||||
);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
@@ -162,7 +129,7 @@ describe('filterPackage', () => {
|
||||
'not-bundled-package': '0.0.1',
|
||||
},
|
||||
};
|
||||
const result = filterPackage('not-bundled-package', '_', buildersPkg, {});
|
||||
const result = filterPackage('not-bundled-package', buildersPkg, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
@@ -174,9 +141,8 @@ describe('filterPackage', () => {
|
||||
};
|
||||
const result = filterPackage(
|
||||
'not-bundled-package@alpha',
|
||||
'_',
|
||||
buildersPkg,
|
||||
{}
|
||||
cliPkg
|
||||
);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
@@ -213,89 +179,57 @@ describe('getBuildUtils', () => {
|
||||
});
|
||||
|
||||
describe('isBundledBuilder', () => {
|
||||
it('should work with "stable" releases', () => {
|
||||
const cliPkg = {
|
||||
dependencies: {
|
||||
'@vercel/node': '1.6.1',
|
||||
},
|
||||
};
|
||||
const cliPkg = {
|
||||
dependencies: {
|
||||
'@vercel/node': '0.0.1',
|
||||
},
|
||||
};
|
||||
|
||||
// "canary" tag
|
||||
{
|
||||
const parsed = npa('@vercel/node@canary');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
}
|
||||
|
||||
// "latest" tag
|
||||
{
|
||||
const parsed = npa('@vercel/node');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
}
|
||||
|
||||
// specific matching version
|
||||
{
|
||||
const parsed = npa('@vercel/node@1.6.1');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
}
|
||||
|
||||
// specific non-matching version
|
||||
{
|
||||
const parsed = npa('@vercel/node@1.6.0');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
}
|
||||
|
||||
// URL
|
||||
{
|
||||
const parsed = npa('https://example.com');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
}
|
||||
it('should not detect when dependency does not appear in CLI package.json', () => {
|
||||
const parsed = npa('@vercel/node');
|
||||
const result = isBundledBuilder(parsed, {});
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should work with "canary" releases', () => {
|
||||
const cliPkg = {
|
||||
dependencies: {
|
||||
'@vercel/node': '1.6.1-canary.0',
|
||||
},
|
||||
};
|
||||
it('should detect "canary" tagged releases', () => {
|
||||
const parsed = npa('@vercel/node@canary');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
// "canary" tag
|
||||
{
|
||||
const parsed = npa('@vercel/node@canary');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
}
|
||||
it('should detect "canary" versioned releases', () => {
|
||||
const parsed = npa('@vercel/node@1.6.1-canary.0');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
// "latest" tag
|
||||
{
|
||||
const parsed = npa('@vercel/node');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
}
|
||||
it('should detect latest releases', () => {
|
||||
const parsed = npa('@vercel/node');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
// specific matching version
|
||||
{
|
||||
const parsed = npa('@vercel/node@1.6.1-canary.0');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
}
|
||||
it('should detect "latest" tagged releases', () => {
|
||||
const parsed = npa('@vercel/node@latest');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
// specific non-matching version
|
||||
{
|
||||
const parsed = npa('@vercel/node@1.5.2-canary.9');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
}
|
||||
it('should detect versioned releases', () => {
|
||||
const parsed = npa('@vercel/node@1.6.1');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
// URL
|
||||
{
|
||||
const parsed = npa('https://example.com');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
}
|
||||
it('should NOT detect URL releases', () => {
|
||||
const parsed = npa('https://example.com');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should NOT detect git url releases', () => {
|
||||
const parsed = npa('git://example.com/repo.git');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,7 +2,11 @@ import fetch from 'node-fetch';
|
||||
import listen from 'async-listen';
|
||||
import { createServer, IncomingMessage, Server, ServerResponse } from 'http';
|
||||
import { JSONValue } from '../../../src/types';
|
||||
import { responseError, responseErrorMessage } from '../../../src/util/error';
|
||||
import {
|
||||
responseError,
|
||||
responseErrorMessage,
|
||||
toEnumerableError,
|
||||
} from '../../../src/util/error';
|
||||
|
||||
const send = (res: ServerResponse, statusCode: number, body: JSONValue) => {
|
||||
res.statusCode = statusCode;
|
||||
@@ -10,7 +14,7 @@ const send = (res: ServerResponse, statusCode: number, body: JSONValue) => {
|
||||
res.end(JSON.stringify(body));
|
||||
};
|
||||
|
||||
describe('responseError', () => {
|
||||
describe('responseError()', () => {
|
||||
let url: string;
|
||||
let server: Server;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
@@ -187,3 +191,43 @@ describe('responseError', () => {
|
||||
expect(formatted.retryAfter).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('toEnumerableError()', () => {
|
||||
it('should JSON stringify Error', () => {
|
||||
const err = new Error('An error');
|
||||
const enumerable = toEnumerableError(err);
|
||||
expect(JSON.stringify(err)).toEqual('{}');
|
||||
|
||||
// Delete `stack` since it makes stringify nondeterministic
|
||||
// (due to filenames / line numbers)
|
||||
expect(typeof enumerable.stack).toEqual('string');
|
||||
delete enumerable.stack;
|
||||
|
||||
expect(JSON.stringify(enumerable)).toEqual(
|
||||
'{"name":"Error","message":"An error"}'
|
||||
);
|
||||
});
|
||||
|
||||
it('should JSON stringify Error with custom properties', () => {
|
||||
const err = new Error('An error');
|
||||
Object.defineProperty(err, 'custom', {
|
||||
enumerable: false,
|
||||
value: 'value',
|
||||
});
|
||||
Object.defineProperty(err, 'userError', {
|
||||
enumerable: false,
|
||||
value: true,
|
||||
});
|
||||
const enumerable = toEnumerableError(err);
|
||||
expect(JSON.stringify(err)).toEqual('{}');
|
||||
|
||||
// Delete `stack` since it makes stringify undeterministinc
|
||||
// (due to filenames / line numbers)
|
||||
expect(typeof enumerable.stack).toEqual('string');
|
||||
delete enumerable.stack;
|
||||
|
||||
expect(JSON.stringify(enumerable)).toEqual(
|
||||
'{"name":"Error","message":"An error","custom":"value","userError":true}'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/client",
|
||||
"version": "12.1.2",
|
||||
"version": "12.1.3",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://vercel.com",
|
||||
@@ -42,7 +42,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "5.0.3",
|
||||
"@vercel/build-utils": "5.0.4",
|
||||
"@vercel/routing-utils": "2.0.0",
|
||||
"@zeit/fetch": "5.2.0",
|
||||
"async-retry": "1.2.3",
|
||||
@@ -51,7 +51,7 @@
|
||||
"ignore": "4.0.6",
|
||||
"minimatch": "5.0.1",
|
||||
"ms": "2.1.2",
|
||||
"node-fetch": "2.6.1",
|
||||
"node-fetch": "2.6.7",
|
||||
"querystring": "^0.2.0",
|
||||
"sleep-promise": "8.0.1"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/go",
|
||||
"version": "2.0.7",
|
||||
"version": "2.0.8",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
|
||||
@@ -25,7 +25,7 @@
|
||||
"@types/fs-extra": "^5.0.5",
|
||||
"@types/node-fetch": "^2.3.0",
|
||||
"@types/tar": "^4.0.0",
|
||||
"@vercel/build-utils": "5.0.3",
|
||||
"@vercel/build-utils": "5.0.4",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"async-retry": "1.3.1",
|
||||
"execa": "^1.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/hydrogen",
|
||||
"version": "0.0.4",
|
||||
"version": "0.0.5",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"homepage": "https://vercel.com/docs",
|
||||
@@ -22,7 +22,7 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "27.5.1",
|
||||
"@types/node": "*",
|
||||
"@vercel/build-utils": "5.0.3",
|
||||
"@vercel/build-utils": "5.0.4",
|
||||
"typescript": "4.6.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/next",
|
||||
"version": "3.1.7",
|
||||
"version": "3.1.8",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
||||
@@ -45,7 +45,7 @@
|
||||
"@types/semver": "6.0.0",
|
||||
"@types/text-table": "0.2.1",
|
||||
"@types/webpack-sources": "3.2.0",
|
||||
"@vercel/build-utils": "5.0.3",
|
||||
"@vercel/build-utils": "5.0.4",
|
||||
"@vercel/nft": "0.20.1",
|
||||
"@vercel/routing-utils": "2.0.0",
|
||||
"async-sema": "3.0.1",
|
||||
|
||||
@@ -57,6 +57,7 @@ const CORRECT_NOT_FOUND_ROUTES_VERSION = 'v12.0.1';
|
||||
const CORRECT_MIDDLEWARE_ORDER_VERSION = 'v12.1.7-canary.29';
|
||||
const NEXT_DATA_MIDDLEWARE_RESOLVING_VERSION = 'v12.1.7-canary.33';
|
||||
const EMPTY_ALLOW_QUERY_FOR_PRERENDERED_VERSION = 'v12.2.0';
|
||||
const CORRECTED_MANIFESTS_VERSION = 'v12.2.0';
|
||||
|
||||
export async function serverBuild({
|
||||
dynamicPages,
|
||||
@@ -146,6 +147,10 @@ export async function serverBuild({
|
||||
nextVersion,
|
||||
CORRECT_MIDDLEWARE_ORDER_VERSION
|
||||
);
|
||||
const isCorrectManifests = semver.gte(
|
||||
nextVersion,
|
||||
CORRECTED_MANIFESTS_VERSION
|
||||
);
|
||||
let hasStatic500 = !!staticPages[path.join(entryDirectory, '500')];
|
||||
|
||||
if (lambdaPageKeys.length === 0) {
|
||||
@@ -409,7 +414,7 @@ export async function serverBuild({
|
||||
fsPath = path.join(requiredServerFilesManifest.appDir, file);
|
||||
}
|
||||
|
||||
const relativePath = path.join(path.relative(baseDir, fsPath));
|
||||
const relativePath = path.relative(baseDir, fsPath);
|
||||
const { mode } = await fs.lstat(fsPath);
|
||||
lstatSema.release();
|
||||
|
||||
@@ -676,18 +681,80 @@ export async function serverBuild({
|
||||
);
|
||||
|
||||
for (const group of combinedGroups) {
|
||||
const groupPageFiles: { [key: string]: PseudoFile } = {};
|
||||
|
||||
for (const page of [...group.pages, ...internalPages]) {
|
||||
const pageFileName = path.normalize(
|
||||
path.relative(baseDir, lambdaPages[page].fsPath)
|
||||
);
|
||||
groupPageFiles[pageFileName] = compressedPages[page];
|
||||
}
|
||||
|
||||
const updatedManifestFiles: { [name: string]: FileBlob } = {};
|
||||
|
||||
if (isCorrectManifests) {
|
||||
// filter dynamic routes to only the included dynamic routes
|
||||
// in this specific serverless function so that we don't
|
||||
// accidentally match a dynamic route while resolving that
|
||||
// is not actually in this specific serverless function
|
||||
for (const manifest of [
|
||||
'routes-manifest.json',
|
||||
'server/pages-manifest.json',
|
||||
] as const) {
|
||||
const fsPath = path.join(entryPath, outputDirectory, manifest);
|
||||
|
||||
const relativePath = path.relative(baseDir, fsPath);
|
||||
delete group.pseudoLayer[relativePath];
|
||||
|
||||
const manifestData = await fs.readJSON(fsPath);
|
||||
const normalizedPages = new Set(
|
||||
group.pages.map(page => {
|
||||
page = `/${page.replace(/\.js$/, '')}`;
|
||||
if (page === '/index') page = '/';
|
||||
return page;
|
||||
})
|
||||
);
|
||||
|
||||
switch (manifest) {
|
||||
case 'routes-manifest.json': {
|
||||
const filterItem = (item: { page: string }) =>
|
||||
normalizedPages.has(item.page);
|
||||
|
||||
manifestData.dynamicRoutes =
|
||||
manifestData.dynamicRoutes?.filter(filterItem);
|
||||
manifestData.staticRoutes =
|
||||
manifestData.staticRoutes?.filter(filterItem);
|
||||
break;
|
||||
}
|
||||
case 'server/pages-manifest.json': {
|
||||
for (const key of Object.keys(manifestData)) {
|
||||
if (isDynamicRoute(key) && !normalizedPages.has(key)) {
|
||||
delete manifestData[key];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new NowBuildError({
|
||||
message: `Unexpected manifest value ${manifest}, please contact support if this continues`,
|
||||
code: 'NEXT_MANIFEST_INVARIANT',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
updatedManifestFiles[relativePath] = new FileBlob({
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(manifestData),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const lambda = await createLambdaFromPseudoLayers({
|
||||
files: launcherFiles,
|
||||
layers: [
|
||||
group.pseudoLayer,
|
||||
[...group.pages, ...internalPages].reduce((prev, page) => {
|
||||
const pageFileName = path.normalize(
|
||||
path.relative(baseDir, lambdaPages[page].fsPath)
|
||||
);
|
||||
prev[pageFileName] = compressedPages[page];
|
||||
return prev;
|
||||
}, {} as { [key: string]: PseudoFile }),
|
||||
],
|
||||
files: {
|
||||
...launcherFiles,
|
||||
...updatedManifestFiles,
|
||||
},
|
||||
layers: [group.pseudoLayer, groupPageFiles],
|
||||
handler: path.join(
|
||||
path.relative(
|
||||
baseDir,
|
||||
|
||||
8
packages/next/test/fixtures/00-mixed-dynamic-routes/index.test.js
vendored
Normal file
8
packages/next/test/fixtures/00-mixed-dynamic-routes/index.test.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
const path = require('path');
|
||||
const { deployAndTest } = require('../../utils');
|
||||
|
||||
describe(`${__dirname.split(path.sep).pop()}`, () => {
|
||||
it('should deploy and pass probe checks', async () => {
|
||||
await deployAndTest(__dirname);
|
||||
});
|
||||
});
|
||||
13
packages/next/test/fixtures/00-mixed-dynamic-routes/package.json
vendored
Normal file
13
packages/next/test/fixtures/00-mixed-dynamic-routes/package.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
}
|
||||
}
|
||||
17
packages/next/test/fixtures/00-mixed-dynamic-routes/pages/[...slug].js
vendored
Normal file
17
packages/next/test/fixtures/00-mixed-dynamic-routes/pages/[...slug].js
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
export default function Page(props) {
|
||||
return (
|
||||
<>
|
||||
<p>/[...slug] page</p>
|
||||
<p>{JSON.stringify(props)}</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps = async ({ params }) => {
|
||||
return {
|
||||
props: {
|
||||
params,
|
||||
page: '[...slug]',
|
||||
},
|
||||
};
|
||||
};
|
||||
29
packages/next/test/fixtures/00-mixed-dynamic-routes/pages/[slug].js
vendored
Normal file
29
packages/next/test/fixtures/00-mixed-dynamic-routes/pages/[slug].js
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
export default function Page(props) {
|
||||
return (
|
||||
<>
|
||||
<p>/[slug] page</p>
|
||||
<p>{JSON.stringify(props)}</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = async ({ params }) => {
|
||||
return {
|
||||
props: {
|
||||
params,
|
||||
page: '[slug]',
|
||||
now: Date.now(),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticPaths = async () => {
|
||||
return {
|
||||
paths: [
|
||||
{ params: { slug: 'static-1' } },
|
||||
{ params: { slug: 'static-2' } },
|
||||
{ params: { slug: 'static-3' } },
|
||||
],
|
||||
fallback: false,
|
||||
};
|
||||
};
|
||||
17
packages/next/test/fixtures/00-mixed-dynamic-routes/pages/index.js
vendored
Normal file
17
packages/next/test/fixtures/00-mixed-dynamic-routes/pages/index.js
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
export default function Page(props) {
|
||||
return (
|
||||
<>
|
||||
<p>index page</p>
|
||||
<p>{JSON.stringify(props)}</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const getStaticProps = async () => {
|
||||
return {
|
||||
props: {
|
||||
page: 'index',
|
||||
now: Date.now(),
|
||||
},
|
||||
};
|
||||
};
|
||||
36
packages/next/test/fixtures/00-mixed-dynamic-routes/vercel.json
vendored
Normal file
36
packages/next/test/fixtures/00-mixed-dynamic-routes/vercel.json
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [{ "src": "package.json", "use": "@vercel/next" }],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"mustContain": "index page"
|
||||
},
|
||||
{
|
||||
"path": "/static-1",
|
||||
"status": 200,
|
||||
"mustContain": "[slug] page"
|
||||
},
|
||||
{
|
||||
"path": "/static-2",
|
||||
"status": 200,
|
||||
"mustContain": "[slug] page"
|
||||
},
|
||||
{
|
||||
"path": "/dynamic-1",
|
||||
"status": 200,
|
||||
"mustContain": "[...slug] page"
|
||||
},
|
||||
{
|
||||
"path": "/dynamic-2",
|
||||
"status": 200,
|
||||
"mustContain": "[...slug] page"
|
||||
},
|
||||
{
|
||||
"path": "/long/dynamic",
|
||||
"status": 200,
|
||||
"mustContain": "[...slug] page"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/node",
|
||||
"version": "2.4.4",
|
||||
"version": "2.4.5",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
|
||||
@@ -31,13 +31,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"@vercel/build-utils": "5.0.3",
|
||||
"@vercel/build-utils": "5.0.4",
|
||||
"@vercel/node-bridge": "3.0.0",
|
||||
"@vercel/static-config": "2.0.1",
|
||||
"edge-runtime": "1.0.1",
|
||||
"esbuild": "0.14.47",
|
||||
"exit-hook": "2.2.1",
|
||||
"node-fetch": "2.6.1",
|
||||
"node-fetch": "2.6.7",
|
||||
"ts-node": "8.9.1",
|
||||
"typescript": "4.3.4"
|
||||
},
|
||||
|
||||
@@ -148,21 +148,26 @@ async function serializeRequest(message: IncomingMessage) {
|
||||
});
|
||||
}
|
||||
|
||||
async function compileUserCode(entrypoint: string) {
|
||||
async function compileUserCode(
|
||||
entrypointPath: string,
|
||||
entrypointLabel: string
|
||||
) {
|
||||
try {
|
||||
const result = await esbuild.build({
|
||||
platform: 'node',
|
||||
target: 'node14',
|
||||
sourcemap: 'inline',
|
||||
bundle: true,
|
||||
entryPoints: [entrypoint],
|
||||
entryPoints: [entrypointPath],
|
||||
write: false, // operate in memory
|
||||
format: 'cjs',
|
||||
});
|
||||
|
||||
const compiledFile = result.outputFiles?.[0];
|
||||
if (!compiledFile) {
|
||||
throw new Error(`Compilation of ${entrypoint} produced no output files.`);
|
||||
throw new Error(
|
||||
`Compilation of ${entrypointLabel} produced no output files.`
|
||||
);
|
||||
}
|
||||
|
||||
const userCode = new TextDecoder().decode(compiledFile.contents);
|
||||
@@ -198,6 +203,10 @@ async function compileUserCode(entrypoint: string) {
|
||||
|
||||
let response = await edgeHandler(event.request, event);
|
||||
|
||||
if (!response) {
|
||||
throw new Error('Edge Function "${entrypointLabel}" did not return a response.');
|
||||
}
|
||||
|
||||
return event.respondWith(response);
|
||||
} catch (error) {
|
||||
// we can't easily show a meaningful stack trace
|
||||
@@ -233,6 +242,9 @@ async function createEdgeRuntime(userCode: string | undefined) {
|
||||
module: {
|
||||
exports: {},
|
||||
},
|
||||
process: {
|
||||
env: process.env,
|
||||
},
|
||||
});
|
||||
return context;
|
||||
},
|
||||
@@ -252,9 +264,10 @@ async function createEdgeRuntime(userCode: string | undefined) {
|
||||
}
|
||||
|
||||
async function createEdgeEventHandler(
|
||||
entrypoint: string
|
||||
entrypointPath: string,
|
||||
entrypointLabel: string
|
||||
): Promise<(request: IncomingMessage) => Promise<VercelProxyResponse>> {
|
||||
const userCode = await compileUserCode(entrypoint);
|
||||
const userCode = await compileUserCode(entrypointPath, entrypointLabel);
|
||||
const server = await createEdgeRuntime(userCode);
|
||||
|
||||
return async function (request: IncomingMessage) {
|
||||
@@ -317,17 +330,17 @@ async function createEventHandler(
|
||||
config: Config,
|
||||
options: { shouldAddHelpers: boolean }
|
||||
): Promise<(request: IncomingMessage) => Promise<VercelProxyResponse>> {
|
||||
const entryPointPath = join(process.cwd(), entrypoint!);
|
||||
const runtime = parseRuntime(entrypoint, entryPointPath);
|
||||
const entrypointPath = join(process.cwd(), entrypoint!);
|
||||
const runtime = parseRuntime(entrypoint, entrypointPath);
|
||||
|
||||
// `middleware.js`/`middleware.ts` file is always run as
|
||||
// an Edge Function, otherwise needs to be opted-in via
|
||||
// `export const config = { runtime: 'experimental-edge' }`
|
||||
if (config.middleware === true || runtime === 'experimental-edge') {
|
||||
return createEdgeEventHandler(entryPointPath);
|
||||
return createEdgeEventHandler(entrypointPath, entrypoint);
|
||||
}
|
||||
|
||||
return createServerlessEventHandler(entryPointPath, options);
|
||||
return createServerlessEventHandler(entrypointPath, options);
|
||||
}
|
||||
|
||||
let handleEvent: (request: IncomingMessage) => Promise<VercelProxyResponse>;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/python",
|
||||
"version": "3.0.7",
|
||||
"version": "3.1.0",
|
||||
"main": "./dist/index.js",
|
||||
"license": "MIT",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
|
||||
@@ -23,7 +23,7 @@
|
||||
"devDependencies": {
|
||||
"@types/execa": "^0.9.0",
|
||||
"@types/jest": "27.4.1",
|
||||
"@vercel/build-utils": "5.0.3",
|
||||
"@vercel/build-utils": "5.0.4",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"execa": "^1.0.0",
|
||||
"typescript": "4.3.4"
|
||||
|
||||
@@ -9,4 +9,4 @@ verify_ssl = true
|
||||
flask = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.6"
|
||||
python_version = "3.9"
|
||||
|
||||
209
packages/python/test/fixtures/02-wsgi-pipenv/Pipfile.lock
generated
vendored
209
packages/python/test/fixtures/02-wsgi-pipenv/Pipfile.lock
generated
vendored
@@ -1,90 +1,123 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "8ec50e78e90ad609e540d41d1ed90f3fb880ffbdf6049b0a6b2f1a00158a3288"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.6"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
|
||||
"sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
|
||||
],
|
||||
"version": "==7.0"
|
||||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48",
|
||||
"sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.0.2"
|
||||
},
|
||||
"itsdangerous": {
|
||||
"hashes": [
|
||||
"sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
|
||||
"sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
|
||||
],
|
||||
"version": "==1.1.0"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
|
||||
"sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
|
||||
],
|
||||
"version": "==2.10.1"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
|
||||
"sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
|
||||
"sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
|
||||
"sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
|
||||
"sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
|
||||
"sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
|
||||
"sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
|
||||
"sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
|
||||
"sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
|
||||
"sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
|
||||
"sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
|
||||
"sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
|
||||
"sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
|
||||
"sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
|
||||
"sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
|
||||
"sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
|
||||
"sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
|
||||
"sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
|
||||
"sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
|
||||
"sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
|
||||
"sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
|
||||
"sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
|
||||
"sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
|
||||
"sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
|
||||
"sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
|
||||
"sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
|
||||
"sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
|
||||
"sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
|
||||
],
|
||||
"version": "==1.1.1"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:0a73e8bb2ff2feecfc5d56e6f458f5b99290ef34f565ffb2665801ff7de6af7a",
|
||||
"sha256:7fad9770a8778f9576693f0cc29c7dcc36964df916b83734f4431c0e612a7fbc"
|
||||
],
|
||||
"version": "==0.15.2"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "f7f1cea682a03d85328caf2f88382c4380283d3892a9ba31b374784fb29536c4"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.9"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
|
||||
"sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==8.1.3"
|
||||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:15972e5017df0575c3d6c090ba168b6db90259e620ac8d7ea813a396bad5b6cb",
|
||||
"sha256:9013281a7402ad527f8fd56375164f3aa021ecfaff89bfe3825346c24f87e04c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.1.3"
|
||||
},
|
||||
"importlib-metadata": {
|
||||
"hashes": [
|
||||
"sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670",
|
||||
"sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23"
|
||||
],
|
||||
"markers": "python_version < '3.10'",
|
||||
"version": "==4.12.0"
|
||||
},
|
||||
"itsdangerous": {
|
||||
"hashes": [
|
||||
"sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44",
|
||||
"sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.2"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852",
|
||||
"sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.1.2"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003",
|
||||
"sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88",
|
||||
"sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5",
|
||||
"sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7",
|
||||
"sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a",
|
||||
"sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603",
|
||||
"sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1",
|
||||
"sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135",
|
||||
"sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247",
|
||||
"sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6",
|
||||
"sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601",
|
||||
"sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77",
|
||||
"sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02",
|
||||
"sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e",
|
||||
"sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63",
|
||||
"sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f",
|
||||
"sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980",
|
||||
"sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b",
|
||||
"sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812",
|
||||
"sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff",
|
||||
"sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96",
|
||||
"sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1",
|
||||
"sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925",
|
||||
"sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a",
|
||||
"sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6",
|
||||
"sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e",
|
||||
"sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f",
|
||||
"sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4",
|
||||
"sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f",
|
||||
"sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3",
|
||||
"sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c",
|
||||
"sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a",
|
||||
"sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417",
|
||||
"sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a",
|
||||
"sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a",
|
||||
"sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37",
|
||||
"sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452",
|
||||
"sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933",
|
||||
"sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a",
|
||||
"sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.1"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6",
|
||||
"sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.2"
|
||||
},
|
||||
"zipp": {
|
||||
"hashes": [
|
||||
"sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2",
|
||||
"sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.8.1"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
"probes": [
|
||||
{
|
||||
"path": "/",
|
||||
"mustContain": "wsgi:RANDOMNESS_PLACEHOLDER",
|
||||
"logMustContain": "Python version \"3.6\" detected in Pipfile.lock has reached End-of-Life. Deployments created on or after 2022-07-18 will fail to build"
|
||||
"mustContain": "wsgi:RANDOMNESS_PLACEHOLDER"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -9,4 +9,4 @@ verify_ssl = true
|
||||
flask = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.6"
|
||||
python_version = "3.9"
|
||||
|
||||
209
packages/python/test/fixtures/03-env-vars/Pipfile.lock
generated
vendored
209
packages/python/test/fixtures/03-env-vars/Pipfile.lock
generated
vendored
@@ -1,90 +1,123 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "8ec50e78e90ad609e540d41d1ed90f3fb880ffbdf6049b0a6b2f1a00158a3288"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.6"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
|
||||
"sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
|
||||
],
|
||||
"version": "==7.0"
|
||||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48",
|
||||
"sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.0.2"
|
||||
},
|
||||
"itsdangerous": {
|
||||
"hashes": [
|
||||
"sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
|
||||
"sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
|
||||
],
|
||||
"version": "==1.1.0"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
|
||||
"sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
|
||||
],
|
||||
"version": "==2.10.1"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
|
||||
"sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
|
||||
"sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
|
||||
"sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
|
||||
"sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
|
||||
"sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
|
||||
"sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
|
||||
"sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
|
||||
"sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
|
||||
"sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
|
||||
"sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
|
||||
"sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
|
||||
"sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
|
||||
"sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
|
||||
"sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
|
||||
"sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
|
||||
"sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
|
||||
"sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
|
||||
"sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
|
||||
"sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
|
||||
"sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
|
||||
"sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
|
||||
"sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
|
||||
"sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
|
||||
"sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
|
||||
"sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
|
||||
"sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
|
||||
"sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
|
||||
],
|
||||
"version": "==1.1.1"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:0a73e8bb2ff2feecfc5d56e6f458f5b99290ef34f565ffb2665801ff7de6af7a",
|
||||
"sha256:7fad9770a8778f9576693f0cc29c7dcc36964df916b83734f4431c0e612a7fbc"
|
||||
],
|
||||
"version": "==0.15.2"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "f7f1cea682a03d85328caf2f88382c4380283d3892a9ba31b374784fb29536c4"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.9"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e",
|
||||
"sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==8.1.3"
|
||||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:15972e5017df0575c3d6c090ba168b6db90259e620ac8d7ea813a396bad5b6cb",
|
||||
"sha256:9013281a7402ad527f8fd56375164f3aa021ecfaff89bfe3825346c24f87e04c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.1.3"
|
||||
},
|
||||
"importlib-metadata": {
|
||||
"hashes": [
|
||||
"sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670",
|
||||
"sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23"
|
||||
],
|
||||
"markers": "python_version < '3.10'",
|
||||
"version": "==4.12.0"
|
||||
},
|
||||
"itsdangerous": {
|
||||
"hashes": [
|
||||
"sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44",
|
||||
"sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.2"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852",
|
||||
"sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.1.2"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003",
|
||||
"sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88",
|
||||
"sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5",
|
||||
"sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7",
|
||||
"sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a",
|
||||
"sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603",
|
||||
"sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1",
|
||||
"sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135",
|
||||
"sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247",
|
||||
"sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6",
|
||||
"sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601",
|
||||
"sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77",
|
||||
"sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02",
|
||||
"sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e",
|
||||
"sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63",
|
||||
"sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f",
|
||||
"sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980",
|
||||
"sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b",
|
||||
"sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812",
|
||||
"sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff",
|
||||
"sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96",
|
||||
"sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1",
|
||||
"sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925",
|
||||
"sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a",
|
||||
"sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6",
|
||||
"sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e",
|
||||
"sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f",
|
||||
"sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4",
|
||||
"sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f",
|
||||
"sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3",
|
||||
"sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c",
|
||||
"sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a",
|
||||
"sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417",
|
||||
"sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a",
|
||||
"sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a",
|
||||
"sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37",
|
||||
"sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452",
|
||||
"sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933",
|
||||
"sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a",
|
||||
"sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.1"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6",
|
||||
"sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==2.1.2"
|
||||
},
|
||||
"zipp": {
|
||||
"hashes": [
|
||||
"sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2",
|
||||
"sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.8.1"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
"probes": [
|
||||
{
|
||||
"path": "/",
|
||||
"mustContain": "RANDOMNESS_PLACEHOLDER:env",
|
||||
"logMustContain": "Python version \"3.6\" detected in Pipfile.lock has reached End-of-Life. Deployments created on or after 2022-07-18 will fail to build"
|
||||
"mustContain": "RANDOMNESS_PLACEHOLDER:env"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -9,4 +9,4 @@ verify_ssl = true
|
||||
django = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.6"
|
||||
python_version = "3.9"
|
||||
|
||||
84
packages/python/test/fixtures/08-django/Pipfile.lock
generated
vendored
84
packages/python/test/fixtures/08-django/Pipfile.lock
generated
vendored
@@ -1,43 +1,45 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "68309cd71a258c30a39567fce09a09ad5c4ff0bdc85b6fba22b47598c985c883"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.6"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"django": {
|
||||
"hashes": [
|
||||
"sha256:7c3543e4fb070d14e10926189a7fcf42ba919263b7473dceaefce34d54e8a119",
|
||||
"sha256:a2814bffd1f007805b19194eb0b9a331933b82bd5da1c3ba3d7b7ba16e06dc4b"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.2"
|
||||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9",
|
||||
"sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c"
|
||||
],
|
||||
"version": "==2018.9"
|
||||
},
|
||||
"sqlparse": {
|
||||
"hashes": [
|
||||
"sha256:40afe6b8d4b1117e7dff5504d7a8ce07d9a1b15aeeade8a2d10f130a834f8177",
|
||||
"sha256:7c3dca29c022744e95b547e867cee89f4fce4373f3549ccd8797d8eb52cdb873"
|
||||
],
|
||||
"version": "==0.3.0"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "c36ae28fea7b9a4cc02145632e2f41469af2e7b38b801903abb8333d3306f36b"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.9"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"asgiref": {
|
||||
"hashes": [
|
||||
"sha256:1d2880b792ae8757289136f1db2b7b99100ce959b2aa57fd69dab783d05afac4",
|
||||
"sha256:4a29362a6acebe09bf1d6640db38c1dc3d9217c68e6f9f6204d72667fc19a424"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==3.5.2"
|
||||
},
|
||||
"django": {
|
||||
"hashes": [
|
||||
"sha256:a67a793ff6827fd373555537dca0da293a63a316fe34cb7f367f898ccca3c3ae",
|
||||
"sha256:ca54ebedfcbc60d191391efbf02ba68fb52165b8bf6ccd6fe71f098cac1fe59e"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.0.6"
|
||||
},
|
||||
"sqlparse": {
|
||||
"hashes": [
|
||||
"sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae",
|
||||
"sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==0.4.2"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
||||
|
||||
207
packages/python/test/fixtures/11-asgi/Pipfile.lock
generated
vendored
207
packages/python/test/fixtures/11-asgi/Pipfile.lock
generated
vendored
@@ -1,207 +0,0 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "93dcd591e5690d3a71cb02979cbe317e83e3c03ec020867bf1554a480ef5cd8a"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.6"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"aiofiles": {
|
||||
"hashes": [
|
||||
"sha256:021ea0ba314a86027c166ecc4b4c07f2d40fc0f4b3a950d1868a0f2571c2bbee",
|
||||
"sha256:1e644c2573f953664368de28d2aa4c89dfd64550429d0c27c4680ccd3aa4985d"
|
||||
],
|
||||
"version": "==0.4.0"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939",
|
||||
"sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695"
|
||||
],
|
||||
"version": "==2019.6.16"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
||||
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
||||
],
|
||||
"version": "==3.0.4"
|
||||
},
|
||||
"h11": {
|
||||
"hashes": [
|
||||
"sha256:acca6a44cb52a32ab442b1779adf0875c443c689e9e028f8d831a3769f9c5208",
|
||||
"sha256:f2b1ca39bfed357d1f19ac732913d5f9faa54a5062eca7d2ec3a916cfb7ae4c7"
|
||||
],
|
||||
"version": "==0.8.1"
|
||||
},
|
||||
"h2": {
|
||||
"hashes": [
|
||||
"sha256:c8f387e0e4878904d4978cd688a3195f6b169d49b1ffa572a3d347d7adc5e09f",
|
||||
"sha256:fd07e865a3272ac6ef195d8904de92dc7b38dc28297ec39cfa22716b6d62e6eb"
|
||||
],
|
||||
"version": "==3.1.0"
|
||||
},
|
||||
"hpack": {
|
||||
"hashes": [
|
||||
"sha256:0edd79eda27a53ba5be2dfabf3b15780928a0dff6eb0c60a3d6767720e970c89",
|
||||
"sha256:8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2"
|
||||
],
|
||||
"version": "==3.0.0"
|
||||
},
|
||||
"httpcore": {
|
||||
"hashes": [
|
||||
"sha256:96f910b528d47b683242ec207050c7bbaa99cd1b9a07f78ea80cf61e55556b58"
|
||||
],
|
||||
"version": "==0.3.0"
|
||||
},
|
||||
"httptools": {
|
||||
"hashes": [
|
||||
"sha256:e00cbd7ba01ff748e494248183abc6e153f49181169d8a3d41bb49132ca01dfc"
|
||||
],
|
||||
"version": "==0.0.13"
|
||||
},
|
||||
"hyperframe": {
|
||||
"hashes": [
|
||||
"sha256:5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40",
|
||||
"sha256:a9f5c17f2cc3c719b917c4f33ed1c61bd1f8dfac4b1bd23b7c80b3400971b41f"
|
||||
],
|
||||
"version": "==5.2.0"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
|
||||
"sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
|
||||
],
|
||||
"version": "==2.8"
|
||||
},
|
||||
"multidict": {
|
||||
"hashes": [
|
||||
"sha256:024b8129695a952ebd93373e45b5d341dbb87c17ce49637b34000093f243dd4f",
|
||||
"sha256:041e9442b11409be5e4fc8b6a97e4bcead758ab1e11768d1e69160bdde18acc3",
|
||||
"sha256:045b4dd0e5f6121e6f314d81759abd2c257db4634260abcfe0d3f7083c4908ef",
|
||||
"sha256:047c0a04e382ef8bd74b0de01407e8d8632d7d1b4db6f2561106af812a68741b",
|
||||
"sha256:068167c2d7bbeebd359665ac4fff756be5ffac9cda02375b5c5a7c4777038e73",
|
||||
"sha256:148ff60e0fffa2f5fad2eb25aae7bef23d8f3b8bdaf947a65cdbe84a978092bc",
|
||||
"sha256:1d1c77013a259971a72ddaa83b9f42c80a93ff12df6a4723be99d858fa30bee3",
|
||||
"sha256:1d48bc124a6b7a55006d97917f695effa9725d05abe8ee78fd60d6588b8344cd",
|
||||
"sha256:31dfa2fc323097f8ad7acd41aa38d7c614dd1960ac6681745b6da124093dc351",
|
||||
"sha256:34f82db7f80c49f38b032c5abb605c458bac997a6c3142e0d6c130be6fb2b941",
|
||||
"sha256:3d5dd8e5998fb4ace04789d1d008e2bb532de501218519d70bb672c4c5a2fc5d",
|
||||
"sha256:4a6ae52bd3ee41ee0f3acf4c60ceb3f44e0e3bc52ab7da1c2b2aa6703363a3d1",
|
||||
"sha256:4b02a3b2a2f01d0490dd39321c74273fed0568568ea0e7ea23e02bd1fb10a10b",
|
||||
"sha256:4b843f8e1dd6a3195679d9838eb4670222e8b8d01bc36c9894d6c3538316fa0a",
|
||||
"sha256:5de53a28f40ef3c4fd57aeab6b590c2c663de87a5af76136ced519923d3efbb3",
|
||||
"sha256:61b2b33ede821b94fa99ce0b09c9ece049c7067a33b279f343adfe35108a4ea7",
|
||||
"sha256:6a3a9b0f45fd75dc05d8e93dc21b18fc1670135ec9544d1ad4acbcf6b86781d0",
|
||||
"sha256:76ad8e4c69dadbb31bad17c16baee61c0d1a4a73bed2590b741b2e1a46d3edd0",
|
||||
"sha256:7ba19b777dc00194d1b473180d4ca89a054dd18de27d0ee2e42a103ec9b7d014",
|
||||
"sha256:7c1b7eab7a49aa96f3db1f716f0113a8a2e93c7375dd3d5d21c4941f1405c9c5",
|
||||
"sha256:7fc0eee3046041387cbace9314926aa48b681202f8897f8bff3809967a049036",
|
||||
"sha256:8ccd1c5fff1aa1427100ce188557fc31f1e0a383ad8ec42c559aabd4ff08802d",
|
||||
"sha256:8e08dd76de80539d613654915a2f5196dbccc67448df291e69a88712ea21e24a",
|
||||
"sha256:c18498c50c59263841862ea0501da9f2b3659c00db54abfbf823a80787fde8ce",
|
||||
"sha256:c49db89d602c24928e68c0d510f4fcf8989d77defd01c973d6cbe27e684833b1",
|
||||
"sha256:ce20044d0317649ddbb4e54dab3c1bcc7483c78c27d3f58ab3d0c7e6bc60d26a",
|
||||
"sha256:d1071414dd06ca2eafa90c85a079169bfeb0e5f57fd0b45d44c092546fcd6fd9",
|
||||
"sha256:d3be11ac43ab1a3e979dac80843b42226d5d3cccd3986f2e03152720a4297cd7",
|
||||
"sha256:db603a1c235d110c860d5f39988ebc8218ee028f07a7cbc056ba6424372ca31b"
|
||||
],
|
||||
"version": "==4.5.2"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
"sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
|
||||
"sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
|
||||
],
|
||||
"version": "==2.22.0"
|
||||
},
|
||||
"requests-async": {
|
||||
"hashes": [
|
||||
"sha256:8731420451383196ecf2fd96082bfc8ae5103ada90aba185888499d7784dde6f"
|
||||
],
|
||||
"version": "==0.5.0"
|
||||
},
|
||||
"rfc3986": {
|
||||
"hashes": [
|
||||
"sha256:0344d0bd428126ce554e7ca2b61787b6a28d2bbd19fc70ed2dd85efe31176405",
|
||||
"sha256:df4eba676077cefb86450c8f60121b9ae04b94f65f85b69f3f731af0516b7b18"
|
||||
],
|
||||
"version": "==1.3.2"
|
||||
},
|
||||
"sanic": {
|
||||
"hashes": [
|
||||
"sha256:cc64978266025afb0e7c0f8be928e2b81670c5d58ddac290d04c9d0da6ec2112",
|
||||
"sha256:ebd806298782400db811ea9d63e8096e835e67f0b5dc5e66e507532984a82bb3"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==19.6.0"
|
||||
},
|
||||
"ujson": {
|
||||
"hashes": [
|
||||
"sha256:f66073e5506e91d204ab0c614a148d5aa938bdbf104751be66f8ad7a222f5f86"
|
||||
],
|
||||
"markers": "sys_platform != 'win32' and implementation_name == 'cpython'",
|
||||
"version": "==1.35"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1",
|
||||
"sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"
|
||||
],
|
||||
"version": "==1.25.3"
|
||||
},
|
||||
"uvloop": {
|
||||
"hashes": [
|
||||
"sha256:0fcd894f6fc3226a962ee7ad895c4f52e3f5c3c55098e21efb17c071849a0573",
|
||||
"sha256:2f31de1742c059c96cb76b91c5275b22b22b965c886ee1fced093fa27dde9e64",
|
||||
"sha256:459e4649fcd5ff719523de33964aa284898e55df62761e7773d088823ccbd3e0",
|
||||
"sha256:67867aafd6e0bc2c30a079603a85d83b94f23c5593b3cc08ec7e58ac18bf48e5",
|
||||
"sha256:8c200457e6847f28d8bb91c5e5039d301716f5f2fce25646f5fb3fd65eda4a26",
|
||||
"sha256:958906b9ca39eb158414fbb7d6b8ef1b7aee4db5c8e8e5d00fcbb69a1ce9dca7",
|
||||
"sha256:ac1dca3d8f3ef52806059e81042ee397ac939e5a86c8a3cea55d6b087db66115",
|
||||
"sha256:b284c22d8938866318e3b9d178142b8be316c52d16fcfe1560685a686718a021",
|
||||
"sha256:c48692bf4587ce281d641087658eca275a5ad3b63c78297bbded96570ae9ce8f",
|
||||
"sha256:fefc3b2b947c99737c348887db2c32e539160dcbeb7af9aa6b53db7a283538fe"
|
||||
],
|
||||
"markers": "sys_platform != 'win32' and implementation_name == 'cpython'",
|
||||
"version": "==0.12.2"
|
||||
},
|
||||
"websockets": {
|
||||
"hashes": [
|
||||
"sha256:0e2f7d6567838369af074f0ef4d0b802d19fa1fee135d864acc656ceefa33136",
|
||||
"sha256:2a16dac282b2fdae75178d0ed3d5b9bc3258dabfae50196cbb30578d84b6f6a6",
|
||||
"sha256:5a1fa6072405648cb5b3688e9ed3b94be683ce4a4e5723e6f5d34859dee495c1",
|
||||
"sha256:5c1f55a1274df9d6a37553fef8cff2958515438c58920897675c9bc70f5a0538",
|
||||
"sha256:669d1e46f165e0ad152ed8197f7edead22854a6c90419f544e0f234cc9dac6c4",
|
||||
"sha256:695e34c4dbea18d09ab2c258994a8bf6a09564e762655408241f6a14592d2908",
|
||||
"sha256:6b2e03d69afa8d20253455e67b64de1a82ff8612db105113cccec35d3f8429f0",
|
||||
"sha256:79ca7cdda7ad4e3663ea3c43bfa8637fc5d5604c7737f19a8964781abbd1148d",
|
||||
"sha256:7fd2dd9a856f72e6ed06f82facfce01d119b88457cd4b47b7ae501e8e11eba9c",
|
||||
"sha256:82c0354ac39379d836719a77ee360ef865377aa6fdead87909d50248d0f05f4d",
|
||||
"sha256:8f3b956d11c5b301206382726210dc1d3bee1a9ccf7aadf895aaf31f71c3716c",
|
||||
"sha256:91ec98640220ae05b34b79ee88abf27f97ef7c61cf525eec57ea8fcea9f7dddb",
|
||||
"sha256:952be9540d83dba815569d5cb5f31708801e0bbfc3a8c5aef1890b57ed7e58bf",
|
||||
"sha256:99ac266af38ba1b1fe13975aea01ac0e14bb5f3a3200d2c69f05385768b8568e",
|
||||
"sha256:9fa122e7adb24232247f8a89f2d9070bf64b7869daf93ac5e19546b409e47e96",
|
||||
"sha256:a0873eadc4b8ca93e2e848d490809e0123eea154aa44ecd0109c4d0171869584",
|
||||
"sha256:cb998bd4d93af46b8b49ecf5a72c0a98e5cc6d57fdca6527ba78ad89d6606484",
|
||||
"sha256:e02e57346f6a68523e3c43bbdf35dde5c440318d1f827208ae455f6a2ace446d",
|
||||
"sha256:e79a5a896bcee7fff24a788d72e5c69f13e61369d055f28113e71945a7eb1559",
|
||||
"sha256:ee55eb6bcf23ecc975e6b47c127c201b913598f38b6a300075f84eeef2d3baff",
|
||||
"sha256:f1414e6cbcea8d22843e7eafdfdfae3dd1aba41d1945f6ca66e4806c07c4f454"
|
||||
],
|
||||
"version": "==6.0"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
from sanic import Sanic
|
||||
from sanic import response
|
||||
app = Sanic()
|
||||
app = Sanic(name='test')
|
||||
|
||||
|
||||
@app.route("/")
|
||||
|
||||
22
packages/python/test/fixtures/11-asgi/requirements.txt
vendored
Normal file
22
packages/python/test/fixtures/11-asgi/requirements.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
sanic==20.12.6
|
||||
# below is meant to lock the version of transitive deps
|
||||
aiofiles==0.8.0; python_version >= "3.6" and python_version < "4.0"
|
||||
certifi==2021.10.8
|
||||
click==8.1.2; python_version >= "3.7"
|
||||
h11==0.9.0
|
||||
httpcore==0.11.1; python_version >= "3.6"
|
||||
httptools==0.4.0; python_version >= "3.5"
|
||||
httpx==0.15.4; python_version >= "3.6"
|
||||
idna==3.3
|
||||
importlib-metadata==4.11.3; python_version < "3.10"
|
||||
itsdangerous==2.1.2; python_version >= "3.7"
|
||||
jinja2==3.1.1; python_version >= "3.7"
|
||||
markupsafe==2.1.1; python_version >= "3.7"
|
||||
multidict==5.2.0; python_version >= "3.6"
|
||||
rfc3986[idna2008]==1.5.0
|
||||
sniffio==1.2.0; python_version >= "3.5"
|
||||
ujson==5.2.0; sys_platform != "win32" and implementation_name == "cpython"
|
||||
uvloop==0.16.0; sys_platform != "win32" and implementation_name == "cpython"
|
||||
websockets==9.1; python_full_version >= "3.6.1"
|
||||
werkzeug==2.1.1; python_version >= "3.7"
|
||||
zipp==3.8.0; python_version >= "3.7"
|
||||
@@ -6,6 +6,6 @@ class handler(BaseHTTPRequestHandler):
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "image/png")
|
||||
self.end_headers()
|
||||
with open("zeit-white-triangle.png", "rb") as image:
|
||||
with open("triangle.png", "rb") as image:
|
||||
self.wfile.write(image.read())
|
||||
return
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { readFile } = require('fs/promises');
|
||||
const { join } = require('path');
|
||||
|
||||
module.exports = async function({ deploymentUrl, fetch }) {
|
||||
const nowjson = require('./now.json');
|
||||
const probe = nowjson.probes[0];
|
||||
const probeUrl = `https://${deploymentUrl}${probe.path}`;
|
||||
const resp = await fetch(probeUrl);
|
||||
module.exports = async function ({ deploymentUrl, fetch }) {
|
||||
const resp = await fetch(`https://${deploymentUrl}`);
|
||||
|
||||
const bytes = await resp.arrayBuffer();
|
||||
|
||||
const image = fs.readFileSync(
|
||||
path.join(__dirname, 'zeit-white-triangle.png')
|
||||
);
|
||||
const image = await readFile(join(__dirname, 'triangle.png'));
|
||||
|
||||
if (!image.equals(new Uint8Array(bytes))) {
|
||||
throw new Error(`unexpected response: ${bytes}`);
|
||||
|
||||
|
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 383 B |
@@ -5,12 +5,5 @@
|
||||
"src": "*.py",
|
||||
"use": "@vercel/python"
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/",
|
||||
"method": "GET",
|
||||
"status": 200
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -6,7 +6,7 @@ verify_ssl = true
|
||||
[dev-packages]
|
||||
|
||||
[packages]
|
||||
sanic = "*"
|
||||
sanic = "22.3.2"
|
||||
|
||||
[requires]
|
||||
python_version = "3.6"
|
||||
python_version = "3.10"
|
||||
203
packages/python/test/fixtures/30-asgi-lifespan/Pipfile.lock
generated
vendored
Normal file
203
packages/python/test/fixtures/30-asgi-lifespan/Pipfile.lock
generated
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "390914ba991c8a230704140fc6be20ca33aa3b6d6359ca151be04d07c9bc6536"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.10"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"aiofiles": {
|
||||
"hashes": [
|
||||
"sha256:7a973fc22b29e9962d0897805ace5856e6a566ab1f0c8e5c91ff6c866519c937",
|
||||
"sha256:8334f23235248a3b2e83b2c3a78a22674f39969b96397126cc93664d9a901e59"
|
||||
],
|
||||
"markers": "python_version >= '3.6' and python_version < '4.0'",
|
||||
"version": "==0.8.0"
|
||||
},
|
||||
"httptools": {
|
||||
"hashes": [
|
||||
"sha256:1a99346ebcb801b213c591540837340bdf6fd060a8687518d01c607d338b7424",
|
||||
"sha256:1ee0b459257e222b878a6c09ccf233957d3a4dcb883b0847640af98d2d9aac23",
|
||||
"sha256:20a45bcf22452a10fa8d58b7dbdb474381f6946bf5b8933e3662d572bc61bae4",
|
||||
"sha256:29bf97a5c532da9c7a04de2c7a9c31d1d54f3abd65a464119b680206bbbb1055",
|
||||
"sha256:2c9a930c378b3d15d6b695fb95ebcff81a7395b4f9775c4f10a076beb0b2c1ff",
|
||||
"sha256:2db44a0b294d317199e9f80123e72c6b005c55b625b57fae36de68670090fa48",
|
||||
"sha256:3194f6d6443befa8d4db16c1946b2fc428a3ceb8ab32eb6f09a59f86104dc1a0",
|
||||
"sha256:34d2903dd2a3dd85d33705b6fde40bf91fc44411661283763fd0746723963c83",
|
||||
"sha256:48e48530d9b995a84d1d89ae6b3ec4e59ea7d494b150ac3bbc5e2ac4acce92cd",
|
||||
"sha256:54bbd295f031b866b9799dd39cb45deee81aca036c9bff9f58ca06726f6494f1",
|
||||
"sha256:5d1fe6b6661022fd6cac541f54a4237496b246e6f1c0a6b41998ee08a1135afe",
|
||||
"sha256:645373c070080e632480a3d251d892cb795be3d3a15f86975d0f1aca56fd230d",
|
||||
"sha256:6a1a7dfc1f9c78a833e2c4904757a0f47ce25d08634dd2a52af394eefe5f9777",
|
||||
"sha256:701e66b59dd21a32a274771238025d58db7e2b6ecebbab64ceff51b8e31527ae",
|
||||
"sha256:72aa3fbe636b16d22e04b5a9d24711b043495e0ecfe58080addf23a1a37f3409",
|
||||
"sha256:7af6bdbd21a2a25d6784f6d67f44f5df33ef39b6159543b9f9064d365c01f919",
|
||||
"sha256:7ee9f226acab9085037582c059d66769862706e8e8cd2340470ceb8b3850873d",
|
||||
"sha256:7f7bfb74718f52d5ed47d608d507bf66d3bc01d4a8b3e6dd7134daaae129357b",
|
||||
"sha256:8e2eb957787cbb614a0f006bfc5798ff1d90ac7c4dd24854c84edbdc8c02369e",
|
||||
"sha256:903f739c9fb78dab8970b0f3ea51f21955b24b45afa77b22ff0e172fc11ef111",
|
||||
"sha256:98993805f1e3cdb53de4eed02b55dcc953cdf017ba7bbb2fd89226c086a6d855",
|
||||
"sha256:9967d9758df505975913304c434cb9ab21e2c609ad859eb921f2f615a038c8de",
|
||||
"sha256:a113789e53ac1fa26edf99856a61e4c493868e125ae0dd6354cf518948fbbd5c",
|
||||
"sha256:a522d12e2ddbc2e91842ffb454a1aeb0d47607972c7d8fc88bd0838d97fb8a2a",
|
||||
"sha256:abe829275cdd4174b4c4e65ad718715d449e308d59793bf3a931ee1bf7e7b86c",
|
||||
"sha256:c286985b5e194ca0ebb2908d71464b9be8f17cc66d6d3e330e8d5407248f56ad",
|
||||
"sha256:cd1295f52971097f757edfbfce827b6dbbfb0f7a74901ee7d4933dff5ad4c9af",
|
||||
"sha256:ceafd5e960b39c7e0d160a1936b68eb87c5e79b3979d66e774f0c77d4d8faaed",
|
||||
"sha256:d1f27bb0f75bef722d6e22dc609612bfa2f994541621cd2163f8c943b6463dfe",
|
||||
"sha256:d3a4e165ca6204f34856b765d515d558dc84f1352033b8721e8d06c3e44930c3",
|
||||
"sha256:d9b90bf58f3ba04e60321a23a8723a1ff2a9377502535e70495e5ada8e6e6722",
|
||||
"sha256:f72b5d24d6730035128b238decdc4c0f2104b7056a7ca55cf047c106842ec890",
|
||||
"sha256:fcddfe70553be717d9745990dfdb194e22ee0f60eb8f48c0794e7bfeda30d2d5",
|
||||
"sha256:fdb9f9ed79bc6f46b021b3319184699ba1a22410a82204e6e89c774530069683"
|
||||
],
|
||||
"markers": "python_full_version >= '3.5.0'",
|
||||
"version": "==0.4.0"
|
||||
},
|
||||
"multidict": {
|
||||
"hashes": [
|
||||
"sha256:0327292e745a880459ef71be14e709aaea2f783f3537588fb4ed09b6c01bca60",
|
||||
"sha256:041b81a5f6b38244b34dc18c7b6aba91f9cdaf854d9a39e5ff0b58e2b5773b9c",
|
||||
"sha256:0556a1d4ea2d949efe5fd76a09b4a82e3a4a30700553a6725535098d8d9fb672",
|
||||
"sha256:05f6949d6169878a03e607a21e3b862eaf8e356590e8bdae4227eedadacf6e51",
|
||||
"sha256:07a017cfa00c9890011628eab2503bee5872f27144936a52eaab449be5eaf032",
|
||||
"sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2",
|
||||
"sha256:19adcfc2a7197cdc3987044e3f415168fc5dc1f720c932eb1ef4f71a2067e08b",
|
||||
"sha256:19d9bad105dfb34eb539c97b132057a4e709919ec4dd883ece5838bcbf262b80",
|
||||
"sha256:225383a6603c086e6cef0f2f05564acb4f4d5f019a4e3e983f572b8530f70c88",
|
||||
"sha256:23b616fdc3c74c9fe01d76ce0d1ce872d2d396d8fa8e4899398ad64fb5aa214a",
|
||||
"sha256:2957489cba47c2539a8eb7ab32ff49101439ccf78eab724c828c1a54ff3ff98d",
|
||||
"sha256:2d36e929d7f6a16d4eb11b250719c39560dd70545356365b494249e2186bc389",
|
||||
"sha256:2e4a0785b84fb59e43c18a015ffc575ba93f7d1dbd272b4cdad9f5134b8a006c",
|
||||
"sha256:3368bf2398b0e0fcbf46d85795adc4c259299fec50c1416d0f77c0a843a3eed9",
|
||||
"sha256:373ba9d1d061c76462d74e7de1c0c8e267e9791ee8cfefcf6b0b2495762c370c",
|
||||
"sha256:4070613ea2227da2bfb2c35a6041e4371b0af6b0be57f424fe2318b42a748516",
|
||||
"sha256:45183c96ddf61bf96d2684d9fbaf6f3564d86b34cb125761f9a0ef9e36c1d55b",
|
||||
"sha256:4571f1beddff25f3e925eea34268422622963cd8dc395bb8778eb28418248e43",
|
||||
"sha256:47e6a7e923e9cada7c139531feac59448f1f47727a79076c0b1ee80274cd8eee",
|
||||
"sha256:47fbeedbf94bed6547d3aa632075d804867a352d86688c04e606971595460227",
|
||||
"sha256:497988d6b6ec6ed6f87030ec03280b696ca47dbf0648045e4e1d28b80346560d",
|
||||
"sha256:4bae31803d708f6f15fd98be6a6ac0b6958fcf68fda3c77a048a4f9073704aae",
|
||||
"sha256:50bd442726e288e884f7be9071016c15a8742eb689a593a0cac49ea093eef0a7",
|
||||
"sha256:514fe2b8d750d6cdb4712346a2c5084a80220821a3e91f3f71eec11cf8d28fd4",
|
||||
"sha256:5774d9218d77befa7b70d836004a768fb9aa4fdb53c97498f4d8d3f67bb9cfa9",
|
||||
"sha256:5fdda29a3c7e76a064f2477c9aab1ba96fd94e02e386f1e665bca1807fc5386f",
|
||||
"sha256:5ff3bd75f38e4c43f1f470f2df7a4d430b821c4ce22be384e1459cb57d6bb013",
|
||||
"sha256:626fe10ac87851f4cffecee161fc6f8f9853f0f6f1035b59337a51d29ff3b4f9",
|
||||
"sha256:6701bf8a5d03a43375909ac91b6980aea74b0f5402fbe9428fc3f6edf5d9677e",
|
||||
"sha256:684133b1e1fe91eda8fa7447f137c9490a064c6b7f392aa857bba83a28cfb693",
|
||||
"sha256:6f3cdef8a247d1eafa649085812f8a310e728bdf3900ff6c434eafb2d443b23a",
|
||||
"sha256:75bdf08716edde767b09e76829db8c1e5ca9d8bb0a8d4bd94ae1eafe3dac5e15",
|
||||
"sha256:7c40b7bbece294ae3a87c1bc2abff0ff9beef41d14188cda94ada7bcea99b0fb",
|
||||
"sha256:8004dca28e15b86d1b1372515f32eb6f814bdf6f00952699bdeb541691091f96",
|
||||
"sha256:8064b7c6f0af936a741ea1efd18690bacfbae4078c0c385d7c3f611d11f0cf87",
|
||||
"sha256:89171b2c769e03a953d5969b2f272efa931426355b6c0cb508022976a17fd376",
|
||||
"sha256:8cbf0132f3de7cc6c6ce00147cc78e6439ea736cee6bca4f068bcf892b0fd658",
|
||||
"sha256:9cc57c68cb9139c7cd6fc39f211b02198e69fb90ce4bc4a094cf5fe0d20fd8b0",
|
||||
"sha256:a007b1638e148c3cfb6bf0bdc4f82776cef0ac487191d093cdc316905e504071",
|
||||
"sha256:a2c34a93e1d2aa35fbf1485e5010337c72c6791407d03aa5f4eed920343dd360",
|
||||
"sha256:a45e1135cb07086833ce969555df39149680e5471c04dfd6a915abd2fc3f6dbc",
|
||||
"sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3",
|
||||
"sha256:aef9cc3d9c7d63d924adac329c33835e0243b5052a6dfcbf7732a921c6e918ba",
|
||||
"sha256:b9d153e7f1f9ba0b23ad1568b3b9e17301e23b042c23870f9ee0522dc5cc79e8",
|
||||
"sha256:bfba7c6d5d7c9099ba21f84662b037a0ffd4a5e6b26ac07d19e423e6fdf965a9",
|
||||
"sha256:c207fff63adcdf5a485969131dc70e4b194327666b7e8a87a97fbc4fd80a53b2",
|
||||
"sha256:d0509e469d48940147e1235d994cd849a8f8195e0bca65f8f5439c56e17872a3",
|
||||
"sha256:d16cce709ebfadc91278a1c005e3c17dd5f71f5098bfae1035149785ea6e9c68",
|
||||
"sha256:d48b8ee1d4068561ce8033d2c344cf5232cb29ee1a0206a7b828c79cbc5982b8",
|
||||
"sha256:de989b195c3d636ba000ee4281cd03bb1234635b124bf4cd89eeee9ca8fcb09d",
|
||||
"sha256:e07c8e79d6e6fd37b42f3250dba122053fddb319e84b55dd3a8d6446e1a7ee49",
|
||||
"sha256:e2c2e459f7050aeb7c1b1276763364884595d47000c1cddb51764c0d8976e608",
|
||||
"sha256:e5b20e9599ba74391ca0cfbd7b328fcc20976823ba19bc573983a25b32e92b57",
|
||||
"sha256:e875b6086e325bab7e680e4316d667fc0e5e174bb5611eb16b3ea121c8951b86",
|
||||
"sha256:f4f052ee022928d34fe1f4d2bc743f32609fb79ed9c49a1710a5ad6b2198db20",
|
||||
"sha256:fcb91630817aa8b9bc4a74023e4198480587269c272c58b3279875ed7235c293",
|
||||
"sha256:fd9fc9c4849a07f3635ccffa895d57abce554b467d611a5009ba4f39b78a8849",
|
||||
"sha256:feba80698173761cddd814fa22e88b0661e98cb810f9f986c54aa34d281e4937",
|
||||
"sha256:feea820722e69451743a3d56ad74948b68bf456984d63c1a92e8347b7b88452d"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==6.0.2"
|
||||
},
|
||||
"sanic": {
|
||||
"hashes": [
|
||||
"sha256:d0653de59cf3073d8ca047253db72c868510d45d753c13b6316aede769fb66fb",
|
||||
"sha256:f6eb181e7a1b9a77a3b916de0f1413eddbe384c59487c2a4bff0c7a41e66e080"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==22.6.0"
|
||||
},
|
||||
"sanic-routing": {
|
||||
"hashes": [
|
||||
"sha256:8282fc05659ff2cebbffa4fb69697601fc9d653c34e0b5bdeed04a832e793fb9",
|
||||
"sha256:fde5a7d4079794b585b9a2904accd0de5a70abf27c82d2658b40c551ef44f703"
|
||||
],
|
||||
"version": "==22.3.0"
|
||||
},
|
||||
"websockets": {
|
||||
"hashes": [
|
||||
"sha256:07cdc0a5b2549bcfbadb585ad8471ebdc7bdf91e32e34ae3889001c1c106a6af",
|
||||
"sha256:210aad7fdd381c52e58777560860c7e6110b6174488ef1d4b681c08b68bf7f8c",
|
||||
"sha256:28dd20b938a57c3124028680dc1600c197294da5db4292c76a0b48efb3ed7f76",
|
||||
"sha256:2f94fa3ae454a63ea3a19f73b95deeebc9f02ba2d5617ca16f0bbdae375cda47",
|
||||
"sha256:31564a67c3e4005f27815634343df688b25705cccb22bc1db621c781ddc64c69",
|
||||
"sha256:347974105bbd4ea068106ec65e8e8ebd86f28c19e529d115d89bd8cc5cda3079",
|
||||
"sha256:379e03422178436af4f3abe0aa8f401aa77ae2487843738542a75faf44a31f0c",
|
||||
"sha256:3eda1cb7e9da1b22588cefff09f0951771d6ee9fa8dbe66f5ae04cc5f26b2b55",
|
||||
"sha256:51695d3b199cd03098ae5b42833006a0f43dc5418d3102972addc593a783bc02",
|
||||
"sha256:54c000abeaff6d8771a4e2cef40900919908ea7b6b6a30eae72752607c6db559",
|
||||
"sha256:5b936bf552e4f6357f5727579072ff1e1324717902127ffe60c92d29b67b7be3",
|
||||
"sha256:6075fd24df23133c1b078e08a9b04a3bc40b31a8def4ee0b9f2c8865acce913e",
|
||||
"sha256:661f641b44ed315556a2fa630239adfd77bd1b11cb0b9d96ed8ad90b0b1e4978",
|
||||
"sha256:6ea6b300a6bdd782e49922d690e11c3669828fe36fc2471408c58b93b5535a98",
|
||||
"sha256:6ed1d6f791eabfd9808afea1e068f5e59418e55721db8b7f3bfc39dc831c42ae",
|
||||
"sha256:7934e055fd5cd9dee60f11d16c8d79c4567315824bacb1246d0208a47eca9755",
|
||||
"sha256:7ab36e17af592eec5747c68ef2722a74c1a4a70f3772bc661079baf4ae30e40d",
|
||||
"sha256:7f6d96fdb0975044fdd7953b35d003b03f9e2bcf85f2d2cf86285ece53e9f991",
|
||||
"sha256:83e5ca0d5b743cde3d29fda74ccab37bdd0911f25bd4cdf09ff8b51b7b4f2fa1",
|
||||
"sha256:85506b3328a9e083cc0a0fb3ba27e33c8db78341b3eb12eb72e8afd166c36680",
|
||||
"sha256:8af75085b4bc0b5c40c4a3c0e113fa95e84c60f4ed6786cbb675aeb1ee128247",
|
||||
"sha256:8b1359aba0ff810d5830d5ab8e2c4a02bebf98a60aa0124fb29aa78cfdb8031f",
|
||||
"sha256:8fbd7d77f8aba46d43245e86dd91a8970eac4fb74c473f8e30e9c07581f852b2",
|
||||
"sha256:907e8247480f287aa9bbc9391bd6de23c906d48af54c8c421df84655eef66af7",
|
||||
"sha256:93d5ea0b5da8d66d868b32c614d2b52d14304444e39e13a59566d4acb8d6e2e4",
|
||||
"sha256:97bc9d41e69a7521a358f9b8e44871f6cdeb42af31815c17aed36372d4eec667",
|
||||
"sha256:994cdb1942a7a4c2e10098d9162948c9e7b235df755de91ca33f6e0481366fdb",
|
||||
"sha256:a141de3d5a92188234afa61653ed0bbd2dde46ad47b15c3042ffb89548e77094",
|
||||
"sha256:a1e15b230c3613e8ea82c9fc6941b2093e8eb939dd794c02754d33980ba81e36",
|
||||
"sha256:aad5e300ab32036eb3fdc350ad30877210e2f51bceaca83fb7fef4d2b6c72b79",
|
||||
"sha256:b529fdfa881b69fe563dbd98acce84f3e5a67df13de415e143ef053ff006d500",
|
||||
"sha256:b9c77f0d1436ea4b4dc089ed8335fa141e6a251a92f75f675056dac4ab47a71e",
|
||||
"sha256:bb621ec2dbbbe8df78a27dbd9dd7919f9b7d32a73fafcb4d9252fc4637343582",
|
||||
"sha256:c7250848ce69559756ad0086a37b82c986cd33c2d344ab87fea596c5ac6d9442",
|
||||
"sha256:c8d1d14aa0f600b5be363077b621b1b4d1eb3fbf90af83f9281cda668e6ff7fd",
|
||||
"sha256:d1655a6fc7aecd333b079d00fb3c8132d18988e47f19740c69303bf02e9883c6",
|
||||
"sha256:d6353ba89cfc657a3f5beabb3b69be226adbb5c6c7a66398e17809b0ce3c4731",
|
||||
"sha256:da4377904a3379f0c1b75a965fff23b28315bcd516d27f99a803720dfebd94d4",
|
||||
"sha256:e49ea4c1a9543d2bd8a747ff24411509c29e4bdcde05b5b0895e2120cb1a761d",
|
||||
"sha256:e4e08305bfd76ba8edab08dcc6496f40674f44eb9d5e23153efa0a35750337e8",
|
||||
"sha256:e6fa05a680e35d0fcc1470cb070b10e6fe247af54768f488ed93542e71339d6f",
|
||||
"sha256:e7e6f2d6fd48422071cc8a6f8542016f350b79cc782752de531577d35e9bd677",
|
||||
"sha256:e904c0381c014b914136c492c8fa711ca4cced4e9b3d110e5e7d436d0fc289e8",
|
||||
"sha256:ec2b0ab7edc8cd4b0eb428b38ed89079bdc20c6bdb5f889d353011038caac2f9",
|
||||
"sha256:ef5ce841e102278c1c2e98f043db99d6755b1c58bde475516aef3a008ed7f28e",
|
||||
"sha256:f351c7d7d92f67c0609329ab2735eee0426a03022771b00102816a72715bb00b",
|
||||
"sha256:fab7c640815812ed5f10fbee7abbf58788d602046b7bb3af9b1ac753a6d5e916",
|
||||
"sha256:fc06cc8073c8e87072138ba1e431300e2d408f054b27047d047b549455066ff4"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==10.3"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
||||
25
packages/python/test/fixtures/30-asgi-lifespan/api/raw.py
vendored
Normal file
25
packages/python/test/fixtures/30-asgi-lifespan/api/raw.py
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
async def app(scope, receive, send):
|
||||
if scope['type'] == 'http':
|
||||
await send(
|
||||
{
|
||||
"type": "http.response.start",
|
||||
"status": 200,
|
||||
"headers": [[b"content-type", b"text/html"]],
|
||||
}
|
||||
)
|
||||
await send(
|
||||
{
|
||||
"type": "http.response.body",
|
||||
"body": b"asgi:RANDOMNESS_PLACEHOLDER"
|
||||
}
|
||||
)
|
||||
elif scope['type'] == 'lifespan':
|
||||
while True:
|
||||
message = await receive()
|
||||
if message['type'] == 'lifespan.startup':
|
||||
await send({'type': 'lifespan.startup.complete'})
|
||||
elif message['type'] == 'lifespan.shutdown':
|
||||
await send({'type': 'lifespan.shutdown.complete'})
|
||||
return
|
||||
else:
|
||||
assert False, "unreachable"
|
||||
8
packages/python/test/fixtures/30-asgi-lifespan/api/sani22.py
vendored
Normal file
8
packages/python/test/fixtures/30-asgi-lifespan/api/sani22.py
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
from sanic import Sanic
|
||||
from sanic import response
|
||||
app = Sanic("vercel_test")
|
||||
|
||||
|
||||
@app.route("/api/sani22.py")
|
||||
async def index(request):
|
||||
return response.text("asgi:RANDOMNESS_PLACEHOLDER")
|
||||
13
packages/python/test/fixtures/30-asgi-lifespan/vercel.json
vendored
Normal file
13
packages/python/test/fixtures/30-asgi-lifespan/vercel.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [
|
||||
{
|
||||
"src": "api/*.py",
|
||||
"use": "@vercel/python"
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{ "path": "/api/raw.py", "mustContain": "asgi:RANDOMNESS_PLACEHOLDER" },
|
||||
{ "path": "/api/sani22.py", "mustContain": "asgi:RANDOMNESS_PLACEHOLDER" }
|
||||
]
|
||||
}
|
||||
3
packages/python/test/unit.test.ts
vendored
3
packages/python/test/unit.test.ts
vendored
@@ -19,9 +19,6 @@ it('should only match supported versions, otherwise throw an error', async () =>
|
||||
expect(
|
||||
getSupportedPythonVersion({ pipLockPythonVersion: '3.9' })
|
||||
).toHaveProperty('runtime', 'python3.9');
|
||||
expect(
|
||||
getSupportedPythonVersion({ pipLockPythonVersion: '3.6' })
|
||||
).toHaveProperty('runtime', 'python3.6');
|
||||
});
|
||||
|
||||
it('should ignore minor version in vercel dev', async () => {
|
||||
|
||||
@@ -167,13 +167,23 @@ elif 'app' in __vc_variables:
|
||||
else:
|
||||
print('using Asynchronous Server Gateway Interface (ASGI)')
|
||||
# Originally authored by Jordan Eremieff and included under MIT license:
|
||||
# https://github.com/erm/mangum/blob/b4d21c8f5e304a3e17b88bc9fa345106acc50ad7/mangum/__init__.py
|
||||
# https://github.com/erm/mangum/blob/b4d21c8f5e304a3e17b88bc9fa345106acc50ad7/LICENSE
|
||||
# https://github.com/erm/mangum/blob/07ce20a0e2f67c5c2593258a92c03fdc66d9edda/mangum/__init__.py
|
||||
# https://github.com/erm/mangum/blob/07ce20a0e2f67c5c2593258a92c03fdc66d9edda/LICENSE
|
||||
import asyncio
|
||||
import enum
|
||||
import logging
|
||||
from contextlib import ExitStack
|
||||
from urllib.parse import urlparse
|
||||
from werkzeug.datastructures import Headers
|
||||
|
||||
def get_event_loop():
|
||||
try:
|
||||
return asyncio.get_running_loop()
|
||||
except:
|
||||
if sys.version_info < (3, 10):
|
||||
return asyncio.get_event_loop()
|
||||
else:
|
||||
return asyncio.get_event_loop_policy().get_event_loop()
|
||||
|
||||
class ASGICycleState(enum.Enum):
|
||||
REQUEST = enum.auto()
|
||||
@@ -194,8 +204,8 @@ elif 'app' in __vc_variables:
|
||||
ASGI instance using the connection scope.
|
||||
Runs until the response is completely read from the application.
|
||||
"""
|
||||
loop = asyncio.new_event_loop()
|
||||
self.app_queue = asyncio.Queue(loop=loop)
|
||||
loop = get_event_loop()
|
||||
self.app_queue = asyncio.Queue()
|
||||
self.put_message({'type': 'http.request', 'body': body, 'more_body': False})
|
||||
|
||||
asgi_instance = app(self.scope, self.receive, self.send)
|
||||
@@ -257,6 +267,156 @@ elif 'app' in __vc_variables:
|
||||
self.response['body'] = base64.b64encode(self.body).decode('utf-8')
|
||||
self.response['encoding'] = 'base64'
|
||||
|
||||
class LifespanFailure(Exception):
|
||||
"""Raise when a lifespan failure event is sent by an application."""
|
||||
|
||||
class LifespanUnsupported(Exception):
|
||||
"""Raise when lifespan events are not supported by an application."""
|
||||
|
||||
class UnexpectedMessage(Exception):
|
||||
"""Raise when an unexpected message type is received during an ASGI cycle."""
|
||||
|
||||
class LifespanCycleState(enum.Enum):
|
||||
"""
|
||||
The state of the ASGI `lifespan` connection.
|
||||
* **CONNECTING** - Initial state. The ASGI application instance will be run with
|
||||
the connection scope containing the `lifespan` type.
|
||||
* **STARTUP** - The lifespan startup event has been pushed to the queue to be
|
||||
received by the application.
|
||||
* **SHUTDOWN** - The lifespan shutdown event has been pushed to the queue to be
|
||||
received by the application.
|
||||
* **FAILED** - A lifespan failure has been detected, and the connection will be
|
||||
closed with an error.
|
||||
* **UNSUPPORTED** - An application attempted to send a message before receiving
|
||||
the lifepan startup event. If the lifespan argument is "on", then the connection
|
||||
will be closed with an error.
|
||||
"""
|
||||
|
||||
CONNECTING = enum.auto()
|
||||
STARTUP = enum.auto()
|
||||
SHUTDOWN = enum.auto()
|
||||
FAILED = enum.auto()
|
||||
UNSUPPORTED = enum.auto()
|
||||
|
||||
class Lifespan:
|
||||
|
||||
def __init__(self, app):
|
||||
self.app = app
|
||||
self.state = LifespanCycleState.CONNECTING
|
||||
self.exception = None
|
||||
self.logger = logging.getLogger('lifespan')
|
||||
self.loop = get_event_loop()
|
||||
self.app_queue = asyncio.Queue()
|
||||
self.startup_event = asyncio.Event()
|
||||
self.shutdown_event = asyncio.Event()
|
||||
|
||||
|
||||
def __enter__(self) -> None:
|
||||
"""Runs the event loop for application startup."""
|
||||
self.loop.create_task(self.run())
|
||||
self.loop.run_until_complete(self.startup())
|
||||
|
||||
def __exit__(
|
||||
self,
|
||||
exc_type,
|
||||
exc_value,
|
||||
traceback,
|
||||
) -> None:
|
||||
"""Runs the event loop for application shutdown."""
|
||||
self.loop.run_until_complete(self.shutdown())
|
||||
|
||||
async def run(self):
|
||||
"""Calls the application with the `lifespan` connection scope."""
|
||||
try:
|
||||
await self.app(
|
||||
{"type": "lifespan", "asgi": {"spec_version": "2.0", "version": "3.0"}},
|
||||
self.receive,
|
||||
self.send,
|
||||
)
|
||||
except LifespanUnsupported:
|
||||
self.logger.info("ASGI 'lifespan' protocol appears unsupported.")
|
||||
except (LifespanFailure, UnexpectedMessage) as exc:
|
||||
self.exception = exc
|
||||
except BaseException as exc:
|
||||
self.logger.error("Exception in 'lifespan' protocol.", exc_info=exc)
|
||||
finally:
|
||||
self.startup_event.set()
|
||||
self.shutdown_event.set()
|
||||
|
||||
async def send(self, message):
|
||||
"""Awaited by the application to send ASGI `lifespan` events."""
|
||||
message_type = message["type"]
|
||||
|
||||
if self.state is LifespanCycleState.CONNECTING:
|
||||
# If a message is sent before the startup event is received by the
|
||||
# application, then assume that lifespan is unsupported.
|
||||
self.state = LifespanCycleState.UNSUPPORTED
|
||||
raise LifespanUnsupported("Lifespan protocol appears unsupported.")
|
||||
|
||||
if message_type not in (
|
||||
"lifespan.startup.complete",
|
||||
"lifespan.shutdown.complete",
|
||||
"lifespan.startup.failed",
|
||||
"lifespan.shutdown.failed",
|
||||
):
|
||||
self.state = LifespanCycleState.FAILED
|
||||
raise UnexpectedMessage(f"Unexpected '{message_type}' event received.")
|
||||
|
||||
if self.state is LifespanCycleState.STARTUP:
|
||||
if message_type == "lifespan.startup.complete":
|
||||
self.startup_event.set()
|
||||
elif message_type == "lifespan.startup.failed":
|
||||
self.state = LifespanCycleState.FAILED
|
||||
self.startup_event.set()
|
||||
message_value = message.get("message", "")
|
||||
raise LifespanFailure(f"Lifespan startup failure. {message_value}")
|
||||
|
||||
elif self.state is LifespanCycleState.SHUTDOWN:
|
||||
if message_type == "lifespan.shutdown.complete":
|
||||
self.shutdown_event.set()
|
||||
elif message_type == "lifespan.shutdown.failed":
|
||||
self.state = LifespanCycleState.FAILED
|
||||
self.shutdown_event.set()
|
||||
message_value = message.get("message", "")
|
||||
raise LifespanFailure(f"Lifespan shutdown failure. {message_value}")
|
||||
|
||||
async def receive(self):
|
||||
"""Awaited by the application to receive ASGI `lifespan` events."""
|
||||
if self.state is LifespanCycleState.CONNECTING:
|
||||
|
||||
# Connection established. The next event returned by the queue will be
|
||||
# `lifespan.startup` to inform the application that the connection is
|
||||
# ready to receive lfiespan messages.
|
||||
self.state = LifespanCycleState.STARTUP
|
||||
|
||||
elif self.state is LifespanCycleState.STARTUP:
|
||||
|
||||
# Connection shutting down. The next event returned by the queue will be
|
||||
# `lifespan.shutdown` to inform the application that the connection is now
|
||||
# closing so that it may perform cleanup.
|
||||
self.state = LifespanCycleState.SHUTDOWN
|
||||
|
||||
return await self.app_queue.get()
|
||||
|
||||
async def startup(self) -> None:
|
||||
"""Pushes the `lifespan` startup event to the queue and handles errors."""
|
||||
await self.app_queue.put({"type": "lifespan.startup"})
|
||||
await self.startup_event.wait()
|
||||
if self.state is LifespanCycleState.FAILED:
|
||||
raise LifespanFailure(self.exception)
|
||||
|
||||
if not self.exception:
|
||||
self.logger.info("Application startup complete.")
|
||||
else:
|
||||
self.logger.info("Application startup failed.")
|
||||
|
||||
async def shutdown(self) -> None:
|
||||
"""Pushes the `lifespan` shutdown event to the queue and handles errors."""
|
||||
await self.app_queue.put({"type": "lifespan.shutdown"})
|
||||
await self.shutdown_event.wait()
|
||||
if self.state is LifespanCycleState.FAILED:
|
||||
raise LifespanFailure(self.exception)
|
||||
|
||||
def vc_handler(event, context):
|
||||
payload = json.loads(event['body'])
|
||||
|
||||
@@ -289,9 +449,13 @@ elif 'app' in __vc_variables:
|
||||
'raw_path': path.encode(),
|
||||
}
|
||||
|
||||
asgi_cycle = ASGICycle(scope)
|
||||
response = asgi_cycle(__vc_module.app, body)
|
||||
return response
|
||||
with ExitStack() as stack:
|
||||
lifespan = Lifespan(__vc_module.app)
|
||||
stack.enter_context(lifespan)
|
||||
|
||||
asgi_cycle = ASGICycle(scope)
|
||||
response = asgi_cycle(__vc_module.app, body)
|
||||
return response
|
||||
|
||||
else:
|
||||
print('Missing variable `handler` or `app` in file "__VC_HANDLER_ENTRYPOINT".')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/redwood",
|
||||
"version": "1.0.8",
|
||||
"version": "1.0.9",
|
||||
"main": "./dist/index.js",
|
||||
"license": "MIT",
|
||||
"homepage": "https://vercel.com/docs",
|
||||
@@ -28,6 +28,6 @@
|
||||
"@types/aws-lambda": "8.10.19",
|
||||
"@types/node": "*",
|
||||
"@types/semver": "6.0.0",
|
||||
"@vercel/build-utils": "5.0.3"
|
||||
"@vercel/build-utils": "5.0.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/remix",
|
||||
"version": "1.0.9",
|
||||
"version": "1.0.10",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"homepage": "https://vercel.com/docs",
|
||||
@@ -26,7 +26,7 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "27.5.1",
|
||||
"@types/node": "*",
|
||||
"@vercel/build-utils": "5.0.3",
|
||||
"@vercel/build-utils": "5.0.4",
|
||||
"typescript": "4.6.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@vercel/ruby",
|
||||
"author": "Nathan Cahill <nathan@nathancahill.com>",
|
||||
"version": "1.3.15",
|
||||
"version": "1.3.16",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/ruby",
|
||||
@@ -23,7 +23,7 @@
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "8.0.0",
|
||||
"@types/semver": "6.0.0",
|
||||
"@vercel/build-utils": "5.0.3",
|
||||
"@vercel/build-utils": "5.0.4",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"execa": "2.0.4",
|
||||
"fs-extra": "^7.0.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/static-build",
|
||||
"version": "1.0.8",
|
||||
"version": "1.0.9",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/build-step",
|
||||
@@ -37,7 +37,7 @@
|
||||
"@types/ms": "0.7.31",
|
||||
"@types/node-fetch": "2.5.4",
|
||||
"@types/promise-timeout": "1.3.0",
|
||||
"@vercel/build-utils": "5.0.3",
|
||||
"@vercel/build-utils": "5.0.4",
|
||||
"@vercel/frameworks": "1.1.1",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@vercel/routing-utils": "2.0.0",
|
||||
@@ -45,7 +45,7 @@
|
||||
"get-port": "5.0.0",
|
||||
"is-port-reachable": "2.0.1",
|
||||
"ms": "2.1.2",
|
||||
"node-fetch": "2.6.1",
|
||||
"node-fetch": "2.6.7",
|
||||
"rc9": "1.2.0",
|
||||
"typescript": "4.3.4"
|
||||
}
|
||||
|
||||
@@ -98,7 +98,11 @@ async function nowDeploy(bodies, randomness, uploadNowJson) {
|
||||
logWithinTest('state is READY, moving on');
|
||||
break;
|
||||
}
|
||||
logWithinTest('state is ', readyState, 'retrying in 1 second');
|
||||
if (i > 0 && i % 25 === 0) {
|
||||
logWithinTest(
|
||||
`State of https://${deploymentUrl} is ${readyState}, retry number ${i}`
|
||||
);
|
||||
}
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user