Add support for specifying the target generator config file

This commit is contained in:
James M. Greene
2022-08-05 17:31:59 -05:00
parent 404d23c4a6
commit 7c3932ff89
23 changed files with 410 additions and 38 deletions

View File

@@ -6,7 +6,10 @@ runs:
main: 'dist/index.js' main: 'dist/index.js'
inputs: inputs:
static_site_generator: static_site_generator:
description: 'Optional static site generator to attempt to configure (nuxt, next or gatsby)' description: 'Optional static site generator to attempt to configure: "nuxt", "next", or "gatsby"'
required: false
generator_config_file:
description: 'Optional file path to static site generator configuration file'
required: false required: false
token: token:
description: 'GitHub token' description: 'GitHub token'

View File

@@ -171,7 +171,7 @@ class ConfigParser {
var depth = 0 var depth = 0
const properties = propertyName.split('.') const properties = propertyName.split('.')
var lastNode = configurationObject var lastNode = configurationObject
while (1) { while (true) {
// Find the node for the current property // Find the node for the current property
var propertyNode = this.findProperty(lastNode, properties[depth]) var propertyNode = this.findProperty(lastNode, properties[depth])

View File

@@ -1,4 +1,5 @@
const fs = require('fs') const fs = require('fs')
const core = require('@actions/core')
const { ConfigParser } = require('./config-parser') const { ConfigParser } = require('./config-parser')
const { getTempFolder, compareFiles } = require('./test-helpers') const { getTempFolder, compareFiles } = require('./test-helpers')
@@ -134,8 +135,18 @@ const cases = [
] ]
describe('config-parser', () => { describe('config-parser', () => {
beforeEach(() => {
jest.restoreAllMocks()
// Mock error/warning/info/debug to silence their output
jest.spyOn(core, 'error').mockImplementation(jest.fn())
jest.spyOn(core, 'warning').mockImplementation(jest.fn())
jest.spyOn(core, 'info').mockImplementation(jest.fn())
jest.spyOn(core, 'debug').mockImplementation(jest.fn())
})
cases.forEach(({ property, source, expected }, index) => { cases.forEach(({ property, source, expected }, index) => {
it(`Inject path properly for case #${index}`, () => { it(`injects path properly for case #${index}`, () => {
// Write the source file // Write the source file
const sourceFile = `${tempFolder}/source.js` const sourceFile = `${tempFolder}/source.js`
fs.writeFileSync(sourceFile, source, { encoding: 'utf8' }) fs.writeFileSync(sourceFile, source, { encoding: 'utf8' })

View File

@@ -6,6 +6,7 @@ function getRequiredVars() {
repositoryNwo: process.env.GITHUB_REPOSITORY, repositoryNwo: process.env.GITHUB_REPOSITORY,
githubToken: core.getInput('token'), githubToken: core.getInput('token'),
staticSiteGenerator: core.getInput('static_site_generator'), staticSiteGenerator: core.getInput('static_site_generator'),
generatorConfigFile: core.getInput('generator_config_file'),
enablement: core.getInput('enablement') !== 'false' enablement: core.getInput('enablement') !== 'false'
} }
} }

View File

@@ -0,0 +1,7 @@
module.exports = {
siteMetadata: {
title: `My Gatsby Site`,
siteUrl: `https://www.yourdomain.tld`,
},
plugins: [],
}

View File

@@ -0,0 +1,8 @@
module.exports = {
pathPrefix: "/docs/",
siteMetadata: {
title: `My Gatsby Site`,
siteUrl: `https://www.yourdomain.tld`,
},
plugins: [],
}

View File

@@ -0,0 +1,8 @@
export default {
pathPrefix: "/docs/",
siteMetadata: {
title: `My Gatsby Site`,
siteUrl: `https://www.yourdomain.tld`,
},
plugins: [],
}

View File

@@ -0,0 +1,7 @@
export default {
siteMetadata: {
title: `My Gatsby Site`,
siteUrl: `https://www.yourdomain.tld`,
},
plugins: [],
}

View File

@@ -0,0 +1,7 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
}
module.exports = nextConfig

View File

@@ -0,0 +1,9 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {images: {unoptimized: true}},
basePath: '/docs',
reactStrictMode: true,
swcMinify: true
}
module.exports = nextConfig

View File

@@ -0,0 +1,9 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {images: {unoptimized: true}},
basePath: '/docs',
reactStrictMode: true,
swcMinify: true
}
export default nextConfig

View File

@@ -0,0 +1,7 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
}
export default nextConfig

View File

@@ -0,0 +1,15 @@
const getAllDynamicRoute = async function() {
const routes = await (async () => {
return ['/posts/hello-world', '/posts/hello-again'];
})();
return routes;
};
module.exports = {
mode: 'universal',
generate: {
async routes () {
return getAllDynamicRoute();
}
}
};

View File

@@ -0,0 +1,17 @@
const getAllDynamicRoute = async function() {
const routes = await (async () => {
return ['/posts/hello-world', '/posts/hello-again'];
})();
return routes;
};
module.exports = {
target: 'static',
router: {base: '/docs/'},
mode: 'universal',
generate: {
async routes () {
return getAllDynamicRoute();
}
}
};

View File

@@ -0,0 +1,17 @@
const getAllDynamicRoute = async function() {
const routes = await (async () => {
return ['/posts/hello-world', '/posts/hello-again'];
})();
return routes;
};
export default {
target: 'static',
router: {base: '/docs/'},
mode: 'universal',
generate: {
async routes () {
return getAllDynamicRoute();
}
}
};

View File

@@ -0,0 +1,15 @@
const getAllDynamicRoute = async function() {
const routes = await (async () => {
return ['/posts/hello-world', '/posts/hello-again'];
})();
return routes;
};
export default {
mode: 'universal',
generate: {
async routes () {
return getAllDynamicRoute();
}
}
};

View File

@@ -0,0 +1,44 @@
module.exports = {
// Disable server-side rendering: https://go.nuxtjs.dev/ssr-mode
ssr: false,
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'nuxt',
htmlAttrs: {
lang: 'en'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
{ name: 'format-detection', content: 'telephone=no' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
],
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}

View File

@@ -0,0 +1,46 @@
module.exports = {
// Disable server-side rendering: https://go.nuxtjs.dev/ssr-mode
target: 'static',
router: { base: "/docs/" },
ssr: false,
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'nuxt',
htmlAttrs: {
lang: 'en'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
{ name: 'format-detection', content: 'telephone=no' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
],
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}

View File

@@ -0,0 +1,46 @@
export default {
// Disable server-side rendering: https://go.nuxtjs.dev/ssr-mode
target: 'static',
router: { base: "/docs/" },
ssr: false,
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'nuxt',
htmlAttrs: {
lang: 'en'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
{ name: 'format-detection', content: 'telephone=no' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
],
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}

View File

@@ -0,0 +1,44 @@
export default {
// Disable server-side rendering: https://go.nuxtjs.dev/ssr-mode
ssr: false,
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'nuxt',
htmlAttrs: {
lang: 'en'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
{ name: 'format-detection', content: 'telephone=no' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
],
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}

View File

@@ -9,13 +9,13 @@ const outputPagesBaseUrl = require('./output-pages-base-url')
async function main() { async function main() {
try { try {
const { repositoryNwo, githubToken, enablement, staticSiteGenerator } = getContext() const { repositoryNwo, githubToken, enablement, staticSiteGenerato, generatorConfigFile } = getContext()
const pageObject = await findOrCreatePagesSite({ repositoryNwo, githubToken, enablement }) const pageObject = await findOrCreatePagesSite({ repositoryNwo, githubToken, enablement })
const siteUrl = new URL(pageObject.html_url) const siteUrl = new URL(pageObject.html_url)
if (staticSiteGenerator) { if (staticSiteGenerator) {
setPagesPath({ staticSiteGenerator, path: siteUrl.pathname }) setPagesPath({ staticSiteGenerator, generatorConfigFile, path: siteUrl.pathname })
} }
outputPagesBaseUrl(siteUrl) outputPagesBaseUrl(siteUrl)
} catch (error) { } catch (error) {

View File

@@ -1,13 +1,13 @@
const core = require('@actions/core') const core = require('@actions/core')
const { ConfigParser } = require('./config-parser') const { ConfigParser } = require('./config-parser')
// Return the settings to be passed to a {ConfigParser} for a given // Return the settings to be passed to a {ConfigParser} for a given static site generator,
// static site generator and a Pages path value to inject // optional configuration file path, and a Pages path value to inject
function getConfigParserSettings(staticSiteGenerator, path) { function getConfigParserSettings({ staticSiteGenerator, generatorConfigFile, path }) {
switch (staticSiteGenerator) { switch (staticSiteGenerator) {
case 'nuxt': case 'nuxt':
return { return {
configurationFile: './nuxt.config.js', configurationFile: generatorConfigFile || './nuxt.config.js',
blankConfigurationFile: `${__dirname}/blank-configurations/nuxt.js`, blankConfigurationFile: `${__dirname}/blank-configurations/nuxt.js`,
properties: { properties: {
// Configure a base path on the router // Configure a base path on the router
@@ -25,7 +25,7 @@ function getConfigParserSettings(staticSiteGenerator, path) {
} }
return { return {
configurationFile: './next.config.js', configurationFile: generatorConfigFile || './next.config.js',
blankConfigurationFile: `${__dirname}/blank-configurations/next.js`, blankConfigurationFile: `${__dirname}/blank-configurations/next.js`,
properties: { properties: {
// Configure a base path // Configure a base path
@@ -38,7 +38,7 @@ function getConfigParserSettings(staticSiteGenerator, path) {
} }
case 'gatsby': case 'gatsby':
return { return {
configurationFile: './gatsby-config.js', configurationFile: generatorConfigFile || './gatsby-config.js',
blankConfigurationFile: `${__dirname}/blank-configurations/gatsby.js`, blankConfigurationFile: `${__dirname}/blank-configurations/gatsby.js`,
properties: { properties: {
// Configure a path prefix // Configure a path prefix
@@ -51,10 +51,10 @@ function getConfigParserSettings(staticSiteGenerator, path) {
} }
// Inject Pages configuration in a given static site generator's configuration file // Inject Pages configuration in a given static site generator's configuration file
function setPagesPath({ staticSiteGenerator, path }) { function setPagesPath({ staticSiteGenerator, generatorConfigFile, path }) {
try { try {
// Parse the configuration file and try to inject the Pages configuration in it // Parse the configuration file and try to inject the Pages configuration in it
const settings = getConfigParserSettings(staticSiteGenerator, path) const settings = getConfigParserSettings({ staticSiteGenerator, generatorConfigFile, path })
new ConfigParser(settings).injectAll() new ConfigParser(settings).injectAll()
} catch (error) { } catch (error) {
// Logging // Logging

View File

@@ -1,5 +1,6 @@
const fs = require('fs') const fs = require('fs')
const path = require('path') const path = require('path')
const core = require('@actions/core')
const { getConfigParserSettings } = require('./set-pages-path') const { getConfigParserSettings } = require('./set-pages-path')
const { ConfigParser } = require('./config-parser') const { ConfigParser } = require('./config-parser')
@@ -10,41 +11,91 @@ const tempFolder = getTempFolder()
// Test suite // Test suite
describe('configParser', () => { describe('configParser', () => {
beforeEach(() => {
jest.restoreAllMocks()
// Mock error/warning/info/debug to silence their output
jest.spyOn(core, 'error').mockImplementation(jest.fn())
jest.spyOn(core, 'warning').mockImplementation(jest.fn())
jest.spyOn(core, 'info').mockImplementation(jest.fn())
jest.spyOn(core, 'debug').mockImplementation(jest.fn())
})
// Iterate over the static site generators // Iterate over the static site generators
;['next', 'nuxt', 'gatsby'].forEach(staticSiteGenerator => { ;['next', 'nuxt', 'gatsby'].forEach(staticSiteGenerator => {
// Folder containing the fixtures for a given static site generator // Folder containing the fixtures for a given static site generator
const fixtureFolder = `${__dirname}/fixtures/${staticSiteGenerator}` const fixtureFolder = `${__dirname}/fixtures/${staticSiteGenerator}`
// Iterate over the fixtures // Get fixture files, excluding expected results
fs.readdirSync(fixtureFolder).forEach(configurationFile => { const configurationFiles = fs.readdirSync(fixtureFolder).filter(filename => !filename.includes('.expected.'))
// Ignore expectation
if (configurationFile.endsWith('.expected.js')) {
return
}
it(`Inject path properly for ${staticSiteGenerator} in ${configurationFile}`, async () => { // Iterate over the fixtures, outputting to default configuration file path
// Get settings for the static site generator const defaultFileExtension = '.js'
const settings = getConfigParserSettings(staticSiteGenerator, '/docs/') configurationFiles
.filter(filename => filename.endsWith(defaultFileExtension))
.forEach(configurationFile => {
it(`injects path properly for ${staticSiteGenerator} in ${configurationFile} to default configuration file`, async () => {
// Copy the source fixture to a temp file
const fixtureSourceFile = `${fixtureFolder}/${configurationFile}`
const fixtureTargetFile = `${tempFolder}/${configurationFile}`
if (configurationFile !== 'blank.js') {
fs.copyFileSync(fixtureSourceFile, fixtureTargetFile)
} else if (fs.existsSync(fixtureTargetFile)) {
fs.rmSync(fixtureTargetFile)
}
// Copy the source fixture to a temp file // Get settings for the static site generator
const fixtureSourceFile = `${fixtureFolder}/${configurationFile}` const settings = getConfigParserSettings({ staticSiteGenerator, path: '/docs/' })
const fixtureTargetFile = `${tempFolder}/${configurationFile}` // Update the settings
if (configurationFile != 'blank.js') { settings.configurationFile = fixtureTargetFile
fs.copyFileSync(fixtureSourceFile, fixtureTargetFile) // Do the injection
} else if (fs.existsSync(fixtureTargetFile)) { new ConfigParser(settings).injectAll()
fs.rmSync(fixtureTargetFile)
}
// Update the settings and do the injection // Read the expected file
settings.configurationFile = fixtureTargetFile const expectedFile = `${fixtureFolder}/${path.basename(
new ConfigParser(settings).injectAll() configurationFile,
defaultFileExtension
)}.expected${defaultFileExtension}`
// Read the expected file // Compare the actual and expected files
const expectedFile = `${fixtureFolder}/${path.basename(configurationFile, '.js')}.expected.js` compareFiles(settings.configurationFile, expectedFile)
})
// Compare the actual and expected files
compareFiles(settings.configurationFile, expectedFile)
}) })
;['.js', '.cjs', '.mjs'].forEach(fileExtension => {
// Iterate over the fixtures, outputting to specified configuration file path
configurationFiles
.filter(filename => filename.endsWith(fileExtension))
.forEach(configurationFile => {
it(`injects path properly for ${staticSiteGenerator} in ${configurationFile} to specified *${fileExtension} configuration file`, async () => {
// Copy the source fixture to a temp file
const fixtureSourceFile = `${fixtureFolder}/${configurationFile}`
const fixtureTargetFile = `${tempFolder}/${configurationFile}`
if (configurationFile !== 'blank.js') {
fs.copyFileSync(fixtureSourceFile, fixtureTargetFile)
} else if (fs.existsSync(fixtureTargetFile)) {
fs.rmSync(fixtureTargetFile)
}
// Get settings for the static site generator
const settings = getConfigParserSettings({
staticSiteGenerator,
generatorConfigFile: fixtureTargetFile,
path: '/docs/'
})
// Do the injection
new ConfigParser(settings).injectAll()
// Read the expected file
const expectedFile = `${fixtureFolder}/${path.basename(
configurationFile,
fileExtension
)}.expected${fileExtension}`
// Compare the actual and expected files
compareFiles(settings.configurationFile, expectedFile)
})
})
}) })
}) })
}) })