diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 0000000..4b41f1c --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,10 @@ +# Prettier (formatter) configuration +--- +printWidth: 80 +tabWidth: 2 +useTabs: false +semi: false +singleQuote: true +trailingComma: none +bracketSpacing: false +arrowParens: avoid diff --git a/package.json b/package.json index 808e4f0..52ddded 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "configure-pages", "version": "1.0.0", - "description": "", + "description": "An action to enable Pages and extract various metadata about a site. It can also be used to configure various static site generators we support as starter workflows.", "main": "src/index.js", "scripts": { "prepare": "ncc build src/index.js -o dist --source-map --license licenses.txt", diff --git a/src/config-parser.js b/src/config-parser.js index 520252f..5ae53d8 100644 --- a/src/config-parser.js +++ b/src/config-parser.js @@ -1,13 +1,13 @@ -const fs = require("fs") -const espree = require("espree") -const format = require("string-format") +const fs = require('fs') +const espree = require('espree') +const format = require('string-format') const core = require('@actions/core') // Parse the AST const espreeOptions = { ecmaVersion: 6, - sourceType: "module", - range: true, + sourceType: 'module', + range: true } class ConfigParser { @@ -17,7 +17,9 @@ class ConfigParser { this.pathPropertyGatsby = `pathPrefix: '{0}'` this.configskeleton = `export default {\n {0}\n}` this.staticSiteConfig = staticSiteConfig - this.config = fs.existsSync(this.staticSiteConfig.filePath) ? fs.readFileSync(this.staticSiteConfig.filePath, "utf8") : null + this.config = fs.existsSync(this.staticSiteConfig.filePath) + ? fs.readFileSync(this.staticSiteConfig.filePath, 'utf8') + : null this.validate() } @@ -33,62 +35,72 @@ class ConfigParser { generateConfigFile() { switch (this.staticSiteConfig.type) { - case "nuxt": - return format(this.configskeleton, format(this.pathPropertyNuxt, this.staticSiteConfig.newPath)) + case 'nuxt': + return format( + this.configskeleton, + format(this.pathPropertyNuxt, this.staticSiteConfig.newPath) + ) break - case "next": - return format(this.configskeleton, format(this.pathPropertyNext, this.staticSiteConfig.newPath)) + case 'next': + return format( + this.configskeleton, + format(this.pathPropertyNext, this.staticSiteConfig.newPath) + ) break - case "gatsby": - return format(this.configskeleton, format(this.pathPropertyGatsby, this.staticSiteConfig.newPath)) + case 'gatsby': + return format( + this.configskeleton, + format(this.pathPropertyGatsby, this.staticSiteConfig.newPath) + ) break default: - throw "Unknown config type" + throw 'Unknown config type' } } generateConfigProperty() { switch (this.staticSiteConfig.type) { - case "nuxt": + case 'nuxt': return format(this.pathPropertyNuxt, this.staticSiteConfig.newPath) break - case "next": + case 'next': return format(this.pathPropertyNext, this.staticSiteConfig.newPath) break - case "gatsby": + case 'gatsby': return format(this.pathPropertyGatsby, this.staticSiteConfig.newPath) break default: - throw "Unknown config type" + throw 'Unknown config type' } } parse() { core.info(`original configuration:\n${this.config}`) - const ast = espree.parse(this.config, espreeOptions); + const ast = espree.parse(this.config, espreeOptions) // Find the default export declaration node var exportNode = ast.body.find(node => node.type === 'ExpressionStatement') if (exportNode) { var property = this.getPropertyModuleExport(exportNode) - } else { - exportNode = ast.body.find(node => node.type === 'ExportDefaultDeclaration') - if (!exportNode) throw "Unable to find default export" + exportNode = ast.body.find( + node => node.type === 'ExportDefaultDeclaration' + ) + if (!exportNode) throw 'Unable to find default export' var property = this.getPropertyExportDefault(exportNode) } if (property) { switch (this.staticSiteConfig.type) { - case "nuxt": + case 'nuxt': this.parseNuxt(property) break - case "next": - case "gatsby": + case 'next': + case 'gatsby': this.parseNextGatsby(property) break default: - throw "Unknown config type" + throw 'Unknown config type' } } core.info(`parsed configuration:\n${this.config}`) @@ -98,18 +110,34 @@ class ConfigParser { getPropertyModuleExport(exportNode) { var propertyNode = exportNode.expression.right.properties.find( - node => node.key.type === 'Identifier' && node.key.name === this.staticSiteConfig.pathName + node => + node.key.type === 'Identifier' && + node.key.name === this.staticSiteConfig.pathName ) if (!propertyNode) { - - core.info("Unable to find property, insert it : " + this.staticSiteConfig.pathName) + core.info( + 'Unable to find property, insert it : ' + + this.staticSiteConfig.pathName + ) if (exportNode.expression.right.properties.length > 0) { - this.config = this.config.slice(0, exportNode.expression.right.properties[0].range[0]) + this.generateConfigProperty() + ',\n' + this.config.slice(exportNode.expression.right.properties[0].range[0]) - core.info("new config = \n" + this.config) + this.config = + this.config.slice( + 0, + exportNode.expression.right.properties[0].range[0] + ) + + this.generateConfigProperty() + + ',\n' + + this.config.slice(exportNode.expression.right.properties[0].range[0]) + core.info('new config = \n' + this.config) } else { - this.config = this.config.slice(0, exportNode.expression.right.range[0] + 1) + '\n ' + this.generateConfigProperty() + '\n' + this.config.slice(exportNode.expression.right.range[1] - 1) - core.info("new config = \n" + this.config) + this.config = + this.config.slice(0, exportNode.expression.right.range[0] + 1) + + '\n ' + + this.generateConfigProperty() + + '\n' + + this.config.slice(exportNode.expression.right.range[1] - 1) + core.info('new config = \n' + this.config) } } return propertyNode @@ -117,18 +145,30 @@ class ConfigParser { getPropertyExportDefault(exportNode) { var propertyNode = exportNode.declaration.properties.find( - node => node.key.type === 'Identifier' && node.key.name === this.staticSiteConfig.pathName + node => + node.key.type === 'Identifier' && + node.key.name === this.staticSiteConfig.pathName ) if (!propertyNode) { - - core.info("Unable to find property, insert it " + this.staticSiteConfig.pathName) + core.info( + 'Unable to find property, insert it ' + this.staticSiteConfig.pathName + ) if (exportNode.declaration.properties.length > 0) { - this.config = this.config.slice(0, exportNode.declaration.properties[0].range[0]) + this.generateConfigProperty() + ',\n' + this.config.slice(exportNode.declaration.properties[0].range[0]) - core.info("new config = \n" + this.config) + this.config = + this.config.slice(0, exportNode.declaration.properties[0].range[0]) + + this.generateConfigProperty() + + ',\n' + + this.config.slice(exportNode.declaration.properties[0].range[0]) + core.info('new config = \n' + this.config) } else { - this.config = this.config.slice(0, exportNode.declaration.range[0] + 1) + '\n ' + this.generateConfigProperty() + '\n' + this.config.slice(exportNode.declaration.range[1] - 1) - core.info("new config = \n" + this.config) + this.config = + this.config.slice(0, exportNode.declaration.range[0] + 1) + + '\n ' + + this.generateConfigProperty() + + '\n' + + this.config.slice(exportNode.declaration.range[1] - 1) + core.info('new config = \n' + this.config) } } @@ -138,19 +178,29 @@ class ConfigParser { parseNuxt(propertyNode) { // Find the base node if (propertyNode && propertyNode.value.type === 'ObjectExpression') { - var baseNode = propertyNode.value.properties.find(node => node.key.type === 'Identifier' && node.key.name === this.staticSiteConfig.subPathName)//'base') + var baseNode = propertyNode.value.properties.find( + node => + node.key.type === 'Identifier' && + node.key.name === this.staticSiteConfig.subPathName + ) //'base') if (baseNode) { // Swap the base value by a hardcoded string and print it - this.config = this.config.slice(0, baseNode.value.range[0]) + `'${this.staticSiteConfig.newPath}'` + this.config.slice(baseNode.value.range[1]) + this.config = + this.config.slice(0, baseNode.value.range[0]) + + `'${this.staticSiteConfig.newPath}'` + + this.config.slice(baseNode.value.range[1]) } } } parseNextGatsby(pathNode) { if (pathNode) { - this.config = this.config.slice(0, pathNode.value.range[0]) + `'${this.staticSiteConfig.newPath}'` + this.config.slice(pathNode.value.range[1]) + this.config = + this.config.slice(0, pathNode.value.range[0]) + + `'${this.staticSiteConfig.newPath}'` + + this.config.slice(pathNode.value.range[1]) } } } -module.exports = {ConfigParser} \ No newline at end of file +module.exports = {ConfigParser} diff --git a/src/config-parser.test.js b/src/config-parser.test.js index d71aae3..6000e5b 100644 --- a/src/config-parser.test.js +++ b/src/config-parser.test.js @@ -1,83 +1,104 @@ -const { ConfigParser } = require('./config-parser') -const fs = require("fs") +const {ConfigParser} = require('./config-parser') +const fs = require('fs') const assert = require('assert') const srcFolder = `${process.cwd()}/src/fixtures` const tmpFolder = `${process.cwd()}/src/fixtures/tmp` const expectedFolder = `${process.cwd()}/src/fixtures/expected` -const repoPath = "/amazing-new-repo/" +const repoPath = '/amazing-new-repo/' const cases = [ - ["next.config.js", { - filePath: `${tmpFolder}/next.config.js`, - type: "next", - pathName: "basePath", - newPath: repoPath - }], - ["next.config.old.js", { - filePath: `${tmpFolder}/next.config.old.js`, - type: "next", - pathName: "basePath", - newPath: repoPath - }], - ["next.config.old.missing.js", { - filePath: `${tmpFolder}/next.config.old.missing.js`, - type: "next", - pathName: "basePath", - newPath: repoPath - }], - ["gatsby-config.js", { - filePath: `${tmpFolder}/gatsby-config.js`, - type: "gatsby", - pathName: "pathPrefix", - newPath: repoPath - }], - ["gatsby-config.old.js", { - filePath: `${tmpFolder}/gatsby-config.old.js`, - type: "gatsby", - pathName: "pathPrefix", - newPath: repoPath - }], - ["nuxt.config.js", { - filePath:`${tmpFolder}/nuxt.config.js`, - type: "nuxt", - pathName: "router", - subPathName: "base", - newPath: repoPath - }], - ["nuxt.config.missing.js", { - filePath:`${tmpFolder}/nuxt.config.missing.js`, - type: "nuxt", - pathName: "router", - subPathName: "base", - newPath: repoPath - }], - ["nuxt.config.old.js", { - filePath:`${tmpFolder}/nuxt.config.old.js`, - type: "nuxt", - pathName: "router", - subPathName: "base", - newPath: repoPath - }], -]; + [ + 'next.config.js', + { + filePath: `${tmpFolder}/next.config.js`, + type: 'next', + pathName: 'basePath', + newPath: repoPath + } + ], + [ + 'next.config.old.js', + { + filePath: `${tmpFolder}/next.config.old.js`, + type: 'next', + pathName: 'basePath', + newPath: repoPath + } + ], + [ + 'next.config.old.missing.js', + { + filePath: `${tmpFolder}/next.config.old.missing.js`, + type: 'next', + pathName: 'basePath', + newPath: repoPath + } + ], + [ + 'gatsby-config.js', + { + filePath: `${tmpFolder}/gatsby-config.js`, + type: 'gatsby', + pathName: 'pathPrefix', + newPath: repoPath + } + ], + [ + 'gatsby-config.old.js', + { + filePath: `${tmpFolder}/gatsby-config.old.js`, + type: 'gatsby', + pathName: 'pathPrefix', + newPath: repoPath + } + ], + [ + 'nuxt.config.js', + { + filePath: `${tmpFolder}/nuxt.config.js`, + type: 'nuxt', + pathName: 'router', + subPathName: 'base', + newPath: repoPath + } + ], + [ + 'nuxt.config.missing.js', + { + filePath: `${tmpFolder}/nuxt.config.missing.js`, + type: 'nuxt', + pathName: 'router', + subPathName: 'base', + newPath: repoPath + } + ], + [ + 'nuxt.config.old.js', + { + filePath: `${tmpFolder}/nuxt.config.old.js`, + type: 'nuxt', + pathName: 'router', + subPathName: 'base', + newPath: repoPath + } + ] +] describe('configParser', () => { - test.each(cases)( - "%p parsed correctly", - (fileName, configuration) => { - srcFileName = `${srcFolder}/${fileName}` - tmpFileName = `${tmpFolder}/${fileName}` - expectedFileName = `${expectedFolder}/${fileName}` - fs.mkdirSync(tmpFolder, {recursive: true}) - fs.copyFileSync(srcFileName, tmpFileName) - const parser = new ConfigParser(configuration) - parser.parse() + test.each(cases)('%p parsed correctly', (fileName, configuration) => { + srcFileName = `${srcFolder}/${fileName}` + tmpFileName = `${tmpFolder}/${fileName}` + expectedFileName = `${expectedFolder}/${fileName}` + fs.mkdirSync(tmpFolder, {recursive: true}) + fs.copyFileSync(srcFileName, tmpFileName) + const parser = new ConfigParser(configuration) + parser.parse() - var expectedContent = fs.readFileSync(expectedFileName).toString() - var actualContent = fs.readFileSync(tmpFileName).toString() - assert.equal(actualContent, expectedContent) - fs.rmSync(tmpFileName) - } - ) + var expectedContent = fs.readFileSync(expectedFileName).toString() + var actualContent = fs.readFileSync(tmpFileName).toString() + assert.equal(actualContent, expectedContent) + fs.rmSync(tmpFileName) + }) }) diff --git a/src/enable-pages.js b/src/enable-pages.js index 15d9c3c..68f47e3 100644 --- a/src/enable-pages.js +++ b/src/enable-pages.js @@ -1,19 +1,19 @@ const core = require('@actions/core') const axios = require('axios') -async function enablePages({ repositoryNwo, githubToken }) { +async function enablePages({repositoryNwo, githubToken}) { const pagesEndpoint = `https://api.github.com/repos/${repositoryNwo}/pages` try { const response = await axios.post( pagesEndpoint, - { build_type: 'workflow' }, + {build_type: 'workflow'}, { headers: { Accept: 'application/vnd.github.v3+json', Authorization: `Bearer ${githubToken}`, - 'Content-type': 'application/json', - }, + 'Content-type': 'application/json' + } } ) core.info('Created pages site') @@ -23,7 +23,7 @@ async function enablePages({ repositoryNwo, githubToken }) { return } - core.error('Couldn\'t create pages site', error) + core.error("Couldn't create pages site", error) throw error } } diff --git a/src/enable-pages.test.js b/src/enable-pages.test.js index 6138e87..359f552 100644 --- a/src/enable-pages.test.js +++ b/src/enable-pages.test.js @@ -18,29 +18,36 @@ describe('enablePages', () => { }) it('makes a request to create a page', async () => { - jest - .spyOn(axios, 'post') - .mockImplementationOnce(() => Promise.resolve({ })) + jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.resolve({})) - await enablePages({ repositoryNwo: GITHUB_REPOSITORY, githubToken: GITHUB_TOKEN }) + await enablePages({ + repositoryNwo: GITHUB_REPOSITORY, + githubToken: GITHUB_TOKEN + }) }) it('handles a 409 response when the page already exists', async () => { jest .spyOn(axios, 'post') - .mockImplementationOnce(() => Promise.reject({ response: { status: 409 } })) + .mockImplementationOnce(() => Promise.reject({response: {status: 409}})) // Simply assert that no error is raised - await enablePages({ repositoryNwo: GITHUB_REPOSITORY, githubToken: GITHUB_TOKEN }) + await enablePages({ + repositoryNwo: GITHUB_REPOSITORY, + githubToken: GITHUB_TOKEN + }) }) it('re-raises errors on failure status codes', async () => { jest .spyOn(axios, 'post') - .mockImplementationOnce(() => Promise.reject({ response: { status: 404 } })) + .mockImplementationOnce(() => Promise.reject({response: {status: 404}})) try { - await enablePages({ repositoryNwo: GITHUB_REPOSITORY, githubToken: GITHUB_TOKEN }) + await enablePages({ + repositoryNwo: GITHUB_REPOSITORY, + githubToken: GITHUB_TOKEN + }) } catch (error) { expect(error.response.status).toEqual(404) } diff --git a/src/get-pages-base-url.js b/src/get-pages-base-url.js index 61f5b9e..730d558 100644 --- a/src/get-pages-base-url.js +++ b/src/get-pages-base-url.js @@ -2,26 +2,27 @@ const core = require('@actions/core') const axios = require('axios') const setPagesPath = require('./set-pages-path') -async function getPagesBaseUrl({ repositoryNwo, githubToken, staticSiteGenerator}) { +async function getPagesBaseUrl({ + repositoryNwo, + githubToken, + staticSiteGenerator +}) { try { const pagesEndpoint = `https://api.github.com/repos/${repositoryNwo}/pages` core.info(`Get the Base URL to the page with endpoint ${pagesEndpoint}`) - const response = await axios.get( - pagesEndpoint, - { - headers: { - Accept: 'application/vnd.github.v3+json', - Authorization: `Bearer ${githubToken}` - } + const response = await axios.get(pagesEndpoint, { + headers: { + Accept: 'application/vnd.github.v3+json', + Authorization: `Bearer ${githubToken}` } - ) + }) pageObject = response.data core.info(JSON.stringify(pageObject)) const siteUrl = new URL(pageObject.html_url) - if ( staticSiteGenerator ) { + if (staticSiteGenerator) { setPagesPath({staticSiteGenerator, path: siteUrl.pathname}) } core.setOutput('base_url', siteUrl.href) diff --git a/src/get-pages-base-url.test.js b/src/get-pages-base-url.test.js index a8ec246..eebc8e4 100644 --- a/src/get-pages-base-url.test.js +++ b/src/get-pages-base-url.test.js @@ -11,7 +11,9 @@ describe('getPagesBaseUrl', () => { beforeEach(() => { jest.restoreAllMocks() - jest.spyOn(core, 'setOutput').mockImplementation((key, value) => { key, value }) + jest.spyOn(core, 'setOutput').mockImplementation((key, value) => { + key, value + }) jest.spyOn(core, 'setFailed').mockImplementation(param => param) // Mock error/warning/info/debug @@ -26,12 +28,20 @@ describe('getPagesBaseUrl', () => { jest .spyOn(axios, 'get') - .mockImplementationOnce(() => Promise.resolve({ data: { html_url: baseUrl } })) + .mockImplementationOnce(() => + Promise.resolve({data: {html_url: baseUrl}}) + ) - await getPagesBaseUrl({ repositoryNwo: GITHUB_REPOSITORY, githubToken: GITHUB_TOKEN }) + await getPagesBaseUrl({ + repositoryNwo: GITHUB_REPOSITORY, + githubToken: GITHUB_TOKEN + }) expect(core.setOutput).toHaveBeenCalledWith('base_url', baseUrl) - expect(core.setOutput).toHaveBeenCalledWith('origin', 'https://octocat.github.io') + expect(core.setOutput).toHaveBeenCalledWith( + 'origin', + 'https://octocat.github.io' + ) expect(core.setOutput).toHaveBeenCalledWith('host', 'octocat.github.io') expect(core.setOutput).toHaveBeenCalledWith('base_path', '/') }) @@ -41,12 +51,20 @@ describe('getPagesBaseUrl', () => { jest .spyOn(axios, 'get') - .mockImplementationOnce(() => Promise.resolve({ data: { html_url: baseUrl } })) + .mockImplementationOnce(() => + Promise.resolve({data: {html_url: baseUrl}}) + ) - await getPagesBaseUrl({ repositoryNwo: GITHUB_REPOSITORY, githubToken: GITHUB_TOKEN }) + await getPagesBaseUrl({ + repositoryNwo: GITHUB_REPOSITORY, + githubToken: GITHUB_TOKEN + }) expect(core.setOutput).toHaveBeenCalledWith('base_url', baseUrl) - expect(core.setOutput).toHaveBeenCalledWith('origin', 'https://octocat.github.io') + expect(core.setOutput).toHaveBeenCalledWith( + 'origin', + 'https://octocat.github.io' + ) expect(core.setOutput).toHaveBeenCalledWith('host', 'octocat.github.io') expect(core.setOutput).toHaveBeenCalledWith('base_path', '/my-repo/') }) @@ -56,12 +74,20 @@ describe('getPagesBaseUrl', () => { jest .spyOn(axios, 'get') - .mockImplementationOnce(() => Promise.resolve({ data: { html_url: baseUrl } })) + .mockImplementationOnce(() => + Promise.resolve({data: {html_url: baseUrl}}) + ) - await getPagesBaseUrl({ repositoryNwo: GITHUB_REPOSITORY, githubToken: GITHUB_TOKEN }) + await getPagesBaseUrl({ + repositoryNwo: GITHUB_REPOSITORY, + githubToken: GITHUB_TOKEN + }) expect(core.setOutput).toHaveBeenCalledWith('base_url', baseUrl) - expect(core.setOutput).toHaveBeenCalledWith('origin', 'https://www.example.com') + expect(core.setOutput).toHaveBeenCalledWith( + 'origin', + 'https://www.example.com' + ) expect(core.setOutput).toHaveBeenCalledWith('host', 'www.example.com') expect(core.setOutput).toHaveBeenCalledWith('base_path', '/') }) diff --git a/src/index.js b/src/index.js index 420e4d7..bf65557 100644 --- a/src/index.js +++ b/src/index.js @@ -17,6 +17,5 @@ async function main() { } } - // Main main() diff --git a/src/set-pages-path.js b/src/set-pages-path.js index 4e10e1f..8a159a6 100644 --- a/src/set-pages-path.js +++ b/src/set-pages-path.js @@ -1,45 +1,46 @@ const core = require('@actions/core') const axios = require('axios') -const { ConfigParser } = require('./config-parser') +const {ConfigParser} = require('./config-parser') async function setPagesPath({staticSiteGenerator, path}) { try { - switch(staticSiteGenerator) - { + switch (staticSiteGenerator) { case 'nuxt': var ssConfig = { - filePath:"./nuxt.config.js", - type: "nuxt", - pathName: "router", - subPathName: "base", + filePath: './nuxt.config.js', + type: 'nuxt', + pathName: 'router', + subPathName: 'base', newPath: path } - break; + break case 'next': var ssConfig = { - filePath:"./next.config.js", - type: "next", - pathName: "basePath", + filePath: './next.config.js', + type: 'next', + pathName: 'basePath', newPath: path } - break; + break case 'gatsby': var ssConfig = { - filePath: "./gatsby-config.js", - type: "gatsby", - pathName: "pathPrefix", + filePath: './gatsby-config.js', + type: 'gatsby', + pathName: 'pathPrefix', newPath: path } - break; + break default: - throw "Unknown config type" + throw 'Unknown config type' } let configParser = new ConfigParser(ssConfig) configParser.parse() - } catch (error) { - core.warning(`We were unable to determine how to inject the site metadata into your config. Generated URLs may be incorrect. The base URL for this site should be ${path}. Please ensure your framework is configured to generate relative links appropriately.`, error) + core.warning( + `We were unable to determine how to inject the site metadata into your config. Generated URLs may be incorrect. The base URL for this site should be ${path}. Please ensure your framework is configured to generate relative links appropriately.`, + error + ) } }