Compare commits

..

10 Commits

Author SHA1 Message Date
Steven
8d5f6f1fa3 Publish Stable
- @now/frameworks@0.0.10
 - @now/build-utils@2.0.0
 - now@17.0.4
 - @now/go@1.0.4
 - @now/next@2.3.16
 - @now/python@1.1.4
 - @now/routing-utils@1.6.0
2020-02-21 18:09:20 -05:00
Steven
617f610c07 [tests] Update cancel workflow (#3817)
Update to latest version, [0.2.0](https://github.com/styfle/cancel-workflow-action/releases/tag/0.2.0), which will fix cancelling on push.

Also this action is available in the [marketplace](https://github.com/marketplace/actions/cancel-workflow-action).
2020-02-21 18:00:27 -05:00
Steven
3229ba0106 Publish Canary
- @now/go@1.0.4-canary.3
 - @now/python@1.1.4-canary.1
2020-02-21 17:27:20 -05:00
Steven
d16a6e4716 [now-go] Fix path segments in now dev (#3816)
The combination of file renaming and brackets doesn't work well for go build so we need to add the file extension back before building.

I also simplified the `.now/cache/folder` logic because it should be the same whether `builds` is defined or not (aka zero config).
2020-02-21 22:25:44 +00:00
Steven
4e5156fb0b [now-python] Fix path segments in now dev (#3815)
The combination of file renaming and brackets doesn't work well for python imports so we need too add the file extension back before importing the python module.

I also simplified the `.now/cache/folder` logic because it should be the same whether `builds` is defined or not (aka zero config).
2020-02-21 20:45:41 +00:00
Joe Haddad
3c013cc36b Publish Canary
- @now/build-utils@2.0.0-canary.2
 - @now/next@2.3.16-canary.1
2020-02-21 11:06:44 -05:00
Joe Haddad
1ed83135be Add Bypass Token to Next.js Builder (#3811)
This pull request adds the bypass token to returned `Prerender` output objects.

There's no tests as this doesn't exist in production yet.
2020-02-21 16:05:22 +00:00
Joe Haddad
0e71ff2df1 [now-build-utils] Add bypassToken to Prerender for iSSG (#3810)
This pull request adds a new `bypassToken` field to the `Prerender` output.

The field is required to be at least 128 bits for security reasons!
2020-02-20 01:59:45 +00:00
JJ Kasper
d8e98ee476 Publish Canary
- @now/next@2.3.16-canary.0
 - @now/routing-utils@1.5.4-canary.0
2020-02-19 16:23:25 -06:00
JJ Kasper
1bc1e8a9b1 [now-routing-utils] Update to not pass used segments in redirect query (#3809)
This updates to not pass segments already used in a redirect's destination query since these values are most likely unwanted and can still be manually added if desired. This change does not affect rewrites and we still pass through all segments in the query
2020-02-19 22:13:36 +00:00
16 changed files with 100 additions and 55 deletions

View File

@@ -4,13 +4,14 @@ on:
branches:
- '*'
- '!master'
jobs:
cancel:
name: 'Cancel Previous Runs'
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- uses: styfle/cancel-workflow-action@master
- uses: styfle/cancel-workflow-action@0.2.0
with:
workflow_id: 435869
access_token: ${{ secrets.GITHUB_WORKFLOW_TOKEN }}

View File

@@ -1,6 +1,6 @@
{
"name": "@now/frameworks",
"version": "0.0.10-canary.0",
"version": "0.0.10",
"main": "frameworks.json",
"license": "UNLICENSED"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@now/build-utils",
"version": "2.0.0-canary.1",
"version": "2.0.0",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",

View File

@@ -8,6 +8,7 @@ interface PrerenderOptions {
lambda: Lambda;
fallback: FileBlob | FileFsRef | FileRef | null;
group?: number;
bypassToken?: string | null /* optional to be non-breaking change */;
}
export class Prerender {
@@ -16,8 +17,15 @@ export class Prerender {
public lambda: Lambda;
public fallback: FileBlob | FileFsRef | FileRef | null;
public group?: number;
public bypassToken: string | null;
constructor({ expiration, lambda, fallback, group }: PrerenderOptions) {
constructor({
expiration,
lambda,
fallback,
group,
bypassToken,
}: PrerenderOptions) {
this.type = 'Prerender';
this.expiration = expiration;
this.lambda = lambda;
@@ -32,6 +40,22 @@ export class Prerender {
}
this.group = group;
if (bypassToken == null) {
this.bypassToken = null;
} else if (typeof bypassToken === 'string') {
if (bypassToken.length < 32) {
// Enforce 128 bits of entropy for safety reasons (UUIDv4 size)
throw new Error(
'The `bypassToken` argument for `Prerender` must be 32 characters or more.'
);
}
this.bypassToken = bypassToken;
} else {
throw new Error(
'The `bypassToken` argument for `Prerender` must be a `string`.'
);
}
if (typeof fallback === 'undefined') {
throw new Error(
'The `fallback` argument for `Prerender` needs to be a `FileBlob`, `FileFsRef`, `FileRef`, or null.'

View File

@@ -1,6 +1,6 @@
{
"name": "now",
"version": "17.0.4-canary.3",
"version": "17.0.4",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Now",

View File

@@ -12,6 +12,7 @@ import {
shouldServe,
Files,
debug,
Meta,
} from '@now/build-utils';
import { createGo, getAnalyzedEntrypoint, OUT_EXTENSION } from './go-helpers';
@@ -40,12 +41,18 @@ async function initPrivateGit(credentials: string) {
* Since `go build` does not support files that begin with a square bracket,
* we must rename to something temporary to support Path Segments.
* The output file is not renamed because v3 builders can't rename outputs
* which works great for this feature.
* which works great for this feature. We also need to add a suffix during `now dev`
* since the entrypoint is already stripped of its suffix before build() is called.
*/
async function getRenamedEntrypoint(entrypoint: string, files: Files) {
async function getRenamedEntrypoint(
entrypoint: string,
files: Files,
meta: Meta
) {
const filename = basename(entrypoint);
if (filename.startsWith('[')) {
const newEntrypoint = entrypoint.replace('/[', '/now-bracket[');
const suffix = meta.isDev && !entrypoint.endsWith('.go') ? '.go' : '';
const newEntrypoint = entrypoint.replace('/[', '/now-bracket[') + suffix;
const file = files[entrypoint];
delete files[entrypoint];
files[newEntrypoint] = file;
@@ -81,7 +88,7 @@ We highly recommend you leverage Go Modules in your project.
Learn more: https://github.com/golang/go/wiki/Modules
`);
}
entrypoint = await getRenamedEntrypoint(entrypoint, files);
entrypoint = await getRenamedEntrypoint(entrypoint, files, meta);
const entrypointArr = entrypoint.split(sep);
// eslint-disable-next-line prefer-const
@@ -126,26 +133,16 @@ Learn more: https://zeit.co/docs/v2/advanced/builders/#go
const parsedAnalyzed = JSON.parse(analyzed) as Analyzed;
if (meta.isDev) {
let base = null;
if (config && config.zeroConfig) {
base = workPath;
} else {
base = dirname(downloadedFiles['now.json'].fsPath);
}
const destNow = join(
base,
// Create cache so Go rebuilds fast with `now dev`
goPath = join(
workPath,
'.now',
'cache',
basename(entrypoint, '.go'),
'src',
'lambda'
'now-go',
basename(entrypoint, '.go')
);
// this will ensure Go rebuilt fast
goPath = join(base, '.now', 'cache', basename(entrypoint, '.go'));
const destNow = join(goPath, 'src', 'lambda');
await download(downloadedFiles, destNow);
downloadedFiles = await glob('**', destNow);
downloadPath = destNow;
}

View File

@@ -1,6 +1,6 @@
{
"name": "@now/go",
"version": "1.0.4-canary.2",
"version": "1.0.4",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://zeit.co/docs/runtimes#official-runtimes/go",

View File

@@ -1,6 +1,6 @@
{
"name": "@now/next",
"version": "2.3.15",
"version": "2.3.16",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://zeit.co/docs/runtimes#official-runtimes/next-js",

View File

@@ -948,12 +948,14 @@ export const build = async ({
lambda,
fallback: htmlFsRef,
group: prerenderGroup,
bypassToken: prerenderManifest.bypassToken,
});
prerenders[outputPathData] = new Prerender({
expiration: initialRevalidate,
lambda,
fallback: jsonFsRef,
group: prerenderGroup,
bypassToken: prerenderManifest.bypassToken,
});
++prerenderGroup;

View File

@@ -614,6 +614,8 @@ export async function createLambdaFromPseudoLayers({
}
export type NextPrerenderedRoutes = {
bypassToken: string | null;
routes: {
[route: string]: {
initialRevalidate: number | false;
@@ -714,7 +716,7 @@ export async function getPrerenderManifest(
.catch(() => false);
if (!hasManifest) {
return { routes: {}, lazyRoutes: {} };
return { routes: {}, lazyRoutes: {}, bypassToken: null };
}
const manifest: {
@@ -734,6 +736,9 @@ export async function getPrerenderManifest(
dataRouteRegex: string;
};
};
preview?: {
previewModeId: string;
};
} = JSON.parse(await fs.readFile(pathPrerenderManifest, 'utf8'));
switch (manifest.version) {
@@ -741,7 +746,12 @@ export async function getPrerenderManifest(
const routes = Object.keys(manifest.routes);
const lazyRoutes = Object.keys(manifest.dynamicRoutes);
const ret: NextPrerenderedRoutes = { routes: {}, lazyRoutes: {} };
const ret: NextPrerenderedRoutes = {
routes: {},
lazyRoutes: {},
bypassToken:
(manifest.preview && manifest.preview.previewModeId) || null,
};
routes.forEach(route => {
const {
@@ -778,7 +788,7 @@ export async function getPrerenderManifest(
return ret;
}
default: {
return { routes: {}, lazyRoutes: {} };
return { routes: {}, lazyRoutes: {}, bypassToken: null };
}
}
}

View File

@@ -3,7 +3,7 @@
"strict": true,
"esModuleInterop": true,
"lib": ["esnext"],
"target": "esnext",
"target": "es2018",
"module": "commonjs",
"outDir": "dist",
"sourceMap": false,

View File

@@ -1,6 +1,6 @@
{
"name": "@now/python",
"version": "1.1.4-canary.0",
"version": "1.1.4",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://zeit.co/docs/runtimes#official-runtimes/python",

View File

@@ -35,21 +35,17 @@ export async function downloadFilesInWorkPath({
entrypoint,
workPath,
files,
meta,
config,
meta = {},
}: BuildOptions) {
debug('Downloading user files...');
let downloadedFiles = await download(files, workPath, meta);
if (meta && meta.isDev) {
let base = null;
if (config && config.zeroConfig) {
base = workPath;
} else {
base = dirname(downloadedFiles['now.json'].fsPath);
}
const destNow = join(base, '.now', 'cache', basename(entrypoint, '.py'));
if (meta.isDev) {
const destNow = join(
workPath,
'.now',
'cache',
basename(entrypoint, '.py')
);
await download(downloadedFiles, destNow);
downloadedFiles = await glob('**', destNow);
workPath = destNow;
@@ -151,14 +147,15 @@ export const build = async ({
const originalPyPath = join(__dirname, '..', 'now_init.py');
const originalNowHandlerPyContents = await readFile(originalPyPath, 'utf8');
// will be used on `from $here import handler`
// for example, `from api.users import handler`
debug('Entrypoint is', entrypoint);
const moduleName = entrypoint.replace(/\//g, '.').replace(/\.py$/, '');
// Since `now dev` renames source files, we must reference the original
const suffix = meta.isDev && !entrypoint.endsWith('.py') ? '.py' : '';
const entrypointWithSuffix = `${entrypoint}${suffix}`;
debug('Entrypoint with suffix is', entrypointWithSuffix);
const nowHandlerPyContents = originalNowHandlerPyContents
.replace(/__NOW_HANDLER_MODULE_NAME/g, moduleName)
.replace(/__NOW_HANDLER_ENTRYPOINT/g, entrypoint);
.replace(/__NOW_HANDLER_ENTRYPOINT/g, entrypointWithSuffix);
// in order to allow the user to have `server.py`, we need our `server.py` to be called
// somethig else

View File

@@ -1,6 +1,6 @@
{
"name": "@now/routing-utils",
"version": "1.5.3",
"version": "1.6.0",
"description": "ZEIT Now routing utilities",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",

View File

@@ -49,7 +49,7 @@ export function convertRedirects(
): Route[] {
return redirects.map(r => {
const { src, segments } = sourceToRegex(r.source);
const loc = replaceSegments(segments, r.destination);
const loc = replaceSegments(segments, r.destination, true);
const route: Route = {
src,
headers: { Location: loc },
@@ -137,7 +137,11 @@ export function sourceToRegex(
return { src: r.source, segments };
}
function replaceSegments(segments: string[], destination: string): string {
function replaceSegments(
segments: string[],
destination: string,
isRedirect?: boolean
): string {
const parsedDestination = parseUrl(destination, true);
delete parsedDestination.href;
delete parsedDestination.path;
@@ -169,6 +173,16 @@ function replaceSegments(segments: string[], destination: string): string {
}
for (const [name, value] of Object.entries(indexes)) {
if (
isRedirect &&
new RegExp(`\\${value}(?!\\d)`).test(pathname + (hash || ''))
) {
// Don't add segment to query if used in destination
// and it's a redirect so that we don't pollute the query
// with unwanted values
continue;
}
if (!(name in query)) {
query[name] = value;
}

View File

@@ -216,17 +216,17 @@ test('convertRedirects', () => {
},
{
src: '^\\/old(?:\\/([^\\/]+?))\\/path$',
headers: { Location: '/new/path/$1?segment=$1' },
headers: { Location: '/new/path/$1' },
status: 308,
},
{
src: '^\\/catchall(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))?$',
headers: { Location: '/catchall/$1/?hello=$1' },
headers: { Location: '/catchall/$1/' },
status: 308,
},
{
src: '^\\/another-catch(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))$',
headers: { Location: '/another-catch/$1/?hello=$1' },
headers: { Location: '/another-catch/$1/' },
status: 308,
},
{
@@ -241,7 +241,7 @@ test('convertRedirects', () => {
},
{
src: '^\\/hello(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))?$',
headers: { Location: '/something?world=$1#$1' },
headers: { Location: '/something#$1' },
status: 308,
},
];