171 Commits

Author SHA1 Message Date
James M. Greene
37538b280c Merge pull request #56 from actions/dependabot/npm_and_yarn/axios-1.3.0
Bump axios from 0.27.2 to 1.3.0
2023-02-01 11:22:00 -06:00
James M. Greene
8d642d8eae Update distributables 2023-02-01 11:21:15 -06:00
dependabot[bot]
9b8d2f4ab2 Bump axios from 0.27.2 to 1.3.0
Bumps [axios](https://github.com/axios/axios) from 0.27.2 to 1.3.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.27.2...v1.3.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-01 17:19:53 +00:00
James M. Greene
e2f34b1f92 Merge pull request #58 from actions/dependabot/npm_and_yarn/jest-29.4.1
Bump jest from 28.1.1 to 29.4.1
2023-02-01 11:19:26 -06:00
dependabot[bot]
7aebbf763e Bump jest from 28.1.1 to 29.4.1
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 28.1.1 to 29.4.1.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.4.1/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-01 17:18:41 +00:00
James M. Greene
6a2b91eafe Merge pull request #57 from actions/dependabot/npm_and_yarn/eslint-plugin-github-4.6.0
Bump eslint-plugin-github from 4.3.7 to 4.6.0
2023-02-01 11:17:49 -06:00
dependabot[bot]
939d05ad85 Bump eslint-plugin-github from 4.3.7 to 4.6.0
Bumps [eslint-plugin-github](https://github.com/github/eslint-plugin-github) from 4.3.7 to 4.6.0.
- [Release notes](https://github.com/github/eslint-plugin-github/releases)
- [Commits](https://github.com/github/eslint-plugin-github/compare/v4.3.7...v4.6.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-github
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-01 17:16:27 +00:00
James M. Greene
0ca1df54d4 Merge pull request #55 from actions/dependabot/npm_and_yarn/eslint-config-prettier-8.6.0
Bump eslint-config-prettier from 8.5.0 to 8.6.0
2023-02-01 11:15:11 -06:00
dependabot[bot]
5c42783e5b Bump eslint-config-prettier from 8.5.0 to 8.6.0
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 8.5.0 to 8.6.0.
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v8.5.0...v8.6.0)

---
updated-dependencies:
- dependency-name: eslint-config-prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-01 17:14:28 +00:00
James M. Greene
13d4de8a28 Merge pull request #54 from actions/dependabot/npm_and_yarn/eslint-8.33.0
Bump eslint from 8.23.1 to 8.33.0
2023-02-01 11:08:42 -06:00
James M. Greene
5aa8bf5ac6 Merge branch 'main' into dependabot/npm_and_yarn/eslint-8.33.0 2023-02-01 11:08:09 -06:00
James M. Greene
1d79de2fe7 Merge pull request #53 from actions/test-set-pages-config
Update tests to actually invoke the desired method instead of replicating it
2023-02-01 11:00:46 -06:00
dependabot[bot]
5a80553d12 Bump eslint from 8.23.1 to 8.33.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.23.1 to 8.33.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.23.1...v8.33.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-01 17:00:40 +00:00
James M. Greene
7eb7a15548 Merge branch 'main' into test-set-pages-config 2023-02-01 11:00:11 -06:00
James M. Greene
b8c94fdc9e Merge pull request #52 from actions/dependabot-npm-updates
Add npm to Dependabot update list
2023-02-01 10:59:58 -06:00
James M. Greene
9b358e73bb Update tests to actually invoke the desired method instead of replicating it 2023-01-30 23:51:40 -06:00
James M. Greene
13e6bc7a20 Add npm to Dependabot update list 2023-01-30 22:11:54 -06:00
James M. Greene
3c444c051b Merge pull request #50 from actions/fix-enablement
Fix `enablement` logic in v3
2023-01-30 12:34:00 -06:00
James M. Greene
12fd9a085c Update distributables 2023-01-30 12:29:45 -06:00
James M. Greene
a8216d627c Fix enablement logic for v3 2023-01-30 12:29:09 -06:00
James M. Greene
5992ce8fd5 Merge pull request #48 from actions/do-not-enable-by-default
Update default behavior to NOT attempt to create/enable the Pages site
2023-01-18 15:13:37 -06:00
James M. Greene
c8deda3832 Update distributables 2023-01-18 15:03:42 -06:00
James M. Greene
5d8963e8a5 Update default behavior to NOT attempt to create/enable the Pages site 2023-01-18 15:03:22 -06:00
James M. Greene
529ba710d5 Merge pull request #47 from actions/dependabot/github_actions/actions/publish-action-0.2.2
Bump actions/publish-action from 0.2.1 to 0.2.2
2023-01-18 14:56:58 -06:00
dependabot[bot]
29e9dd5abe Bump actions/publish-action from 0.2.1 to 0.2.2
Bumps [actions/publish-action](https://github.com/actions/publish-action) from 0.2.1 to 0.2.2.
- [Release notes](https://github.com/actions/publish-action/releases)
- [Commits](https://github.com/actions/publish-action/compare/v0.2.1...v0.2.2)

---
updated-dependencies:
- dependency-name: actions/publish-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-18 20:56:23 +00:00
James M. Greene
c450a282d7 Merge pull request #45 from actions/dependabot/npm_and_yarn/json5-1.0.2
Bump json5 from 1.0.1 to 1.0.2
2023-01-18 14:55:38 -06:00
dependabot[bot]
6567d4c154 Bump json5 from 1.0.1 to 1.0.2
Bumps [json5](https://github.com/json5/json5) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-18 20:53:57 +00:00
James M. Greene
aba1aa6bab Merge pull request #46 from actions/dependabot-config
Add Dependabot config for Actions usage updates
2023-01-13 16:37:40 -06:00
James M. Greene
6a80311a73 Comply with Prettier expectations 2023-01-13 16:34:06 -06:00
James M. Greene
380c12d4cc Add Dependabot config for Actions usage updates 2023-01-13 15:59:46 -06:00
James M. Greene
c5a3e1159e Merge pull request #43 from actions/warn-unsupported-exts
Warn about unsupported file extensions after erring
2022-11-23 09:32:16 -06:00
James M. Greene
a069fede0c Update distributables after updating deps 2022-11-22 23:17:34 -06:00
James M. Greene
2f460cfbe0 Update distributables 2022-11-22 23:11:12 -06:00
James M. Greene
e5c1ee9f14 Reformat 2022-11-22 23:10:56 -06:00
James M. Greene
7fea7010df Minor revisions 2022-11-22 23:10:56 -06:00
James M. Greene
34521f23a5 Add warn for unsupported extensions 2022-11-22 23:10:37 -06:00
James M. Greene
d84b27279d Merge pull request #42 from actions/JamesMGreene-patch-1
Update to the latest `actions/publish-action`
2022-11-22 22:29:53 -06:00
James M. Greene
5650def507 Update to the latest actions/publish-action
To avoid Actions core deprecation messages.

https://github.com/actions/publish-action/releases/tag/v0.2.1
2022-11-22 22:29:07 -06:00
James M. Greene
0c2178e929 Merge pull request #41 from actions/alt-blank-extensions
Test: Better support alternative file extensions for blank config files
2022-11-22 21:35:02 -06:00
James M. Greene
948e60fb96 Reformat 2022-11-22 21:34:10 -06:00
James M. Greene
1305a1ba92 Better support alternative file extensions for blank config files in the tests 2022-11-22 21:30:53 -06:00
James M. Greene
b94e9adb36 Merge pull request #38 from actions/support-wrapped-exports
Support wrapped exports
2022-11-21 16:57:31 -06:00
James M. Greene
fc8c2c4e6e Update the distributables 2022-11-21 13:12:55 -06:00
James M. Greene
e978eba337 Add support for indirect config declarator in chained declaration statement 2022-11-21 13:12:45 -06:00
James M. Greene
343cb08233 Add tests for when multiple declarations are chained together 2022-11-21 12:36:09 -06:00
James M. Greene
f87a94c875 Update the distributables 2022-11-21 12:15:34 -06:00
James M. Greene
7eb40247a7 Format 2022-11-21 12:14:59 -06:00
James M. Greene
86f141f32d Add support for 'Indirect module export with a wrapping call at the export' 2022-11-21 12:12:47 -06:00
James M. Greene
76b6a8292e Small corrections 2022-11-21 12:08:39 -06:00
James M. Greene
8e221f24db Add support for 'Indirect module export with a wrapping call at the definition' 2022-11-21 12:05:26 -06:00
James M. Greene
d897860efd Add support for 'Indirect default export with a wrapping call at the export' 2022-11-21 11:34:58 -06:00
James M. Greene
24270f0cca Add support for 'Indirect default export with a wrapping call at the definition' 2022-11-21 11:04:42 -06:00
James M. Greene
0c3c14948a Merge branch 'main' into support-wrapped-exports 2022-11-18 01:02:58 -06:00
James M. Greene
b0c19d0de9 Merge pull request #37 from actions/merge-pr-33
Merge PR #33
2022-11-18 01:01:12 -06:00
James M. Greene
51323db177 Fix the Next.js tests 2022-11-18 00:57:58 -06:00
James M. Greene
3d9811d6e2 Update distributables 2022-11-18 00:56:40 -06:00
James M. Greene
9c3b6344a2 Merge branch 'main' into patch-1 2022-11-18 00:50:11 -06:00
James M. Greene
97fb35057c Add comment 2022-11-18 00:50:00 -06:00
James M. Greene
c917d1c3cd Merge pull request #35 from actions/bump-actions
Bump actions
2022-11-18 00:46:30 -06:00
James M. Greene
ffa824f004 Start making some of those tests pass 2022-11-18 00:45:01 -06:00
James M. Greene
d4a76d1ee1 Add unit tests to verify support for function-wrapped exports 2022-11-18 00:29:31 -06:00
Yoann Chaudet
bd8a5da49f Bump actions 2022-10-31 16:34:08 -07:00
Kapil Koju
5cb77813a2 Add back experimental.images.unoptimized for old NextJS 2022-10-24 23:46:06 -04:00
Kapil Koju
2094727a1b Fix nextjs images.unoptimized config path name
`images.unoptimized` is no longer in `experimental` and is stable with NextJS `v12.3.0`.
https://nextjs.org/docs/api-reference/next/image#unoptimized
2022-10-24 23:09:43 -04:00
Mingzi
d875fa8dc1 Merge pull request #31 from rentziass/rentziass/update-actions-core
Update @actions/core to 1.10.0
2022-10-06 09:56:39 -07:00
Francesco Renzi
67f329fcfd Update @actions/core to 1.10.0 2022-10-06 11:08:55 +01:00
James M. Greene
2ce6d5eaa1 Merge pull request #27 from actions/fix-readme-links
Fix non-Code links in README
2022-09-26 12:01:36 -05:00
James M. Greene
bb6976f8d1 Merge branch 'main' into fix-readme-links 2022-09-26 11:00:10 -05:00
James M. Greene
f2098a32c3 Merge pull request #26 from actions/unused-deps
Clean up some unused dependencies
2022-09-26 10:59:55 -05:00
James M. Greene
7fa35a05fd Merge branch 'main' into unused-deps 2022-09-26 10:58:37 -05:00
James M. Greene
c3113876b0 Merge pull request #25 from actions/eslint-roller
Add ESLint
2022-09-26 10:52:23 -05:00
James M. Greene
af5f3c3f72 Merge branch 'main' into eslint-roller 2022-09-21 16:18:10 -05:00
James M. Greene
ad83b485e7 Merge pull request #24 from actions/i-feel-pretty
Expand Prettier usage
2022-09-21 16:17:21 -05:00
James M. Greene
a84400a87f Fix non-Code links in README 2022-09-19 10:50:02 -05:00
James M. Greene
7a0a617c8a Remove unused dependencies 2022-09-16 23:20:01 -05:00
James M. Greene
062df390be Make ESLint fail hard on semi-colon usage 2022-09-16 23:00:18 -05:00
James M. Greene
7619de7040 Simplify ESLint ignore pattern 2022-09-16 22:55:06 -05:00
James M. Greene
66e9ac3c2e Add an 'all' script and simplify 'prepare' 2022-09-16 22:54:24 -05:00
James M. Greene
4012a9fa87 Correct Actions input parameter name 2022-09-16 22:43:42 -05:00
James M. Greene
4a12ff50fb Update distributables 2022-09-16 22:41:27 -05:00
James M. Greene
a07391ec25 Don't lint during prepare 2022-09-16 22:03:34 -05:00
James M. Greene
2491ca8488 Reformat ESLint config 2022-09-16 22:03:15 -05:00
James M. Greene
875ec87ff9 Remove stray line break 2022-09-16 22:01:13 -05:00
James M. Greene
4eadc891b5 Add Actions workflow to verify lint status 2022-09-16 21:57:04 -05:00
James M. Greene
c4feb8d01e Ignore ESLint rule about condition looping condition for now 2022-09-16 21:56:47 -05:00
James M. Greene
1f9ca39237 Fix bad reference in string interpolation
Regression from https://github.com/actions/configure-pages/pull/21
2022-09-16 21:54:58 -05:00
James M. Greene
1cefe6fc7c Remove unnecessary try/catch 2022-09-16 21:50:49 -05:00
James M. Greene
25a1ec8799 Add eslint configuration and scripts 2022-09-16 21:48:52 -05:00
James M. Greene
b9c4ac6c14 Minor workflow improvements 2022-09-16 20:48:19 -05:00
James M. Greene
6e4f93b15d Add eslint dependency and plugins 2022-09-16 20:47:23 -05:00
James M. Greene
069c984c5e Let Prettier reformat all of the things 2022-09-16 20:37:18 -05:00
James M. Greene
b030b061cb Allow prettier to check more files that it's capable of handling 2022-09-16 20:35:47 -05:00
James M. Greene
45efe60937 Apply consistent spacing and use of single quotes 2022-09-11 10:23:22 -05:00
James M. Greene
35c001ded6 Dereference as 'path'
This minimizes the changes to the codebase, as well as slightly clarifying that its value may not remain the same as the 'pathname'
2022-09-11 10:23:22 -05:00
James M. Greene
27457957e6 Merge pull request #21 from AndrewLester/ssg-origin
Use GitHub Pages site origin for setting up SSG configs
2022-09-11 10:21:18 -05:00
AndrewLester
7ec0edaa8e Fix prepare output 2022-08-19 15:10:01 -05:00
AndrewLester
d48340abcd Use GitHub Pages site origin for setting up SSG configs 2022-08-19 14:33:39 -05:00
James M. Greene
f53b57ff56 Merge pull request #20 from actions/update-major-on-full-releases
Update major version only on full releases
2022-08-19 13:21:44 -05:00
James M. Greene
6d1d650751 Update major version only on full releases 2022-08-19 12:44:16 -05:00
James M. Greene
61fd3a3cc1 Merge pull request #19 from actions/no-trailing-slashes
[BREAKING] Remove the trailing slash from `base_url` and `base_path` outputs
2022-08-19 09:27:06 -05:00
James M. Greene
0ec542a837 Update distributables 2022-08-18 18:08:52 -05:00
James M. Greene
3a90973fd3 Use local module for removing trailing slash to reduce duplication 2022-08-18 18:08:30 -05:00
James M. Greene
dc5b850bfd breaking: Remove trailing slash from base_url and base_path outputs 2022-08-18 18:08:30 -05:00
James M. Greene
9a141972ca Merge pull request #18 from actions/dependabot/npm_and_yarn/actions/core-1.9.1
Bump @actions/core from 1.8.2 to 1.9.1
2022-08-18 18:06:10 -05:00
James M. Greene
7d9bb68583 Update distributables 2022-08-18 18:04:58 -05:00
dependabot[bot]
ec022f4ae9 Bump @actions/core from 1.8.2 to 1.9.1
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.8.2 to 1.9.1.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

---
updated-dependencies:
- dependency-name: "@actions/core"
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-18 19:59:15 +00:00
James M. Greene
f71d3d08f0 Merge pull request #16 from AndrewLester/ssg-sveltekit
Add SvelteKit as an option for static_site_generator setting
2022-08-17 14:42:52 -05:00
James M. Greene
9ff7f29195 Update dist map 2022-08-17 14:41:47 -05:00
James M. Greene
9b7553ef7f Change environment variable data type to explicit string 2022-08-17 14:34:23 -05:00
AndrewLester
42451665cc Run prepare script 2022-08-10 16:28:32 -04:00
AndrewLester
adc528a6d8 Export GITHUB_PAGES env variable 2022-08-10 16:28:32 -04:00
AndrewLester
789c331a21 Support new features from #15 2022-08-10 16:28:32 -04:00
AndrewLester
ff1182a56a Add SvelteKit to action yml 2022-08-10 16:28:32 -04:00
AndrewLester
c872edcdfb Update config parser to support export default with identifier and add SvelteKit code
Co-authored-by: NatoBoram <natoboram@users.noreply.github.com>
2022-08-10 16:28:31 -04:00
James M. Greene
c61e34fb27 Merge pull request #12 from actions/better-docs
Improve a few contribution notes in the README
2022-08-10 14:19:56 -05:00
James M. Greene
a220556ffe Merge branch 'main' into better-docs 2022-08-10 14:10:38 -05:00
James M. Greene
491169de17 Revise release procedure 2022-08-10 14:10:15 -05:00
James M. Greene
f19391002a Merge pull request #17 from actions/marketplace-action-rename
Rename to include "GitHub" in "GitHub Pages" for Marketplace
2022-08-10 13:58:37 -05:00
James M. Greene
742be05113 Update action.yml 2022-08-10 12:52:41 -05:00
James M. Greene
90b7c04b80 Merge branch 'main' into better-docs 2022-08-10 10:00:39 -05:00
James M. Greene
15f519fab9 Merge pull request #15 from actions/ssg-config-file-input
Add support for specifying the SSG configuration file path
2022-08-10 09:18:00 -05:00
James M. Greene
f5b4063a62 Update distributables properly 2022-08-10 09:02:07 -05:00
James M. Greene
d06799dbbe Fix typo in dist 2022-08-10 08:57:37 -05:00
James M. Greene
fad78054b6 Fix typo in src 2022-08-10 08:56:12 -05:00
James M. Greene
64fa685553 Rebuild distributables 2022-08-09 11:23:03 -05:00
James M. Greene
891eba7f6e Update src/config-parser.js
Co-authored-by: Yoann Chaudet <yoannchaudet@github.com>
2022-08-09 11:22:14 -05:00
James M. Greene
9f6ed02477 Tweak the title and description in README 2022-08-08 11:15:41 -05:00
James M. Greene
68595d0746 Update distributables 2022-08-05 17:47:09 -05:00
James M. Greene
4f27d51853 Add support for indirect default export declarations 2022-08-05 17:44:40 -05:00
James M. Greene
1395534a78 Hoist important arrays to top-level constants 2022-08-05 17:37:00 -05:00
James M. Greene
7c3932ff89 Add support for specifying the target generator config file 2022-08-05 17:35:23 -05:00
James M. Greene
404d23c4a6 Merge pull request #13 from actions/prettier
Prettier formatting
2022-08-05 17:29:38 -05:00
James M. Greene
06406d74b2 Merge branch 'main' into prettier 2022-08-05 17:28:54 -05:00
James M. Greene
cc95980c79 Merge pull request #14 from actions/workflow-audit
Workflow audit
2022-08-05 17:28:32 -05:00
James M. Greene
4f84ed2a14 Add concurrency settings to PR-based workflows 2022-08-05 15:54:53 -05:00
James M. Greene
f19d25133d Ensure minimal permissions are explicit on all workflows 2022-08-05 15:54:15 -05:00
James M. Greene
f24e879a69 Add concurrency and permissions to workflow 2022-08-05 15:44:58 -05:00
James M. Greene
da85ca493f Update fixtures with Prettier formatting 2022-08-05 15:40:25 -05:00
James M. Greene
d949e1515f Rename Prettier config file extension for consistency 2022-08-05 15:39:17 -05:00
James M. Greene
c69bbc2c2c Fix one expected test fixture given Prettier configuration 2022-08-05 15:35:48 -05:00
James M. Greene
8441c1b1dc Improve a few contribution notes in the README 2022-08-05 15:29:09 -05:00
James M. Greene
4036d0f035 Add a workflow to verify Prettier formatting 2022-08-05 15:28:22 -05:00
James M. Greene
5c1535b807 Update all source files to match expected Prettier formatting 2022-08-05 15:26:05 -05:00
James M. Greene
e22fa7ebed Merge pull request #11 from actions/improve-action-manifest
Improve Actions manifest
2022-08-05 13:40:43 -05:00
James M. Greene
635cafe472 Use single quotes everywhere for consistency in Actions manifest 2022-08-05 13:29:15 -05:00
James M. Greene
7c6340377c Add author to Action manifest 2022-08-05 13:28:40 -05:00
James M. Greene
542786ddbc Improve and shorten description for Marketplace publication 2022-08-05 13:27:44 -05:00
James M. Greene
c4a801b850 Merge pull request #9 from actions/dist-check-workflow
Add workflow to verify distributables are built
2022-08-05 13:10:05 -05:00
James M. Greene
fcc627b194 Merge branch 'main' into dist-check-workflow 2022-08-05 13:09:06 -05:00
James M. Greene
2fc7b604aa Add explicit permissions to workflow 2022-08-05 13:08:52 -05:00
James M. Greene
bcfa2c863c Merge pull request #8 from actions/cleanup-test-workflow
Cleanup formatting of test workflow
2022-08-05 13:07:40 -05:00
James M. Greene
c95cb0d322 Merge pull request #7 from actions/pkg-metadata
Correct a few metadata field values in the `package.json`
2022-08-05 13:07:25 -05:00
James M. Greene
d2f9056bbc Merge pull request #6 from actions/optional-enablement
Make Pages enablement (and write permissions) optional
2022-08-05 13:06:58 -05:00
James M. Greene
b619d6bb2a Make certain the env var isn't present during testing 2022-08-05 12:59:28 -05:00
James M. Greene
1f779755f8 Readd distributables 2022-08-05 12:13:48 -05:00
James M. Greene
bce63914b1 Incorporate the spirit of changes from https://github.com/actions/configure-pages/pull/10 2022-08-05 12:13:23 -05:00
James M. Greene
0a94d4c3bb Merge branch 'main' into optional-enablement 2022-08-05 12:05:17 -05:00
Mingzi
d868d5fe4e Merge pull request #10 from actions/fix-hard-coded-api-endpoint
Fix hardcoded api endpoint
2022-08-05 09:55:37 -07:00
yimysty
d8dd1327a1 fix hardcoded api endpoint 2022-08-05 09:52:17 -07:00
James M. Greene
2a2b0fadb6 Remove diff of 'pre' since this Action doesn't have that directory 2022-08-03 21:47:18 -05:00
James M. Greene
e2ea66d572 Revise comment 2022-08-03 21:46:57 -05:00
James M. Greene
55225928a1 Add workflow to verify distributables are built 2022-08-03 18:30:55 -05:00
James M. Greene
62a7d4f2dc Cleanup formatting of test workflow 2022-08-03 18:30:19 -05:00
James M. Greene
929a1c7425 Correct a few metadata field values in the package.json 2022-08-03 18:24:31 -05:00
James M. Greene
17536ca11a Update organization name in tests 2022-08-03 18:19:57 -05:00
James M. Greene
d801b818b5 Update dist 2022-08-03 18:10:24 -05:00
James M. Greene
fc0fb71264 Delete old modules 2022-08-03 18:10:04 -05:00
James M. Greene
af945d6133 Update index.js to utilize new modules 2022-08-03 18:09:46 -05:00
James M. Greene
b2561d383d Add dedicated Actions-outputs module 2022-08-03 18:09:04 -05:00
James M. Greene
bb42d7b1cb Add new API client to consolidate REST API calls 2022-08-03 18:08:29 -05:00
James M. Greene
0455a16aca Allow a user to manually opt-out of Pages site enablement 2022-08-02 20:45:01 -05:00
72 changed files with 12317 additions and 4964 deletions

17
.eslintrc.json Normal file
View File

@@ -0,0 +1,17 @@
{
"env": {
"commonjs": true,
"es2021": true,
"node": true,
"jest": true
},
"plugins": ["github"],
"extends": ["eslint:recommended", "prettier", "plugin:github/internal"],
"parserOptions": {
"ecmaVersion": 12
},
"rules": {
"semi": ["error", "never"]
},
"ignorePatterns": ["/dist/", "/src/fixtures/", "/src/blank-configurations/"]
}

11
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'weekly'
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: 'weekly'

View File

@@ -1,6 +1,6 @@
---
name-template: "v$RESOLVED_VERSION"
tag-template: "v$RESOLVED_VERSION"
name-template: 'v$RESOLVED_VERSION'
tag-template: 'v$RESOLVED_VERSION'
template: |
# Changelog
@@ -8,33 +8,33 @@ template: |
See details of [all code changes](https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION) since previous release.
categories:
- title: "🚀 Features"
- title: '🚀 Features'
labels:
- "feature"
- "enhancement"
- title: "🐛 Bug Fixes"
- 'feature'
- 'enhancement'
- title: '🐛 Bug Fixes'
labels:
- "fix"
- "bugfix"
- "bug"
- title: "🧰 Maintenance"
- 'fix'
- 'bugfix'
- 'bug'
- title: '🧰 Maintenance'
labels:
- "infrastructure"
- "automation"
- "documentation"
- title: "🏎 Performance"
label: "performance"
change-template: "- $TITLE @$AUTHOR (#$NUMBER)"
- 'infrastructure'
- 'automation'
- 'documentation'
- title: '🏎 Performance'
label: 'performance'
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
version-resolver:
major:
labels:
- "type: breaking"
- 'type: breaking'
minor:
labels:
- "type: enhancement"
- 'type: enhancement'
patch:
labels:
- "type: bug"
- "type: maintenance"
- "type: documentation"
- 'type: bug'
- 'type: maintenance'
- 'type: documentation'
default: patch

52
.github/workflows/check-dist.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
# When you reference this Action with `uses:` in a workflow,
# `dist/index.js` is the code that will run.
# For our project, we generate this file using `ncc`.
# We need to make sure the checked-in `dist/index.js` actually matches what we expect it to be.
name: Check dist/
on:
push:
branches:
- main
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
workflow_dispatch:
permissions:
contents: read
# This allows a subsequently queued workflow run to interrupt previous runs
concurrency:
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
cancel-in-progress: true
jobs:
check-dist:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Rebuild the dist/ directory
run: npm run prepare
- name: Compare the expected and actual dist/ directories
run: |
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
echo "Detected uncommitted changes after build in dist folder. See status below:"
git diff
exit 1
fi

35
.github/workflows/check-formatting.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: Check formatting
on:
push:
branches:
- main
pull_request:
permissions:
contents: read
# This allows a subsequently queued workflow run to interrupt previous runs
concurrency:
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Verify formatting
run: npm run format:check

View File

@@ -4,11 +4,14 @@ on:
branches:
- main
permissions:
contents: write
jobs:
draft-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: release-drafter/release-drafter@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

35
.github/workflows/lint.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: Lint code
on:
push:
branches:
- main
pull_request:
permissions:
contents: read
# This allows a subsequently queued workflow run to interrupt previous runs
concurrency:
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- name: Check out repo
uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: npm
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint:check

View File

@@ -1,11 +1,11 @@
name: Release
on:
release:
types: [published]
types: [released]
workflow_dispatch:
inputs:
TAG_NAME:
description: "Tag name that the major tag will point to"
description: 'Tag name that the major tag will point to'
required: true
env:
@@ -24,7 +24,7 @@ jobs:
steps:
- name: Update the ${{ env.TAG_NAME }} tag
id: update-major-tag
uses: actions/publish-action@v0.1.0
uses: actions/publish-action@v0.2.2
with:
source-tag: ${{ env.TAG_NAME }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}

View File

@@ -6,20 +6,29 @@ on:
- main
pull_request:
permissions:
contents: read
# This allows a subsequently queued workflow run to interrupt previous runs
concurrency:
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Checkout
uses: actions/checkout@v3
- name: Set Node.JS
uses: actions/setup-node@v3
with:
node-version: 16.x
- name: Setup Node.JS
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test

5
.prettierignore Normal file
View File

@@ -0,0 +1,5 @@
# Ignore build artifacts
/dist/
# Ignore all Markdown files
*.md

View File

@@ -1,10 +1,10 @@
# Prettier (formatter) configuration
---
printWidth: 80
printWidth: 120
tabWidth: 2
useTabs: false
semi: false
singleQuote: true
trailingComma: none
bracketSpacing: false
bracketSpacing: true
arrowParens: avoid

View File

@@ -1,8 +1,8 @@
# Configure-Pages
# configure-pages
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][starter-workflows].
A GitHub 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][starter-workflows].
See [`set-pages-path.js`](./src/set-pages-path.js) for more details on how we configure static site generators to work "out of the box" with GitHub Pages.
See [`set-pages-config.js`](src/set-pages-config.js) for more details on how we configure static site generators to work "out of the box" with GitHub Pages.
# Usage
@@ -12,18 +12,13 @@ See [action.yml](action.yml) and the [Pages starter workflows][starter-workflows
In order to release a new version of this Action:
1. Locate the semantic version of the upcoming release (a draft is maintained by the [`draft-release` workflow][draft-release])
1. Locate the semantic version of the [upcoming release][release-list] (a draft is maintained by the [`draft-release` workflow][draft-release]).
2. Push a matching tag, for instance for `v0.1.0`:
2. Publish the draft release from the `main` branch with semantic version as the tag name, _with_ the checkbox to publish to the GitHub Marketplace checked. :ballot_box_with_check:
```bash
git tag v0.1.0
git push origin v0.1.0
```
3. After publishing the release, the [`release` workflow][release] will automatically run to create/update the corresponding the major version tag such as `v0`.
3. Publish the draft release (the major tag such as `v0` will be created/updated by the [`release` workflow][release])
⚠️ Environment approval is required.
⚠️ Environment approval is required. Check the [Release workflow run list][release-workflow-runs].
# License
@@ -31,5 +26,7 @@ The scripts and documentation in this project are released under the [MIT Licens
<!-- references -->
[starter-workflows]: https://github.com/actions/starter-workflows/tree/main/pages
[release-list]: https://github.com/actions/configure-pages/releases
[draft-release]: .github/workflows/draft-release.yml
[release]: .github/workflows/release.yml
[release]: .github/workflows/release.yml
[release-workflow-runs]: https://github.com/actions/configure-pages/actions/workflows/release.yml

View File

@@ -1,22 +1,30 @@
name: "Configure Pages"
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."
name: 'Configure GitHub Pages'
description: 'A GitHub Action to enable Pages, extract various metadata about a site, and configure some supported static site generators.'
author: 'GitHub'
runs:
using: "node16"
main: "dist/index.js"
using: 'node16'
main: 'dist/index.js'
inputs:
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", "gatsby", or "sveltekit"'
required: false
generator_config_file:
description: 'Optional file path to static site generator configuration file'
required: false
token:
description: "GitHub token"
description: 'GitHub token'
default: ${{ github.token }}
required: true
enablement:
description: 'Should a Pages site be enabled for the repository if not so already? This will only work with user-to-server tokens.'
default: 'false'
required: false
outputs:
base_url:
description: 'GitHub Pages site full base URL. Examples: "https://octocat.github.io/my-repo/", "https://octocat.github.io/", "https://www.example.com/"'
description: 'GitHub Pages site full base URL. Examples: "https://octocat.github.io/my-repo", "https://octocat.github.io", "https://www.example.com"'
origin:
description: 'GitHub Pages site origin. Examples: "https://octocat.github.io", "https://www.example.com"'
host:
description: 'GitHub Pages site host. Examples: "octocat.github.io", "www.example.com"'
base_path:
description: 'GitHub Pages site full base path. Examples: "/my-repo/" or "/"'
description: 'GitHub Pages site full base path. Examples: "/my-repo" or ""'

8511
dist/index.js vendored

File diff suppressed because it is too large Load Diff

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

57
dist/licenses.txt vendored
View File

@@ -110,25 +110,13 @@ SOFTWARE.
axios
MIT
Copyright (c) 2014-present Matt Zabriskie
# Copyright (c) 2014-present Matt Zabriskie & Collaborators
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
combined-stream
@@ -572,6 +560,30 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
proxy-from-env
MIT
The MIT License
Copyright (C) 2016-2018 Rob Wu <rob@robwu.nl>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
supports-color
MIT
MIT License
@@ -608,3 +620,16 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
uuid
MIT
The MIT License (MIT)
Copyright (c) 2010-2020 Robert Kieffer and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

8
dist/sveltekit.js vendored Normal file
View File

@@ -0,0 +1,8 @@
// Default Pages configuration for SvelteKit
import adapter from '@sveltejs/adapter-auto'
export default {
kit: {
adapter: adapter()
}
}

6468
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,32 +1,39 @@
{
"private": true,
"name": "configure-pages",
"version": "1.0.0",
"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",
"description": "A GitHub 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": "./dist/index.js",
"scripts": {
"all": "npm run format && npm run lint && npm run prepare && npm run test",
"format": "prettier --write .",
"format:check": "prettier --check .",
"lint": "DEBUG=eslint:cli-engine eslint --fix .",
"lint:check": "DEBUG=eslint:cli-engine eslint .",
"prepare": "ncc build src/index.js -o dist --source-map --license licenses.txt",
"test": "jest"
},
"repository": {
"type": "git",
"url": "git+https://github.com/paper-spa/configure-pages.git"
"url": "git+https://github.com/actions/configure-pages.git"
},
"author": "GitHub",
"license": "MIT",
"bugs": {
"url": "https://github.com/paper-spa/configure-pages/issues"
"url": "https://github.com/actions/configure-pages/issues"
},
"homepage": "https://github.com/paper-spa/configure-pages#readme",
"homepage": "https://github.com/actions/configure-pages#readme",
"dependencies": {
"@actions/core": "^1.8.2",
"axios": "^0.27.2",
"axios-retry": "^3.2.5",
"espree": "^9.3.2",
"string-format": "^1.0.0"
"@actions/core": "^1.10.0",
"axios": "^1.3.0",
"espree": "^9.3.2"
},
"devDependencies": {
"@vercel/ncc": "^0.34.0",
"jest": "^28.1.1",
"eslint": "^8.33.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-github": "^4.6.0",
"jest": "^29.4.1",
"prettier": "^2.7.1"
}
}

87
src/api-client.js Normal file
View File

@@ -0,0 +1,87 @@
const axios = require('axios')
const core = require('@actions/core')
function getApiBaseUrl() {
return process.env.GITHUB_API_URL || 'https://api.github.com'
}
async function enablePagesSite({ repositoryNwo, githubToken }) {
const pagesEndpoint = `${getApiBaseUrl()}/repos/${repositoryNwo}/pages`
try {
const response = await axios.post(
pagesEndpoint,
{ build_type: 'workflow' },
{
headers: {
Accept: 'application/vnd.github.v3+json',
Authorization: `Bearer ${githubToken}`,
'Content-type': 'application/json'
}
}
)
const pageObject = response.data
return pageObject
} catch (error) {
if (error.response && error.response.status === 409) {
return null
}
throw error
}
}
async function getPagesSite({ repositoryNwo, githubToken }) {
const pagesEndpoint = `${getApiBaseUrl()}/repos/${repositoryNwo}/pages`
const response = await axios.get(pagesEndpoint, {
headers: {
Accept: 'application/vnd.github.v3+json',
Authorization: `Bearer ${githubToken}`
}
})
const pageObject = response.data
return pageObject
}
async function findOrCreatePagesSite({ repositoryNwo, githubToken, enablement = true }) {
let pageObject
// Try to find an existing Pages site first
try {
pageObject = await getPagesSite({ repositoryNwo, githubToken })
} catch (error) {
if (!enablement) {
core.error('Get Pages site failed', error)
throw error
}
core.warning('Get Pages site failed', error)
}
if (!pageObject && enablement) {
// Create a new Pages site if one doesn't exist
try {
pageObject = await enablePagesSite({ repositoryNwo, githubToken })
} catch (error) {
core.error('Create Pages site failed', error)
throw error
}
// This somehow implies that the Pages site was already created but initially failed to be retrieved.
// Try one more time for this extreme edge case!
if (pageObject == null) {
try {
pageObject = await getPagesSite({ repositoryNwo, githubToken })
} catch (error) {
core.error('Get Pages site still failed', error)
throw error
}
}
}
return pageObject
}
module.exports = { findOrCreatePagesSite, enablePagesSite, getPagesSite, getApiBaseUrl }

215
src/api-client.test.js Normal file
View File

@@ -0,0 +1,215 @@
const core = require('@actions/core')
const axios = require('axios')
const apiClient = require('./api-client')
describe('apiClient', () => {
const GITHUB_REPOSITORY = 'actions/is-awesome'
const GITHUB_TOKEN = 'gha-token'
const PAGE_OBJECT = { html_url: 'https://actions.github.io/is-awesome/' }
beforeEach(() => {
jest.restoreAllMocks()
// Mock error/warning/info/debug
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())
})
describe('getApiBaseUrl', () => {
it('returns GITHUB_API_URL environment variable when set', async () => {
const expectedBaseUrl = 'https://api.ghe.com'
process.env.GITHUB_API_URL = expectedBaseUrl
const result = apiClient.getApiBaseUrl()
delete process.env.GITHUB_API_URL
expect(result).toEqual(expectedBaseUrl)
})
it('defaults to GitHub API if GITHUB_API_URL environment variable is empty', async () => {
process.env.GITHUB_API_URL = ''
const result = apiClient.getApiBaseUrl()
delete process.env.GITHUB_API_URL
expect(result).toEqual('https://api.github.com')
})
it('defaults to GitHub API if GITHUB_API_URL environment variable is not set', async () => {
delete process.env.GITHUB_API_URL
const result = apiClient.getApiBaseUrl()
expect(result).toEqual('https://api.github.com')
})
})
describe('enablePagesSite', () => {
it('makes a request to create a page', async () => {
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.resolve({ status: 201, data: PAGE_OBJECT }))
const result = await apiClient.enablePagesSite({
repositoryNwo: GITHUB_REPOSITORY,
githubToken: GITHUB_TOKEN
})
expect(result).toEqual(PAGE_OBJECT)
})
it('handles a 409 response when the page already exists', async () => {
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.reject({ response: { status: 409 } }))
// Simply assert that no error is raised
const result = await apiClient.enablePagesSite({
repositoryNwo: GITHUB_REPOSITORY,
githubToken: GITHUB_TOKEN
})
expect(result).toBe(null)
})
it('re-raises errors on failure status codes', async () => {
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
let erred = false
try {
await apiClient.enablePagesSite({
repositoryNwo: GITHUB_REPOSITORY,
githubToken: GITHUB_TOKEN
})
} catch (error) {
erred = true
expect(error.response.status).toEqual(404)
}
expect(erred).toBe(true)
})
})
describe('getPagesSite', () => {
it('makes a request to get a page', async () => {
const PAGE_OBJECT = { html_url: 'https://actions.github.io/is-awesome/' }
jest.spyOn(axios, 'get').mockImplementationOnce(() => Promise.resolve({ status: 200, data: PAGE_OBJECT }))
const result = await apiClient.getPagesSite({
repositoryNwo: GITHUB_REPOSITORY,
githubToken: GITHUB_TOKEN
})
expect(result).toEqual(PAGE_OBJECT)
})
it('re-raises errors on failure status codes', async () => {
jest.spyOn(axios, 'get').mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
let erred = false
try {
await apiClient.getPagesSite({
repositoryNwo: GITHUB_REPOSITORY,
githubToken: GITHUB_TOKEN
})
} catch (error) {
erred = true
expect(error.response.status).toEqual(404)
}
expect(erred).toBe(true)
})
})
describe('findOrCreatePagesSite', () => {
it('does not make a request to create a page if it already exists', async () => {
const PAGE_OBJECT = { html_url: 'https://actions.github.io/is-awesome/' }
jest.spyOn(axios, 'get').mockImplementationOnce(() => Promise.resolve({ status: 200, data: PAGE_OBJECT }))
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
const result = await apiClient.findOrCreatePagesSite({
repositoryNwo: GITHUB_REPOSITORY,
githubToken: GITHUB_TOKEN
})
expect(result).toEqual(PAGE_OBJECT)
expect(axios.get).toHaveBeenCalledTimes(1)
expect(axios.post).toHaveBeenCalledTimes(0)
})
it('makes request to create a page by default if it does not exist', async () => {
const PAGE_OBJECT = { html_url: 'https://actions.github.io/is-awesome/' }
jest.spyOn(axios, 'get').mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.resolve({ status: 201, data: PAGE_OBJECT }))
const result = await apiClient.findOrCreatePagesSite({
repositoryNwo: GITHUB_REPOSITORY,
githubToken: GITHUB_TOKEN
})
expect(result).toEqual(PAGE_OBJECT)
expect(axios.get).toHaveBeenCalledTimes(1)
expect(axios.post).toHaveBeenCalledTimes(1)
})
it('makes a request to create a page when explicitly enabled if it does not exist', async () => {
const PAGE_OBJECT = { html_url: 'https://actions.github.io/is-awesome/' }
jest.spyOn(axios, 'get').mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.resolve({ status: 201, data: PAGE_OBJECT }))
const result = await apiClient.findOrCreatePagesSite({
repositoryNwo: GITHUB_REPOSITORY,
githubToken: GITHUB_TOKEN,
enablement: true
})
expect(result).toEqual(PAGE_OBJECT)
expect(axios.get).toHaveBeenCalledTimes(1)
expect(axios.post).toHaveBeenCalledTimes(1)
})
it('does not make a request to create a page when explicitly disabled even if it does not exist', async () => {
jest.spyOn(axios, 'get').mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.reject({ response: { status: 500 } })) // just so they both aren't 404
let erred = false
try {
await apiClient.findOrCreatePagesSite({
repositoryNwo: GITHUB_REPOSITORY,
githubToken: GITHUB_TOKEN,
enablement: false
})
} catch (error) {
erred = true
// re-raised error
expect(error.response.status).toEqual(404)
}
expect(erred).toBe(true)
expect(axios.get).toHaveBeenCalledTimes(1)
expect(axios.post).toHaveBeenCalledTimes(0)
})
it('does not make a second request to get page if create fails for reason other than existence', async () => {
jest.spyOn(axios, 'get').mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.reject({ response: { status: 500 } })) // just so they both aren't 404
let erred = false
try {
await apiClient.findOrCreatePagesSite({
repositoryNwo: GITHUB_REPOSITORY,
githubToken: GITHUB_TOKEN
})
} catch (error) {
erred = true
// re-raised error
expect(error.response.status).toEqual(500)
}
expect(erred).toBe(true)
expect(axios.get).toHaveBeenCalledTimes(1)
expect(axios.post).toHaveBeenCalledTimes(1)
})
it('makes second request to get page if create fails because of existence', async () => {
const PAGE_OBJECT = { html_url: 'https://actions.github.io/is-awesome/' }
jest
.spyOn(axios, 'get')
.mockImplementationOnce(() => Promise.reject({ response: { status: 404 } }))
.mockImplementationOnce(() => Promise.resolve({ status: 200, data: PAGE_OBJECT }))
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.reject({ response: { status: 409 } }))
const result = await apiClient.findOrCreatePagesSite({
repositoryNwo: GITHUB_REPOSITORY,
githubToken: GITHUB_TOKEN
})
expect(result).toEqual(PAGE_OBJECT)
expect(axios.get).toHaveBeenCalledTimes(2)
expect(axios.post).toHaveBeenCalledTimes(1)
})
})
})

View File

@@ -0,0 +1,8 @@
// Default Pages configuration for SvelteKit
import adapter from '@sveltejs/adapter-auto'
export default {
kit: {
adapter: adapter()
}
}

View File

@@ -9,7 +9,7 @@ Pages's path based routing (and work).
Supported configuration initializations:
(1) Default export:
(1) Direct default export:
export default {
// configuration object here
@@ -21,19 +21,69 @@ Supported configuration initializations:
// configuration object here
}
(3) Indirect module export:
(3) Indirect default export:
const config = // configuration object here
const config = {
// configuration object here
}
export default config
(4) Indirect module export:
const config = {
// configuration object here
}
module.exports = config
(5) Direct default export with wrapping call:
export default defineConfig({
// configuration object here
})
(6) Direct module export with wrapping call:
module.exports = defineConfig({
// configuration object here
})
(7) Indirect default export with wrapping call at the definition:
const config = defineConfig({
// configuration object here
})
export default config
(8) Indirect default export with wrapping call at the export:
const config = {
// configuration object here
}
export default defineConfig(config)
(9) Indirect module export with wrapping call at the definition:
const config = defineConfig({
// configuration object here
})
module.exports = config
(10) Indirect module export with wrapping call at the export:
const config = {
// configuration object here
}
module.exports = defineConfig(config)
*/
class ConfigParser {
// Ctor
// - configurationFile: path to the configuration file
// - blankConfigurationFile: a blank configuration file to use if non was previously found
constructor({configurationFile, blankConfigurationFile, properties}) {
constructor({ configurationFile, blankConfigurationFile, allowWrappingCall = false, properties }) {
// Save field
this.configurationFile = configurationFile
this.allowWrappingCall = allowWrappingCall === true
this.properties = properties
// If the configuration file does not exist, initialize it with the blank configuration file
@@ -49,23 +99,110 @@ class ConfigParser {
this.configuration = fs.readFileSync(this.configurationFile, 'utf8')
}
findTopLevelVariableDeclarator(ast, identifierName) {
let targetDeclarator
ast.body.find(
node =>
node.type === 'VariableDeclaration' &&
node.declarations &&
node.declarations.length > 0 &&
node.declarations.find(declarator => {
if (
declarator.type === 'VariableDeclarator' &&
declarator.id &&
declarator.id.type === 'Identifier' &&
declarator.id.name === identifierName
) {
targetDeclarator = declarator
return true
}
})
)
return targetDeclarator
}
// Find the configuration object in an AST.
// Look for a default export, a direct module export or an indirect module
// export (in that order).
// Look for, in order:
// - a direct default export
// - a direct default export with a wrapping call
// - an indirect default export
// - an indirect default export with a wrapping call at the definition
// - an indirect default export with a wrapping call at the export
// - a direct module export
// - a direct module export with a wrapping call
// - an indirect module export
// - an indirect module export with a wrapping call at the definition
// - an indirect module export with a wrapping call at the export
//
// Return the configuration object or null.
findConfigurationObject(ast) {
findConfigurationObject(ast, allowWrappingCall = false) {
// Try to find a default export
var defaultExport = ast.body.find(
node =>
node.type === 'ExportDefaultDeclaration' &&
node.declaration.type === 'ObjectExpression'
)
if (defaultExport) {
core.info('Found configuration object in default export declaration')
var defaultExport = ast.body.find(node => node.type === 'ExportDefaultDeclaration')
// Direct default export
if (defaultExport && defaultExport.declaration.type === 'ObjectExpression') {
core.info('Found configuration object in direct default export declaration')
return defaultExport.declaration
}
// Direct default export with a wrapping call
else if (
allowWrappingCall &&
defaultExport &&
defaultExport.declaration.type === 'CallExpression' &&
defaultExport.declaration.arguments.length > 0 &&
defaultExport.declaration.arguments[0] &&
defaultExport.declaration.arguments[0].type === 'ObjectExpression'
) {
core.info('Found configuration object in direct default export declaration with a wrapping call')
return defaultExport.declaration.arguments[0]
}
// Indirect default export
else if (defaultExport && defaultExport.declaration.type === 'Identifier') {
const identifierName = defaultExport.declaration.name
const identifierDeclarator = this.findTopLevelVariableDeclarator(ast, identifierName)
const identifierInitialization = identifierDeclarator && identifierDeclarator.init
if (identifierInitialization && identifierInitialization.type === 'ObjectExpression') {
core.info('Found configuration object in indirect default export declaration')
return identifierInitialization
}
// Indirect default export with a wrapping call at the definition
else if (
allowWrappingCall &&
identifierInitialization &&
identifierInitialization.type === 'CallExpression' &&
identifierInitialization.arguments.length > 0 &&
identifierInitialization.arguments[0] &&
identifierInitialization.arguments[0].type === 'ObjectExpression'
) {
core.info(
'Found configuration object in indirect default export declaration with a wrapping call at the definition'
)
return identifierInitialization.arguments[0]
}
}
// Indirect default export with a wrapping call at the export
else if (
allowWrappingCall &&
defaultExport &&
defaultExport.declaration.type === 'CallExpression' &&
defaultExport.declaration.arguments.length > 0 &&
defaultExport.declaration.arguments[0] &&
defaultExport.declaration.arguments[0].type === 'Identifier'
) {
const identifierName = defaultExport.declaration.arguments[0].name
const identifierDeclarator = this.findTopLevelVariableDeclarator(ast, identifierName)
const identifierInitialization = identifierDeclarator && identifierDeclarator.init
if (identifierInitialization && identifierInitialization.type === 'ObjectExpression') {
core.info(
'Found configuration object in indirect default export declaration with a wrapping call at the export'
)
return identifierInitialization
}
}
// Try to find a module export
var moduleExport = ast.body.find(
node =>
@@ -80,32 +217,62 @@ class ConfigParser {
)
// Direct module export
if (
moduleExport &&
moduleExport.expression.right.type === 'ObjectExpression'
) {
if (moduleExport && moduleExport.expression.right.type === 'ObjectExpression') {
core.info('Found configuration object in direct module export')
return moduleExport.expression.right
}
// Indirect module export
// Direct default export with a wrapping call
else if (
allowWrappingCall &&
moduleExport &&
moduleExport.expression.right.type === 'Identifier'
moduleExport.expression.right.type === 'CallExpression' &&
moduleExport.expression.right.arguments.length > 0 &&
moduleExport.expression.right.arguments[0] &&
moduleExport.expression.right.arguments[0].type === 'ObjectExpression'
) {
core.info('Found configuration object in direct module export with a wrapping call')
return moduleExport.expression.right.arguments[0]
}
// Indirect module export
else if (moduleExport && moduleExport.expression.right.type === 'Identifier') {
const identifierName = moduleExport && moduleExport.expression.right.name
const identifierDefinition = ast.body.find(
node =>
node.type === 'VariableDeclaration' &&
node.declarations.length == 1 &&
node.declarations[0].type === 'VariableDeclarator' &&
node.declarations[0].id.type === 'Identifier' &&
node.declarations[0].id.name === identifierName &&
node.declarations[0].init.type === 'ObjectExpression'
)
if (identifierDefinition) {
const identifierDeclarator = this.findTopLevelVariableDeclarator(ast, identifierName)
const identifierInitialization = identifierDeclarator && identifierDeclarator.init
if (identifierInitialization && identifierInitialization.type === 'ObjectExpression') {
core.info('Found configuration object in indirect module export')
return identifierDefinition.declarations[0].init
return identifierInitialization
}
// Indirect module export with a wrapping call at the definition
else if (
allowWrappingCall &&
identifierInitialization &&
identifierInitialization.type === 'CallExpression' &&
identifierInitialization.arguments.length > 0 &&
identifierInitialization.arguments[0] &&
identifierInitialization.arguments[0].type === 'ObjectExpression'
) {
core.info('Found configuration object in indirect module export with a wrapping call at the definition')
return identifierInitialization.arguments[0]
}
}
// Indirect module export with a wrapping call at the export
else if (
allowWrappingCall &&
moduleExport &&
moduleExport.expression.right.type === 'CallExpression' &&
moduleExport.expression.right.arguments.length > 0 &&
moduleExport.expression.right.arguments[0] &&
moduleExport.expression.right.arguments[0].type === 'Identifier'
) {
const identifierName = moduleExport.expression.right.arguments[0].name
const identifierDeclarator = this.findTopLevelVariableDeclarator(ast, identifierName)
const identifierInitialization = identifierDeclarator && identifierDeclarator.init
if (identifierInitialization && identifierInitialization.type === 'ObjectExpression') {
core.info('Found configuration object in indirect module export declaration with a wrapping call at the export')
return identifierInitialization
}
}
@@ -120,9 +287,7 @@ class ConfigParser {
// Try to find a property matching a given name
const property =
object.type === 'ObjectExpression' &&
object.properties.find(
node => node.key.type === 'Identifier' && node.key.name === name
)
object.properties.find(node => node.key.type === 'Identifier' && node.key.name === name)
// Return the property's value (if found) or null
if (property) {
@@ -142,9 +307,7 @@ class ConfigParser {
return `${properties[startIndex]}: ${JSON.stringify(propertyValue)}`
} else {
return (
`${properties[startIndex]}: {` +
this.getPropertyDeclaration(properties, startIndex + 1, propertyValue) +
'}'
`${properties[startIndex]}: {` + this.getPropertyDeclaration(properties, startIndex + 1, propertyValue) + '}'
)
}
}
@@ -173,17 +336,18 @@ class ConfigParser {
const ast = espree.parse(this.configuration, espreeOptions)
// Find the configuration object
var configurationObject = this.findConfigurationObject(ast)
var configurationObject = this.findConfigurationObject(ast, this.allowWrappingCall)
if (!configurationObject) {
throw 'Could not find a configuration object in the configuration file'
}
// A property may be nested in the configuration file. Split the property name with `.`
// A property may be nested in the configuration file. Split the property name with '.'
// then walk the configuration object one property at a time.
var depth = 0
const properties = propertyName.split('.')
var lastNode = configurationObject
while (1) {
// eslint-disable-next-line no-constant-condition
while (true) {
// Find the node for the current property
var propertyNode = this.findProperty(lastNode, properties[depth])
@@ -222,11 +386,7 @@ class ConfigParser {
// Create nested properties in the configuration file
else {
// Build the declaration to inject
const declaration = this.getPropertyDeclaration(
properties,
depth,
propertyValue
)
const declaration = this.getPropertyDeclaration(properties, depth, propertyValue)
// The last node identified is an object expression, so do the assignment
if (lastNode.type === 'ObjectExpression') {
@@ -263,7 +423,7 @@ class ConfigParser {
}
// Logging
core.info(`Injection successful, new configuration:`)
core.info('Injection successful, new configuration:')
core.info(this.configuration)
// Finally write the new configuration in the file
@@ -273,4 +433,4 @@ class ConfigParser {
}
}
module.exports = {ConfigParser}
module.exports = { ConfigParser }

View File

@@ -1,7 +1,8 @@
const fs = require('fs')
const core = require('@actions/core')
const {ConfigParser} = require('./config-parser')
const {getTempFolder, compareFiles} = require('./test-helpers')
const { ConfigParser } = require('./config-parser')
const { getTempFolder, compareFiles } = require('./test-helpers')
// Get the temp folder
const tempFolder = getTempFolder()
@@ -9,84 +10,109 @@ const tempFolder = getTempFolder()
// Cases to test
const cases = [
//
// Default export
// Direct default export
//
{
property: 'property',
source: `export default {}`,
expected: `export default { property: "value" }`
source: 'export default {}',
expected: 'export default { property: "value" }'
},
{
property: 'property',
source: `export default { property: 0 }`, // property exists and is a number
expected: `export default { property: "value" }`
source: 'export default { property: 0 }', // property exists and is a number
expected: 'export default { property: "value" }'
},
{
property: 'property',
source: `export default { property: false }`, // property exists and is a boolean
expected: `export default { property: "value" }`
source: 'export default { property: false }', // property exists and is a boolean
expected: 'export default { property: "value" }'
},
{
property: 'property',
source: `export default { property: "test" }`, // property exists and is a string
expected: `export default { property: "value" }`
source: 'export default { property: "test" }', // property exists and is a string
expected: 'export default { property: "value" }'
},
{
property: 'property',
source: `export default { property: [1,2] }`, // property exists and is an array
expected: `export default { property: "value" }`
source: 'export default { property: [1,2] }', // property exists and is an array
expected: 'export default { property: "value" }'
},
{
property: 'property',
source: `export default { property: null }`, // property exists and is null
expected: `export default { property: "value" }`
source: 'export default { property: null }', // property exists and is null
expected: 'export default { property: "value" }'
},
{
property: 'property',
source: `export default { property: {}}`, // property exists and is an object
expected: `export default { property: "value" }`
source: 'export default { property: { } }', // property exists and is an object
expected: 'export default { property: "value" }'
},
// Deep properties (injection 1)
{
property: 'property.b.c',
source: `export default {}`,
expected: `export default { property: { b: { c: "value" }}}`
source: 'export default {}',
expected: 'export default { property: { b: { c: "value" } } }'
},
{
property: 'property.b.c',
source: `export default { property: 0 }`, // property exists and is a number
expected: `export default { property: { b: { c: "value" }}}`
source: 'export default { property: 0 }', // property exists and is a number
expected: 'export default { property: { b: { c: "value" } } }'
},
{
property: 'property.b.c',
source: `export default { property: {}}`, // property exists and is an object
expected: `export default { property: { b: { c: "value" }}}`
source: 'export default { property: { } }', // property exists and is an object
expected: 'export default { property: { b: { c: "value" } } }'
},
// Deep properties (injection 2)
{
property: 'property.b.c',
source: `export default { property: { b: 0 }}`, // property exists and is a number
expected: `export default { property: { b: { c: "value" }}}`
source: 'export default { property: { b: 0 } }', // property exists and is a number
expected: 'export default { property: { b: { c: "value" } } }'
},
{
property: 'property.b.c',
source: `export default { property: { b: {}}}`, // property exists and is an object
expected: `export default { property: { b: { c: "value" }}}`
source: 'export default { property: { b: { } } }', // property exists and is an object
expected: 'export default { property: { b: { c: "value" } } }'
},
{
property: 'property.b.c',
source: `export default { property: { b: { hello: 123}}}`, // property exists and is a non-empty object
expected: `export default { property: { b: { c: "value", hello: 123 }}}`
source: 'export default { property: { b: { hello: 123 } } }', // property exists and is a non-empty object
expected: 'export default { property: { b: { c: "value", hello: 123 } } }'
},
// Deep properties (existing properties)
{
property: 'a1.a2',
source: `export default { a2: false, a1: { a3: [12]}}`, // property exists and is a non-empty object
expected: `export default { a2: false, a1: { a2: "value", a3: [12]}}`
source: 'export default { a2: false, a1: { a3: [12] } }', // property exists and is a non-empty object
expected: 'export default { a2: false, a1: { a2: "value", a3: [12] } }'
},
//
// Indirect default export
//
{
property: 'property',
source: 'const config = {}; export default config',
expected: 'const config = { property: "value"}; export default config'
},
// with more than 1 declaration chained together
{
property: 'property',
source: 'var temp = {}, config = {}; export default config',
expected: 'var temp = {}, config = { property: "value"}; export default config'
},
// deeper
{
property: 'a.b.c',
source: 'var config = {}; export default config',
expected: 'var config = { a: { b: { c: "value" } } }; export default config'
},
{
property: 'a.b.c',
source: 'var config = { a: { b: [], c: "hello" } }; export default config',
expected: 'var config = { a: { b: { c: "value"}, c: "hello" } }; export default config'
},
//
@@ -94,18 +120,18 @@ const cases = [
//
{
property: 'property',
source: `module.exports = {}`,
expected: `module.exports = { property: "value"}`
source: 'module.exports = {}',
expected: 'module.exports = { property: "value"}'
},
{
property: 'property',
source: `module.exports = { p1: 0}`,
expected: `module.exports = { property: "value", p1: 0}`
source: 'module.exports = { p1: 0}',
expected: 'module.exports = { property: "value", p1: 0}'
},
{
property: 'a.b.c',
source: `module.exports = { p1: 0}`,
expected: `module.exports = { a: { b: { c: "value" }}, p1: 0}`
source: 'module.exports = { p1: 0}',
expected: 'module.exports = { a: { b: { c: "value" } }, p1: 0}'
},
//
@@ -113,40 +139,156 @@ const cases = [
//
{
property: 'property',
source: `const config = {}; module.exports = config`,
expected: `const config = { property: "value"}; module.exports = config`
source: 'const config = {}; module.exports = config',
expected: 'const config = { property: "value"}; module.exports = config'
},
// with more than 1 declaration chained together
{
property: 'property',
source: `var config = {}; module.exports = config`,
expected: `var config = { property: "value"}; module.exports = config`
source: 'var temp = {}, config = {}; module.exports = config',
expected: 'var temp = {}, config = { property: "value"}; module.exports = config'
},
// deeper
{
property: 'a.b.c',
source: 'var config = {}; module.exports = config',
expected: 'var config = { a: { b: { c: "value" } } }; module.exports = config'
},
{
property: 'a.b.c',
source: `var config = {}; module.exports = config`,
expected: `var config = { a: { b: { c: "value"}}}; module.exports = config`
source: 'var config = { a: { b: [], c: "hello" } }; module.exports = config',
expected: 'var config = { a: { b: { c: "value"}, c: "hello" } }; module.exports = config'
},
//
// Direct default export with wrapping call
//
{
property: 'a.b.c',
source: `var config = { a: { b: [], c: "hello"}}; module.exports = config`,
expected: `var config = { a: { b: { c: "value"}, c: "hello"}}; module.exports = config`
property: 'property',
source: 'import { defineConfig } from "astro/config"; export default defineConfig({ p1: 0 })',
expected: 'import { defineConfig } from "astro/config"; export default defineConfig({ property: "value", p1: 0 })',
allowWrappingCall: true
},
//
// Direct module exports with wrapping call
//
{
property: 'property',
source: 'const { defineConfig } = require("astro/config"); module.exports = defineConfig({ p1: 0 })',
expected:
'const { defineConfig } = require("astro/config"); module.exports = defineConfig({ property: "value", p1: 0 })',
allowWrappingCall: true
},
//
// Indirect default export with wrapping call at the definition
//
{
property: 'property',
source: 'import { defineConfig } from "astro/config"; const config = defineConfig({}); export default config',
expected:
'import { defineConfig } from "astro/config"; const config = defineConfig({ property: "value" }); export default config',
allowWrappingCall: true
},
// with more than 1 declaration chained together
{
property: 'property',
source:
'import { defineConfig } from "astro/config"; const temp = {}, config = defineConfig({}); export default config',
expected:
'import { defineConfig } from "astro/config"; const temp = {}, config = defineConfig({ property: "value" }); export default config',
allowWrappingCall: true
},
//
// Indirect default export with wrapping call at the export
//
{
property: 'property',
source: 'import { defineConfig } from "astro/config"; const config = {}; export default defineConfig(config)',
expected:
'import { defineConfig } from "astro/config"; const config = { property: "value" }; export default defineConfig(config)',
allowWrappingCall: true
},
// with more than 1 declaration chained together
{
property: 'property',
source:
'import { defineConfig } from "astro/config"; const temp = {}, config = {}; export default defineConfig(config)',
expected:
'import { defineConfig } from "astro/config"; const temp = {}, config = { property: "value" }; export default defineConfig(config)',
allowWrappingCall: true
},
//
// Indirect module exports with wrapping call at the definition
//
{
property: 'property',
source:
'const { defineConfig } = require("astro/config"); const config = defineConfig({}); module.exports = config',
expected:
'const { defineConfig } = require("astro/config"); const config = defineConfig({ property: "value"}); module.exports = config',
allowWrappingCall: true
},
// with more than 1 declaration chained together
{
property: 'property',
source:
'const { defineConfig } = require("astro/config"); const temp = {}, config = defineConfig({}); module.exports = config',
expected:
'const { defineConfig } = require("astro/config"); const temp = {}, config = defineConfig({ property: "value"}); module.exports = config',
allowWrappingCall: true
},
//
// Indirect module exports with wrapping call at the export
//
{
property: 'property',
source:
'const { defineConfig } = require("astro/config"); const config = {}; module.exports = defineConfig(config)',
expected:
'const { defineConfig } = require("astro/config"); const config = { property: "value"}; module.exports = defineConfig(config)',
allowWrappingCall: true
},
// with more than 1 declaration chained together
{
property: 'property',
source:
'const { defineConfig } = require("astro/config"); const temp = {}, config = {}; module.exports = defineConfig(config)',
expected:
'const { defineConfig } = require("astro/config"); const temp = {}, config = { property: "value"}; module.exports = defineConfig(config)',
allowWrappingCall: true
}
]
describe('config-parser', () => {
cases.forEach(({property, source, expected}, index) => {
it(`Inject path properly for case #${index}`, () => {
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, allowWrappingCall = false }, index) => {
it(`injects path properly for case #${index}`, () => {
// Write the source file
const sourceFile = `${tempFolder}/source.js`
fs.writeFileSync(sourceFile, source, {encoding: 'utf8'})
fs.writeFileSync(sourceFile, source, { encoding: 'utf8' })
// Write the expected file
const expectedFile = `${tempFolder}/expected.js`
fs.writeFileSync(expectedFile, expected, {encoding: 'utf8'})
fs.writeFileSync(expectedFile, expected, { encoding: 'utf8' })
// Update the settings and do the injection
new ConfigParser({
configurationFile: sourceFile
configurationFile: sourceFile,
allowWrappingCall
}).inject(property, 'value')
// Compare the files

View File

@@ -5,7 +5,9 @@ function getRequiredVars() {
return {
repositoryNwo: process.env.GITHUB_REPOSITORY,
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') === 'true'
}
}
@@ -21,4 +23,4 @@ function getContext() {
return requiredVars
}
module.exports = {getContext}
module.exports = { getContext }

View File

@@ -1,31 +0,0 @@
const core = require('@actions/core')
const axios = require('axios')
async function enablePages({repositoryNwo, githubToken}) {
const pagesEndpoint = `https://api.github.com/repos/${repositoryNwo}/pages`
try {
const response = await axios.post(
pagesEndpoint,
{build_type: 'workflow'},
{
headers: {
Accept: 'application/vnd.github.v3+json',
Authorization: `Bearer ${githubToken}`,
'Content-type': 'application/json'
}
}
)
core.info('Created pages site')
} catch (error) {
if (error.response && error.response.status === 409) {
core.info('Pages site exists')
return
}
core.error("Couldn't create pages site", error)
throw error
}
}
module.exports = enablePages

View File

@@ -1,55 +0,0 @@
const core = require('@actions/core')
const axios = require('axios')
const enablePages = require('./enable-pages')
describe('enablePages', () => {
const GITHUB_REPOSITORY = 'paper-spa/is-awesome'
const GITHUB_TOKEN = 'gha-token'
beforeEach(() => {
jest.restoreAllMocks()
// Mock error/warning/info/debug
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())
})
it('makes a request to create a page', async () => {
jest.spyOn(axios, 'post').mockImplementationOnce(() => Promise.resolve({}))
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}}))
// Simply assert that no error is raised
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}}))
try {
await enablePages({
repositoryNwo: GITHUB_REPOSITORY,
githubToken: GITHUB_TOKEN
})
} catch (error) {
expect(error.response.status).toEqual(404)
}
})
})

View File

@@ -1,2 +1,2 @@
// Default Pages configuration for Gatsby
module.exports = { pathPrefix: "/docs/" }
module.exports = { siteMetadata: { siteUrl: 'https://configure-pages.github.io' }, pathPrefix: '/docs/' }

View File

@@ -1 +1 @@
// This file is not read by the test suite
// This file is not read by the test suite

View File

@@ -0,0 +1,6 @@
module.exports = {
siteMetadata: {
title: 'My Gatsby Site'
},
plugins: []
}

View File

@@ -0,0 +1,8 @@
module.exports = {
pathPrefix: '/docs/',
siteMetadata: {
siteUrl: 'https://configure-pages.github.io',
title: 'My Gatsby Site'
},
plugins: []
}

View File

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

View File

@@ -0,0 +1,8 @@
export default {
pathPrefix: '/docs/',
siteMetadata: {
siteUrl: 'https://configure-pages.github.io',
title: 'My Gatsby Site'
},
plugins: []
}

View File

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

View File

@@ -0,0 +1,6 @@
export default {
siteMetadata: {
title: 'My Gatsby Site'
},
plugins: []
}

View File

@@ -1,6 +1,3 @@
// Default Pages configuration for Next
const nextConfig = {
experimental: {images: {unoptimized: true}},
basePath: '/docs'
}
const nextConfig = { images: { unoptimized: true }, experimental: { images: { unoptimized: true } }, basePath: '/docs' }
module.exports = nextConfig

View File

@@ -1 +1 @@
// This file is not read by the test suite
// This file is not read by the test suite

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
swcMinify: true
}
module.exports = nextConfig
module.exports = 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

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

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

@@ -1,2 +1,2 @@
// Default Pages configuration for Nuxt
export default {target: 'static', router: {base: '/docs/'}}
export default { target: 'static', router: { base: '/docs/' } }

View File

@@ -1 +1 @@
// This file is not read by the test suite
// This file is not read by the test suite

View File

@@ -0,0 +1,37 @@
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,39 @@
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

@@ -1,7 +1,7 @@
export default {
// Disable server-side rendering: https://go.nuxtjs.dev/ssr-mode
target: 'static',
router: { base: "/docs/" },
router: { base: '/docs/' },
ssr: false,
// Global page headers: https://go.nuxtjs.dev/config-head
@@ -16,31 +16,24 @@ export default {
{ hid: 'description', name: 'description', content: '' },
{ name: 'format-detection', content: 'telephone=no' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
],
css: [],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
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: [
],
buildModules: [],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
],
modules: [],
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}
build: {}
}

View File

@@ -0,0 +1,39 @@
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

@@ -14,31 +14,24 @@ export default {
{ hid: 'description', name: 'description', content: '' },
{ name: 'format-detection', content: 'telephone=no' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
],
css: [],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
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: [
],
buildModules: [],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
],
modules: [],
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}
build: {}
}

View File

@@ -0,0 +1,37 @@
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

@@ -0,0 +1,10 @@
// Default Pages configuration for SvelteKit
import adapter from '@sveltejs/adapter-auto'
export default {
kit: {
prerender: { origin: 'https://configure-pages.github.io' },
paths: { base: '/docs' },
adapter: adapter()
}
}

View File

@@ -0,0 +1 @@
// This file is not read by the test suite

View File

@@ -0,0 +1,12 @@
import adapter from '@sveltejs/adapter-auto'
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
prerender: { origin: 'https://configure-pages.github.io' },
paths: { base: '/docs' },
adapter: adapter()
}
}
export default config

View File

@@ -0,0 +1,10 @@
import adapter from '@sveltejs/adapter-auto'
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter()
}
}
export default config

View File

@@ -1,38 +0,0 @@
const core = require('@actions/core')
const axios = require('axios')
const {setPagesPath} = require('./set-pages-path')
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}`
}
})
pageObject = response.data
core.info(JSON.stringify(pageObject))
const siteUrl = new URL(pageObject.html_url)
if (staticSiteGenerator) {
setPagesPath({staticSiteGenerator, path: siteUrl.pathname})
}
core.setOutput('base_url', siteUrl.href)
core.setOutput('origin', siteUrl.origin)
core.setOutput('host', siteUrl.host)
core.setOutput('base_path', siteUrl.pathname)
} catch (error) {
core.error('Get on the Page failed', error)
throw error
}
}
module.exports = getPagesBaseUrl

View File

@@ -1,93 +0,0 @@
const core = require('@actions/core')
const axios = require('axios')
const getPagesBaseUrl = require('./get-pages-base-url')
describe('getPagesBaseUrl', () => {
const GITHUB_REPOSITORY = 'paper-spa/is-awesome'
const GITHUB_TOKEN = 'gha-token'
beforeEach(() => {
jest.restoreAllMocks()
jest.spyOn(core, 'setOutput').mockImplementation((key, value) => {
key, value
})
jest.spyOn(core, 'setFailed').mockImplementation(param => param)
// Mock error/warning/info/debug
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())
})
it('gets expected outputs for profile site', async () => {
const baseUrl = 'https://octocat.github.io/'
jest
.spyOn(axios, 'get')
.mockImplementationOnce(() =>
Promise.resolve({data: {html_url: baseUrl}})
)
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('host', 'octocat.github.io')
expect(core.setOutput).toHaveBeenCalledWith('base_path', '/')
})
it('gets expected outputs for project site', async () => {
const baseUrl = 'https://octocat.github.io/my-repo/'
jest
.spyOn(axios, 'get')
.mockImplementationOnce(() =>
Promise.resolve({data: {html_url: baseUrl}})
)
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('host', 'octocat.github.io')
expect(core.setOutput).toHaveBeenCalledWith('base_path', '/my-repo/')
})
it('gets expected outputs for site with custom domain name', async () => {
const baseUrl = 'https://www.example.com/'
jest
.spyOn(axios, 'get')
.mockImplementationOnce(() =>
Promise.resolve({data: {html_url: baseUrl}})
)
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('host', 'www.example.com')
expect(core.setOutput).toHaveBeenCalledWith('base_path', '/')
})
})

View File

@@ -1,16 +1,24 @@
const core = require('@actions/core')
const enablePages = require('./enable-pages')
const getPagesBaseUrl = require('./get-pages-base-url')
// All variables we need from the runtime are loaded here
const {getContext} = require('./context')
const { getContext } = require('./context')
const { findOrCreatePagesSite } = require('./api-client')
const { setPagesConfig } = require('./set-pages-config')
const outputPagesBaseUrl = require('./output-pages-base-url')
async function main() {
try {
const context = getContext()
await enablePages(context)
await getPagesBaseUrl(context)
const { repositoryNwo, githubToken, enablement, staticSiteGenerator, generatorConfigFile } = getContext()
const pageObject = await findOrCreatePagesSite({ repositoryNwo, githubToken, enablement })
const siteUrl = new URL(pageObject.html_url)
if (staticSiteGenerator) {
setPagesConfig({ staticSiteGenerator, generatorConfigFile, siteUrl })
}
outputPagesBaseUrl(siteUrl)
core.exportVariable('GITHUB_PAGES', 'true')
} catch (error) {
core.setFailed(error)
process.exit(1)

View File

@@ -0,0 +1,15 @@
const core = require('@actions/core')
const removeTrailingSlash = require('./remove-trailing-slash')
function outputPagesBaseUrl(siteUrl) {
// Many static site generators do not want the trailing slash, and it is much easier to add than remove in a workflow
const baseUrl = removeTrailingSlash(siteUrl.href)
const basePath = removeTrailingSlash(siteUrl.pathname)
core.setOutput('base_url', baseUrl)
core.setOutput('origin', siteUrl.origin)
core.setOutput('host', siteUrl.host)
core.setOutput('base_path', basePath)
}
module.exports = outputPagesBaseUrl

View File

@@ -0,0 +1,53 @@
const core = require('@actions/core')
const outputPagesBaseUrl = require('./output-pages-base-url')
describe('outputPagesBaseUrl', () => {
beforeEach(() => {
jest.restoreAllMocks()
jest.spyOn(core, 'setOutput').mockImplementation((key, value) => {
key, value
})
jest.spyOn(core, 'setFailed').mockImplementation(param => param)
// Mock error/warning/info/debug
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())
})
it('gets expected outputs for profile site', async () => {
const baseUrl = 'https://octocat.github.io/'
outputPagesBaseUrl(new URL(baseUrl))
expect(core.setOutput).toHaveBeenCalledWith('base_url', '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', '')
})
it('gets expected outputs for project site', async () => {
const baseUrl = 'https://octocat.github.io/my-repo/'
outputPagesBaseUrl(new URL(baseUrl))
expect(core.setOutput).toHaveBeenCalledWith('base_url', 'https://octocat.github.io/my-repo')
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')
})
it('gets expected outputs for site with custom domain name', async () => {
const baseUrl = 'https://www.example.com/'
outputPagesBaseUrl(new URL(baseUrl))
expect(core.setOutput).toHaveBeenCalledWith('base_url', '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', '')
})
})

View File

@@ -0,0 +1,3 @@
module.exports = function removeTrailingSlash(str) {
return str.endsWith('/') ? str.slice(0, -1) : str
}

100
src/set-pages-config.js Normal file
View File

@@ -0,0 +1,100 @@
const core = require('@actions/core')
const { ConfigParser } = require('./config-parser')
const removeTrailingSlash = require('./remove-trailing-slash')
const SUPPORTED_FILE_EXTENSIONS = ['.js', '.cjs', '.mjs']
// Return the settings to be passed to a {ConfigParser} for a given static site generator,
// optional configuration file path, and a Pages siteUrl value to inject
function getConfigParserSettings({ staticSiteGenerator, generatorConfigFile, siteUrl }) {
let { pathname: path, origin } = siteUrl
switch (staticSiteGenerator) {
case 'nuxt':
return {
configurationFile: generatorConfigFile || './nuxt.config.js',
blankConfigurationFile: `${__dirname}/blank-configurations/nuxt.js`,
properties: {
// Configure a base path on the router
'router.base': path,
// Set the target to static too
// https://nuxtjs.org/docs/configuration-glossary/configuration-target/
target: 'static'
}
}
case 'next':
// Next does not want a trailing slash
path = removeTrailingSlash(path)
return {
configurationFile: generatorConfigFile || './next.config.js',
blankConfigurationFile: `${__dirname}/blank-configurations/next.js`,
properties: {
// Configure a base path
basePath: path,
// Disable server side image optimization too
// https://nextjs.org/docs/api-reference/next/image#unoptimized
'experimental.images.unoptimized': true,
// No longer experimental as of Next.js v12.3.0
'images.unoptimized': true
}
}
case 'gatsby':
return {
configurationFile: generatorConfigFile || './gatsby-config.js',
blankConfigurationFile: `${__dirname}/blank-configurations/gatsby.js`,
properties: {
// Configure a path prefix
pathPrefix: path,
// Configure a site url
'siteMetadata.siteUrl': origin
}
}
case 'sveltekit':
// SvelteKit does not want a trailing slash
path = removeTrailingSlash(path)
return {
configurationFile: generatorConfigFile || './svelte.config.js',
blankConfigurationFile: `${__dirname}/blank-configurations/sveltekit.js`,
properties: {
// Configure a base path
'kit.paths.base': path,
// Configure a prerender origin
'kit.prerender.origin': origin
}
}
default:
throw `Unsupported static site generator: ${staticSiteGenerator}`
}
}
// Inject Pages configuration in a given static site generator's configuration file
function setPagesConfig({ staticSiteGenerator, generatorConfigFile, siteUrl }) {
try {
// Parse the configuration file and try to inject the Pages configuration in it
const settings = getConfigParserSettings({ staticSiteGenerator, generatorConfigFile, siteUrl })
new ConfigParser(settings).injectAll()
} catch (error) {
const isSupportedFileExtension = SUPPORTED_FILE_EXTENSIONS.some(ext => generatorConfigFile.endsWith(ext))
// Logging
if (!isSupportedFileExtension) {
core.warning(
`Unsupported configuration file extension. Currently supported extensions: ${SUPPORTED_FILE_EXTENSIONS.map(
ext => JSON.stringify(ext)
).join(', ')}`,
error
)
} else {
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 ${siteUrl}. Please ensure your framework is configured to generate relative links appropriately.`,
error
)
}
}
}
module.exports = { getConfigParserSettings, setPagesConfig }

View File

@@ -0,0 +1,111 @@
const fs = require('fs')
const path = require('path')
const core = require('@actions/core')
const { setPagesConfig } = require('./set-pages-config')
const { getTempFolder, compareFiles } = require('./test-helpers')
// Get the temp folder
const tempFolder = getTempFolder()
const SUPPORTED_GENERATORS = ['next', 'nuxt', 'gatsby', 'sveltekit']
const SUPPORTED_FILE_EXTENSIONS = ['.js', '.cjs', '.mjs']
const IS_BLANK_CONFIG_FILE_REGEX = new RegExp(
'^blank\\.(' + SUPPORTED_FILE_EXTENSIONS.map(ext => ext.slice(1)).join('|') + ')$'
)
function isBlankConfigFileName(fileName) {
return IS_BLANK_CONFIG_FILE_REGEX.test(fileName)
}
// Test suite
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
SUPPORTED_GENERATORS.forEach(staticSiteGenerator => {
// Folder containing the fixtures for a given static site generator
const fixtureFolder = `${__dirname}/fixtures/${staticSiteGenerator}`
// Get fixture files, excluding expected results
const configurationFiles = fs.readdirSync(fixtureFolder).filter(filename => !filename.includes('.expected.'))
// Create test siteUrl
const siteUrl = new URL('https://configure-pages.github.io/docs/')
// Iterate over the fixtures, outputting to default configuration file path
const defaultFileExtension = '.js'
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 (!isBlankConfigFileName(configurationFile)) {
fs.copyFileSync(fixtureSourceFile, fixtureTargetFile)
} else if (fs.existsSync(fixtureTargetFile)) {
fs.rmSync(fixtureTargetFile)
}
// Do the injections for the static site generator
setPagesConfig({
staticSiteGenerator,
generatorConfigFile: fixtureTargetFile,
siteUrl
})
// Read the expected file
const expectedFile = `${fixtureFolder}/${path.basename(
configurationFile,
defaultFileExtension
)}.expected${defaultFileExtension}`
// Compare the actual and expected files
compareFiles(fixtureTargetFile, expectedFile)
})
})
SUPPORTED_FILE_EXTENSIONS.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 (!isBlankConfigFileName(configurationFile)) {
fs.copyFileSync(fixtureSourceFile, fixtureTargetFile)
} else if (fs.existsSync(fixtureTargetFile)) {
fs.rmSync(fixtureTargetFile)
}
// Do the injections for the static site generator
setPagesConfig({
staticSiteGenerator,
generatorConfigFile: fixtureTargetFile,
siteUrl
})
// Read the expected file
const expectedFile = `${fixtureFolder}/${path.basename(
configurationFile,
fileExtension
)}.expected${fileExtension}`
// Compare the actual and expected files
compareFiles(fixtureTargetFile, expectedFile)
})
})
})
})
})

View File

@@ -1,68 +0,0 @@
const core = require('@actions/core')
const {ConfigParser} = require('./config-parser')
// Return the settings to be passed to a {ConfigParser} for a given
// static site generator and a Pages path value to inject
function getConfigParserSettings(staticSiteGenerator, path) {
switch (staticSiteGenerator) {
case 'nuxt':
return {
configurationFile: './nuxt.config.js',
blankConfigurationFile: `${__dirname}/blank-configurations/nuxt.js`,
properties: {
// Configure a base path on the router
'router.base': path,
// Set the target to static too
// https://nuxtjs.org/docs/configuration-glossary/configuration-target/
target: 'static'
}
}
case 'next':
// Next does not want a trailing slash
if (path.endsWith('/')) {
path = path.slice(0, -1)
}
return {
configurationFile: './next.config.js',
blankConfigurationFile: `${__dirname}/blank-configurations/next.js`,
properties: {
// Configure a base path
basePath: path,
// Disable server side image optimization too
// https://nextjs.org/docs/api-reference/next/image#unoptimized
'experimental.images.unoptimized': true
}
}
case 'gatsby':
return {
configurationFile: './gatsby-config.js',
blankConfigurationFile: `${__dirname}/blank-configurations/gatsby.js`,
properties: {
// Configure a path prefix
pathPrefix: path
}
}
default:
throw `Unsupported static site generator: ${staticSiteGenerator}`
}
}
// Inject Pages configuration in a given static site generator's configuration file
function setPagesPath({staticSiteGenerator, path}) {
try {
// Parse the configuration file and try to inject the Pages configuration in it
const settings = getConfigParserSettings(staticSiteGenerator, path)
new ConfigParser(settings).injectAll()
} catch (error) {
// Logging
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
)
}
}
module.exports = {getConfigParserSettings, setPagesPath}

View File

@@ -1,53 +0,0 @@
const fs = require('fs')
const path = require('path')
const {getConfigParserSettings} = require('./set-pages-path')
const {ConfigParser} = require('./config-parser')
const {getTempFolder, compareFiles} = require('./test-helpers')
// Get the temp folder
const tempFolder = getTempFolder()
// Test suite
describe('configParser', () => {
// Iterate over the static site generators
;['next', 'nuxt', 'gatsby'].forEach(staticSiteGenerator => {
// Folder containing the fixtures for a given static site generator
const fixtureFolder = `${__dirname}/fixtures/${staticSiteGenerator}`
// Iterate over the fixtures
fs.readdirSync(fixtureFolder).forEach(configurationFile => {
// Ignore expectation
if (configurationFile.endsWith('.expected.js')) {
return
}
it(`Inject path properly for ${staticSiteGenerator} in ${configurationFile}`, async () => {
// Get settings for the static site generator
const settings = getConfigParserSettings(staticSiteGenerator, '/docs/')
// 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)
}
// Update the settings and do the injection
settings.configurationFile = fixtureTargetFile
new ConfigParser(settings).injectAll()
// Read the expected file
const expectedFile = `${fixtureFolder}/${path.basename(
configurationFile,
'.js'
)}.expected.js`
// Compare the actual and expected files
compareFiles(settings.configurationFile, expectedFile)
})
})
})
})

View File

@@ -6,7 +6,7 @@ const assert = require('assert')
function getTempFolder() {
const tmpFolder = `${__dirname}/fixtures/tmp`
if (!fs.existsSync(tmpFolder)) {
fs.mkdirSync(tmpFolder, {recursive: true})
fs.mkdirSync(tmpFolder, { recursive: true })
}
return tmpFolder
}
@@ -14,19 +14,21 @@ function getTempFolder() {
// Read a JavaScript file and return it formatted
function formatFile(file) {
const fileContent = fs.readFileSync(file, 'utf8')
return prettier.format(fileContent, {
parser: 'espree',
return prettier
.format(fileContent, {
parser: 'espree',
// Prettier options
printWidth: 80,
tabWidth: 2,
useTabs: false,
semi: false,
singleQuote: true,
trailingComma: 'none',
bracketSpacing: false,
arrowParens: 'avoid'
}).trim()
// Prettier options
printWidth: 120,
tabWidth: 2,
useTabs: false,
semi: false,
singleQuote: true,
trailingComma: 'none',
bracketSpacing: true,
arrowParens: 'avoid'
})
.trim()
}
// Compare two JavaScript files
@@ -34,4 +36,4 @@ function compareFiles(actualFile, expectedFile) {
assert.equal(formatFile(actualFile), formatFile(expectedFile))
}
module.exports = {getTempFolder, formatFile, compareFiles}
module.exports = { getTempFolder, formatFile, compareFiles }