@suffolklitlab/alkiln 4.11.6 → 5.0.0-experimental2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ In this PR, I have:
2
+
3
+ * [ ] Added tests for any new features or bug fixes (if relevant)
4
+ * [ ] Added my changes to the CHANGELOG.md at the top, under the "Unreleased" section
5
+ * [ ] Ensured issues that this PR closes will be [automatically closed](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
6
+
7
+ ### Reason for this PR
8
+
9
+ <Insert reasons for this PR>
10
+
11
+ ### Links to any solved or related issues
12
+
13
+ <Insert links>
14
+
15
+ ### Any manual testing I have done to ensure my PR is working
16
+
17
+ <Insert description>
@@ -20,7 +20,7 @@ jobs:
20
20
 
21
21
  strategy:
22
22
  matrix:
23
- node-version: [17.x]
23
+ node-version: [18.x]
24
24
 
25
25
  env:
26
26
  BASE_URL: ${{ secrets.SERVER_URL }}
@@ -34,6 +34,7 @@ jobs:
34
34
  SECRET_VAR1: secret-var1-value
35
35
  SECRET_VAR2: secret-var2-value
36
36
  SECRET_FOR_MISSING_FIELD: secret for missing field
37
+ _ORIGIN: github
37
38
 
38
39
  name: Run Puppeteer tests
39
40
  steps:
@@ -52,24 +53,24 @@ jobs:
52
53
  # For the testing repo, the `REPO_URL` is that of a different repo and is created in `env:`
53
54
  - run: echo "Repo address is $REPO_URL"
54
55
  - name: Checkout
55
- uses: actions/checkout@v2
56
+ uses: actions/checkout@v3
56
57
  - name: Setup environment
57
- uses: actions/setup-node@v1
58
+ uses: actions/setup-node@v3
58
59
  with:
59
60
  node-version: ${{ matrix.node-version }}
60
61
  - run: npm install
61
62
  - run: npm run setup
62
- - run: npm run test -- ${{ github.event.inputs.tags && format('"--tags" "{0}"', github.event.inputs.tags) }}
63
+ - run: npm run test ${{ github.event.inputs.tags && format('{0}', github.event.inputs.tags) }}
63
64
  # Artifacts
64
65
  - name: upload unit tests artifacts folder
65
- uses: actions/upload-artifact@v2
66
+ uses: actions/upload-artifact@v3
66
67
  # This will upload even if a previous step has failed
67
68
  if: ${{ always() }}
68
69
  with:
69
70
  name: ${{ env.UNIT_TESTS_ARTIFACT_NAME }}
70
71
  path: ./_alkiln-*
71
72
  - name: upload integration tests artifacts folder
72
- uses: actions/upload-artifact@v2
73
+ uses: actions/upload-artifact@v3
73
74
  if: ${{ always() }}
74
75
  with:
75
76
  name: ${{ env.ARTIFACT_NAME }}
package/CHANGELOG.md CHANGED
@@ -38,30 +38,37 @@ Format:
38
38
  ### Security
39
39
  -
40
40
  -->
41
- <!-- ## [Unreleased] -->
42
-
43
- ## [4.11.5] - 2023-06-12
44
- ### Fixed
45
- - Updated field decoding to handle new object field encoding. See [#711](https://github.com/SuffolkLITLab/ALKiln/issues/711)
46
-
47
- ## [4.11.4] - 2023-04-19
48
- ### Fixed
49
- - Shorten path names to try to accommodate limitations of windows systems while still keeping enough useful information to help devs identify the test outputs. https://github.com/SuffolkLITLab/ALKiln/issues/618
41
+ ## [Unreleased]
42
+ ### Added
43
+ - added additional functionality to the sign method to allow developers to take a name argument to sign on canvas: issue #596
44
+ - A new script: `alkiln-run`, which acts like `npm run cucumber`, but can
45
+ be run in any directory, not just in an npm package.
46
+ - Additional environment variables and their validation to allow for tests that run on a developer's server/Playground instead of through GitHub. Also, other functionality for that purpose. [Issue #661](https://github.com/SuffolkLITLab/ALKiln/issues/661)
47
+ - Tests for new session_vars behavior and improve previous tests.
48
+ - Adds `npm-shrinkwrap.json`, so installs from npm will have fixed version dependencies
50
49
 
51
- ## [4.11.3] - 2023-04-06
52
50
  ### Changed
53
- - Project name prefix now includes ALKiln in it for clarity
51
+ - BREAKING: the github action no longer runs `npm run XYZ`; it directly calls scripts,
52
+ e.g. `alkiln-setup`, `alkiln-run`, `alkiln-takedown`
53
+ - upgraded cucumber v8.6.0
54
+ - using cucumber's JS API to run tests. For more details on how it works,
55
+ see [the cucumber-js docs](https://github.com/cucumber/cucumber-js/blob/main/docs/javascript_api.md).
56
+ - don't print the ["publish this cucumber report" message](https://github.com/cucumber/cucumber-js/blob/main/docs/configuration.md#options)
57
+ - Adjusted validation of some environment variables to account for Playground vs. GitHub or local test runs. [Issue #661](https://github.com/SuffolkLITLab/ALKiln/issues/661)
58
+ - Docassemble Project name prefix now includes ALKiln in it for clarity
54
59
 
55
60
  ### Fixed
56
61
  - Projects created in da each have a unique name. https://github.com/SuffolkLITLab/ALKiln/issues/663
62
+ - Shorten path names to try to accommodate limitations of windows systems while still keeping enough useful information to help devs identify the test outputs. https://github.com/SuffolkLITLab/ALKiln/issues/618
63
+ - Updated field decoding to handle new object field encoding. See [#711](https://github.com/SuffolkLITLab/ALKiln/issues/711)
64
+ - Allows ALKilnInThePlayground to upload files. See https://github.com/SuffolkLITLab/docassemble-ALKilnInThePlayground/issues/18.
65
+ - Conform upload file behavior to that of other Story Table rows - avoid erroring when field isn't set properly unless using all variables is required.
57
66
 
58
- ## [4.11.2] - 2023-03-22
59
67
  ### Security
60
68
  - Pass docassemble API keys through HTTP headers instead of as parameters.
61
- - ACTION: all users should delete any uWSGI logs that show their API keys.
62
69
  - Parameters to certain HTTP requests are printed directly in docassemble's
63
70
  uWSGI log, leaking API keys to actors with log access on your docassemble
64
- server.
71
+ server
65
72
 
66
73
  ## [4.11.1] - 2023-03-21
67
74
  ### Changed
@@ -599,4 +606,4 @@ Format:
599
606
  - `example.feature` - an example test to get a project started
600
607
  - `github/workflows/run_form_tests.yml` - Automated github workflow to run tests when code is pushed and a manual trigger for testing without needing to push
601
608
  - `.gitignore` - ignores files that are generated by the tests and shouldn't be added to the repo
602
- - `package.json` - keep up-to-date version of this test repository and hold scripts that the automated tests run
609
+ - `package.json` - keep up-to-date version of this test repository and hold scripts that the automated tests run
package/CONTRIBUTING.md CHANGED
@@ -112,6 +112,12 @@ Our tests require the user/developer to have a docassemble server on which they
112
112
 
113
113
  When the developer commits code to GitHub, their account triggers our code, passing along variables that our code needs, like their GitHub secret of the API key for their docassemble server developer account.
114
114
 
115
+ ## Updating dependencies
116
+
117
+ Sometimes you will have to add dependencies to ALKiln. You can do so by adding the dependency in the `package.json` "dependencies" section, specifying an exact version. Then, run `npm install` to update `npm-shrinkwrap.json` to have the new dependency.
118
+
119
+ If you have to update an existing dependency, you can change the version in `package.json`, and run `npm install` to update `npm-shrankwrap.json`.
120
+
115
121
  ## Very general architecture of files and folders
116
122
 
117
123
  An honest look at our current project architecture—some of our files and folders, what they do, and how they interact.
package/action.yml CHANGED
@@ -61,6 +61,7 @@ runs:
61
61
  echo "DOCASSEMBLE_DEVELOPER_API_KEY=${{ inputs.DOCASSEMBLE_DEVELOPER_API_KEY }}" >> $GITHUB_ENV
62
62
  echo "ALKILN_VERSION=${{ inputs.ALKILN_VERSION }}" >> $GITHUB_ENV
63
63
  echo "MAX_SECONDS_FOR_SETUP=${{ inputs.MAX_SECONDS_FOR_SETUP }}" >> $GITHUB_ENV
64
+ echo "_ORIGIN=github" >> $GITHUB_ENV
64
65
  shell: bash
65
66
  - name: "ALKiln: confirm info"
66
67
  run: |
@@ -68,64 +69,36 @@ runs:
68
69
  echo -e "\nALKiln version is $ALKILN_VERSION\nRepo is $REPO_URL\nBranch ref is $BRANCH_PATH\nMAX_SECONDS_FOR_SETUP is $MAX_SECONDS_FOR_SETUP\nManually added languages are $EXTRA_LANGUAGES\n"
69
70
  shell: bash
70
71
 
71
- # This doesn't use an already established package-lock.json and that
72
- # comes with some types of test breaking risks. Same problem as before.
73
- - name: Temporarily overwrite or create package.json
74
- run: |
75
- cat << EOF > "package.json"
76
- {
77
- "scripts": {
78
- "test": "npm run langs_setup && npm run cucumber -- $@",
79
- "cucumber_base": "./node_modules/.bin/cucumber-js --require ./node_modules/@suffolklitlab/alkiln/lib/index.js",
80
- "cucumber": "run_cucumber(){ npm run cucumber_base -- \"$@\" docassemble/*/data/sources/*.feature --retry 1; }; run_cucumber",
81
- "langs": "npm run langs_setup && ./node_modules/.bin/cucumber-js --require ./node_modules/.bin/alkiln-cucumber docassemble/*/data/sources/*_lang*.feature",
82
- "langs_setup": "node_modules/.bin/alkiln-langs 'docassemble/*/data/sources/*.feature'",
83
- "setup": "node_modules/.bin/alkiln-setup",
84
- "takedown": "node_modules/.bin/alkiln-takedown"
85
- },
86
- "dependencies": {
87
- "colors": "1.4.0",
88
- "@cucumber/cucumber": "7.3.2",
89
- "@suffolklitlab/alkiln": "$ALKILN_VERSION"
90
- }
91
- }
92
- EOF
93
- # Keep in sync with the cucumber.js in root
94
- cat << EOF > "cucumber.js"
95
- module.exports = {
96
- default: "--require ./lib/index.js --format progress --format summary:cucumber-report.txt"
97
- }
98
- EOF
99
- shell: bash
100
-
101
72
  # Install node
102
73
  - name: "ALKiln: Install node packages"
103
- uses: actions/setup-node@v1
74
+ uses: actions/setup-node@v3
104
75
  with:
105
- node-version: "17"
106
- - run: npm install
76
+ node-version: "18"
77
+ - name: Install ALKiln directly from npm
78
+ run: |
79
+ npm install -g github:SuffolkLITLab/ALKiln#v5
107
80
  shell: bash
108
81
 
109
82
  # Run tests
110
83
  - name: "ALKiln: Create a Project and pull the package from GitHub"
111
- run: npm run setup
84
+ run: alkiln-setup
112
85
  shell: bash
113
86
  - name: "ALKiln: Run tests"
114
87
  if: ${{ success() }}
115
- run: npm run test -- ${{ github.event.inputs.tags && format('"--tags" "{0}"', github.event.inputs.tags) }}
88
+ run: alkiln-run ${{ github.event.inputs.tags && format('{0}', github.event.inputs.tags) }}
116
89
  shell: bash
117
90
  - run: echo -e "\n\n====ALKiln could not create a project on your server's testing account or pull your package into it. Check the messages above this line.\n\n"
118
91
  if: ${{ failure() }}
119
92
  shell: bash
120
93
  - name: "ALKiln: Delete project from docassemble test account"
121
94
  if: ${{ always() }}
122
- run: npm run takedown
95
+ run: alkiln-takedown
123
96
  shell: bash
124
97
 
125
98
  # Upload artifacts that subscribers can download on the Actions summary page
126
99
  - name: "ALKiln: Upload artifacts folder"
127
100
  if: ${{ always() }}
128
- uses: actions/upload-artifact@v2
101
+ uses: actions/upload-artifact@v3
129
102
  with:
130
103
  name: ${{ env.ARTIFACT_NAME }}
131
104
  path: ./alkiln-*
@@ -27,7 +27,8 @@ da.get_dev_id = async function ( timeout ) {
27
27
  try {
28
28
  return await axios.request( options );
29
29
  } catch (error) {
30
- throw {...error.toJSON(), data: error.response?.data};
30
+ let response = error.response || {data: null}
31
+ throw {...error.toJSON(), data: response.data};
31
32
  }
32
33
  }; // Ends da.get_dev_id()
33
34
 
@@ -48,7 +49,8 @@ da.create_project = async function ( project_name, timeout ) {
48
49
  try {
49
50
  return await axios.request( options );
50
51
  } catch (error) {
51
- throw {...error.toJSON(), data: error.response?.data};
52
+ let response = error.response || {data: null}
53
+ throw {...error.toJSON(), data: response.data};
52
54
  }
53
55
  }; // Ends da.create_project()
54
56
 
@@ -71,7 +73,8 @@ da.pull = async function ( timeout ) {
71
73
  try {
72
74
  return await axios.request( options );
73
75
  } catch (error) {
74
- throw {...error.toJSON(), data: error.response?.data};
76
+ let response = error.response || {data: null}
77
+ throw {...error.toJSON(), data: response.data};
75
78
  }
76
79
  }; // Ends da.pull()
77
80
 
@@ -92,7 +95,8 @@ da.has_task_finished = async function ( task_id, timeout ) {
92
95
  try {
93
96
  return await axios.request( options );
94
97
  } catch (error) {
95
- throw {...error.toJSON(), data: error.response?.data};
98
+ let response = error.response || {data: null}
99
+ throw {...error.toJSON(), data: response.data};
96
100
  }
97
101
  }; // Ends da.has_task_finished()
98
102
 
@@ -113,7 +117,8 @@ da.delete_project = async function ( timeout ) {
113
117
  try {
114
118
  return await axios.request( options );
115
119
  } catch (error) {
116
- throw {...error.toJSON(), data: error.response?.data};
120
+ let response = error.response || {data: null}
121
+ throw {...error.toJSON(), data: response.data};
117
122
  }
118
123
  }; // Ends da.delete_project()
119
124
 
@@ -142,7 +147,8 @@ da.__delete_projects_starting_with = async function ( base_name, starting_num=1,
142
147
 
143
148
  await axios.request( options );
144
149
  } catch ( error ) {
145
- console.log( {...error.toJSON(), data: error.response?.data});
150
+ let response = error.response || {data: null}
151
+ console.log( {...error.toJSON(), data: response.data});
146
152
  }
147
153
  name_incrementor++;
148
154
  }
@@ -122,9 +122,15 @@ da_i.throw_an_error_if_server_is_not_responding = async function ( options ) {
122
122
 
123
123
  // node -e 'require("./lib/docassemble/docassemble_api_interface.js").is_server_responding()'
124
124
  da_i.is_server_responding = async function ( dev_id_options ) {
125
- /** Use _da_REST.get_dev_id() to test if server is up.
125
+ /** For non-playground interviews, use _da_REST.get_dev_id() to
126
+ * return if server is up. Otherwise, return true.
126
127
  * See https://docassemble.org/docs/api.html#user. */
127
128
 
129
+ // Playground interview will itself timeout. No way to detect that.
130
+ if ( session_vars.get_origin() === 'playground' ) {
131
+ return true;
132
+ }
133
+
128
134
  // Default timeouts
129
135
  let { timeout } = dev_id_options || { timeout: DEFAULT_MAX_REQUEST_MS };
130
136
  try {
@@ -141,13 +147,28 @@ da_i.is_server_responding = async function ( dev_id_options ) {
141
147
 
142
148
  // node -e 'require("./lib/docassemble/docassemble_api_interface.js").get_dev_id()'
143
149
  da_i.get_dev_id = async function ( dev_id_options ) {
144
- /** For consistency, wrap _da_REST.get_dev_id().
145
- * See https://docassemble.org/docs/api.html#user. */
150
+ /** Get user id, either from the server or from env vars (for Playground runs).
151
+ * See https://docassemble.org/docs/api.html#user.
152
+ *
153
+ * @param dev_id_options {obj} Options for getting dev_id
154
+ * @param dev_id_options.timeout {int} Required if options is defined. Max MS
155
+ * to allow for server request.
156
+ */
146
157
 
147
- // Default timeouts
148
- let { timeout } = dev_id_options || { timeout: DEFAULT_MAX_REQUEST_MS };
149
- let response = await _da_REST.get_dev_id( timeout );
150
- return response.data.id;
158
+ let dev_id = null;
159
+
160
+ // For tests running in the dev Playground, use the appropriate env var
161
+ if ( session_vars.get_origin() === 'playground' ) {
162
+ dev_id = session_vars.get_user_id();
163
+
164
+ } else {
165
+ // Default timeouts
166
+ let { timeout } = dev_id_options || { timeout: DEFAULT_MAX_REQUEST_MS };
167
+ let response = await _da_REST.get_dev_id( timeout );
168
+ dev_id = response.data.id;
169
+ }
170
+
171
+ return dev_id;
151
172
  }; // Ends da_i.get_dev_id();
152
173
 
153
174
 
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const log = require('./utils/log');
5
+ const session_vars = require('./utils/session_vars');
6
+
7
+ const cucumber_api = require('@cucumber/cucumber/api');
8
+
9
+ (async function main() {
10
+ let argv = process.argv;
11
+
12
+ const environment = { cwd: process.cwd() };
13
+ console.log("alkiln-run: environment: %o", environment);
14
+ const provided_config = {
15
+ "publishQuiet": true,
16
+ "require": "./lib/index.js",
17
+ "format": ["progress", "summary:cucumber-report.txt"],
18
+ "paths": ["docassemble/*/data/sources/*.feature"],
19
+ "retry": 1,
20
+ }
21
+
22
+
23
+ // If they're running it from an interview on their server instead of from GitHub
24
+ if ( session_vars.get_origin() === `playground` ) {
25
+ provided_config.paths.push(`/usr/share/docassemble/files/playgroundsources/${session_vars.get_user_id()}/${session_vars.get_user_project_name()}/*.feature`);
26
+ // For S3
27
+ provided_config.paths.push(`/tmp/playgroundsources/${session_vars.get_user_id()}/${session_vars.get_user_project_name()}/*.feature`);
28
+ }
29
+
30
+ let tags = argv.slice(2);
31
+ if ( session_vars.get_origin() === `playground` ) {
32
+ tags = session_vars.get_tags();
33
+ }
34
+
35
+ if (tags.length > 0) {
36
+ // Cucumber expects tags in boolean expressions, like (@a0 or @a1) and @random.
37
+ // If we get a list of only tags, then "or" them all together
38
+ if (tags.every((val) => val.startsWith("@"))) {
39
+ provided_config.tags = tags.join(' or ');
40
+ }
41
+ // If we get a list of seemingly no tags, assume they meant to use tags
42
+ else if (tags.every((val) => !val.startsWith("@"))) {
43
+ provided_config.tags = tags.map((val) => "@" + val).join(' or ');
44
+ }
45
+ // If it's a mix of tags and no tags, it's probably a boolean expression!
46
+ else {
47
+ provided_config.tags = tags.join(' ');
48
+ }
49
+ }
50
+
51
+ const { runConfiguration } = await cucumber_api.loadConfiguration({
52
+ provided: provided_config
53
+ }, environment);
54
+ console.log("alkiln-run: runConfiguration: %o", runConfiguration);
55
+ var path = require('path');
56
+ var codeDir = path.dirname(require.main.filename);
57
+ const support = await cucumber_api.loadSupport({ support: {
58
+ requireModules: [`${ codeDir }/index.js`],
59
+ requirePaths: [ `${ codeDir }/index.js`],
60
+ importPaths: [],
61
+ }, sources: {paths: []}}, environment);
62
+
63
+ console.log("alkiln-run: working directory: %o", codeDir);
64
+ console.log(`\n\n`);
65
+
66
+ const { success } = await cucumber_api.runCucumber({...runConfiguration, support});
67
+ console.log("alkiln-run: success: %b", success);
68
+ const exitCode = success ? 0 : 1;
69
+ process.exitCode = exitCode;
70
+
71
+ // This is hardcoded information from `provide_config` above.
72
+ // This code isn't used for anything other than detecting and removing color codes.
73
+ let summary_file_name = 'cucumber-report.txt';
74
+ fs.readFile(summary_file_name, 'utf8', (err, data) => {
75
+ if (err) {
76
+ console.error(err);
77
+ return;
78
+ }
79
+
80
+ // Replace terminal color codes, if present
81
+ // https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#colors--graphics-mode
82
+ data = data.replace(/\x1b\[[0-9][0-9]?[0-9]?m/g, '');
83
+
84
+ // Put it in the correct file in the correct folder
85
+ let artifacts_path = session_vars.get_artifacts_path_name();
86
+ fs.appendFileSync( `${ artifacts_path}/${ log.debug_log_file }`, data);
87
+ });
88
+ })();