Skip to content

Commit

Permalink
feat: pass through functions[].schedule property to ZISI (#3761)
Browse files Browse the repository at this point in the history
* chore: add test for schedule config field

* feat: pass through schedule field to zisi

* feat: put change behind feature flag

* feat: implement validation for schedule field

* chore: rename feature flag

* chore: order parameters

* chore: install cron-parser on right package

* chore: integrate test into existing

* chore: embed netli-link for cron syntax

Co-authored-by: Netlify Team Account 1 <netlify-team-account-1@users.noreply.github.com>
  • Loading branch information
1 parent 492264e commit d3ccdc4
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 6 deletions.
34 changes: 34 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/build/src/core/feature_flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const DEFAULT_FEATURE_FLAGS = {
buildbot_es_modules_esbuild: false,
buildbot_zisi_trace_nft: false,
buildbot_zisi_esbuild_parser: false,
buildbot_scheduled_functions: false,
}

module.exports = { normalizeCliFeatureFlags, DEFAULT_FEATURE_FLAGS }
4 changes: 3 additions & 1 deletion packages/build/src/plugins_core/functions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const isUsingEsbuild = (functionsConfig = {}) =>
// The function configuration keys returned by @netlify/config are not an exact
// match to the properties that @netlify/zip-it-and-ship-it expects. We do that
// translation here.
const normalizeFunctionConfig = ({ buildDir, functionConfig = {}, isRunningLocally }) => ({
const normalizeFunctionConfig = ({ buildDir, featureFlags, functionConfig = {}, isRunningLocally }) => ({
externalNodeModules: functionConfig.external_node_modules,
includedFiles: functionConfig.included_files,
includedFilesBasePath: buildDir,
Expand All @@ -39,6 +39,8 @@ const normalizeFunctionConfig = ({ buildDir, functionConfig = {}, isRunningLocal
// path that will get cached in between builds, allowing us to speed up the
// build process.
rustTargetDirectory: isRunningLocally ? undefined : resolve(buildDir, '.netlify', 'rust-functions-cache', '[name]'),

schedule: featureFlags.buildbot_scheduled_functions ? functionConfig.schedule : undefined,
})

const getZisiParameters = ({
Expand Down
3 changes: 3 additions & 0 deletions packages/build/tests/core/fixtures/schedule/functions/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict'

module.exports = () => {}
5 changes: 5 additions & 0 deletions packages/build/tests/core/fixtures/schedule/netlify.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[functions]
directory = "functions"

[functions.test]
schedule="@daily"
19 changes: 14 additions & 5 deletions packages/build/tests/core/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -354,28 +354,33 @@ test.serial('Passes the right base path properties to zip-it-and-ship-it', async
t.is(repositoryRoot, fixtureDir)
})

// eslint-disable-next-line max-statements
test.serial('Passes the right feature flags to zip-it-and-ship-it', async (t) => {
const mockZipFunctions = sinon.stub().resolves()
const stub = sinon.stub(zipItAndShipIt, 'zipFunctions').get(() => mockZipFunctions)

await runFixture(t, 'core', { snapshot: false })
await runFixture(t, 'core', {
await runFixture(t, 'schedule', { snapshot: false })
await runFixture(t, 'schedule', {
flags: { featureFlags: { buildbot_zisi_trace_nft: true } },
snapshot: false,
})
await runFixture(t, 'core', {
await runFixture(t, 'schedule', {
flags: { featureFlags: { buildbot_build_go_functions: true } },
snapshot: false,
})
await runFixture(t, 'core', {
await runFixture(t, 'schedule', {
flags: { featureFlags: { buildbot_zisi_esbuild_parser: true } },
snapshot: false,
})
await runFixture(t, 'schedule', {
flags: { featureFlags: { buildbot_scheduled_functions: true } },
snapshot: false,
})

stub.restore()

// eslint-disable-next-line no-magic-numbers
t.is(mockZipFunctions.callCount, 4)
t.is(mockZipFunctions.callCount, 5)

t.false(mockZipFunctions.getCall(0).args[2].featureFlags.traceWithNft)
t.false(mockZipFunctions.getCall(0).args[2].featureFlags.buildGoSource)
Expand All @@ -384,6 +389,10 @@ test.serial('Passes the right feature flags to zip-it-and-ship-it', async (t) =>
t.true(mockZipFunctions.getCall(1).args[2].featureFlags.traceWithNft)
t.true(mockZipFunctions.getCall(2).args[2].featureFlags.buildGoSource)
t.true(mockZipFunctions.getCall(3).args[2].featureFlags.parseWithEsbuild)

t.is(mockZipFunctions.getCall(0).args[2].config.test.schedule, undefined)
// eslint-disable-next-line no-magic-numbers
t.is(mockZipFunctions.getCall(4).args[2].config.test.schedule, '@daily')
})

test('Print warning on lingering processes', async (t) => {
Expand Down
1 change: 1 addition & 0 deletions packages/config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"@ungap/from-entries": "^0.2.1",
"array-flat-polyfill": "^1.0.1",
"chalk": "^4.1.2",
"cron-parser": "^4.1.0",
"deepmerge": "^4.2.2",
"dot-prop": "^5.3.0",
"execa": "^5.1.1",
Expand Down
1 change: 1 addition & 0 deletions packages/config/src/functions_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const FUNCTION_CONFIG_PROPERTIES = new Set([
'ignored_node_modules',
'included_files',
'node_bundler',
'schedule',
])

// Takes a functions configuration object and looks for the functions directory
Expand Down
22 changes: 22 additions & 0 deletions packages/config/src/validate/validations.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
/* eslint-disable max-lines */
'use strict'

const CronParser = require('cron-parser')
const isPlainObj = require('is-plain-obj')
const validateNpmPackageName = require('validate-npm-package-name')

const { bundlers, WILDCARD_ALL: FUNCTIONS_CONFIG_WILDCARD_ALL } = require('../functions_config')

const { functionsDirectoryCheck, isArrayOfObjects, isArrayOfStrings, isString, validProperties } = require('./helpers')

/**
* @param {string} cron
* @returns {boolean}
*/
const isValidCronExpression = (cron) => {
try {
CronParser.parseExpression(cron)
return true
} catch (error) {
return false
}
}

// List of validations performed on the configuration file.
// Validation are performed in order: parent should be before children.
// Each validation is an object with the following properties:
Expand Down Expand Up @@ -212,6 +226,14 @@ const POST_NORMALIZE_VALIDATIONS = [
functions: { directory: 'my-functions' },
}),
},
{
property: 'functions.*.schedule',
check: isValidCronExpression,
message: 'must be a valid cron expression (see https://ntl.fyi/cron-syntax).',
example: (value, key, prevPath) => ({
functions: { [prevPath[1]]: { schedule: '5 4 * * *' } },
}),
},
{
property: 'functionsDirectory',
check: isString,
Expand Down

0 comments on commit d3ccdc4

Please sign in to comment.