@suffolklitlab/alkiln 5.14.0 → 5.15.0-deps-2

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.
Files changed (37) hide show
  1. package/.github/workflows/github_server.yml +1 -1
  2. package/.github/workflows/playground.yml +2 -1
  3. package/CHANGELOG.md +29 -0
  4. package/action.yml +26 -10
  5. package/action_for_github_server/action.yml +31 -27
  6. package/docs/4_environments.md +2 -2
  7. package/docs/artifacts_folder_name.md +121 -71
  8. package/lib/docassemble/server_install.js +0 -2
  9. package/lib/docassemble/setup.js +1 -3
  10. package/lib/docassemble/takedown.js +2 -2
  11. package/lib/globals.js +10 -0
  12. package/lib/run_cucumber.js +40 -53
  13. package/lib/scope.js +32 -0
  14. package/lib/setup/TestGenerator.js +1757 -0
  15. package/lib/setup/artifacts.js +20 -0
  16. package/lib/setup/generate.js +42 -0
  17. package/lib/setup/get_Gherkin_AST.js +26 -0
  18. package/lib/setup/validate.js +89 -0
  19. package/lib/steps.js +53 -19
  20. package/lib/utils/Log.js +302 -149
  21. package/lib/utils/get_error_stacks.js +16 -0
  22. package/lib/utils/pdf_reader.js +9 -2
  23. package/lib/utils/reports.js +43 -23
  24. package/lib/utils/session_vars.js +77 -57
  25. package/lib/utils/set_sources_paths.js +98 -0
  26. package/npm-shrinkwrap.json +739 -924
  27. package/package.json +17 -10
  28. package/tests/log_codes/check_codes.sh +17 -13
  29. package/tests/log_codes/log_code_expected_instances.txt +58 -0
  30. package/tests/unit_tests/constrained_random_answers/invalid.fixtures.js +178 -0
  31. package/tests/unit_tests/constrained_random_answers/invalid.test.js +251 -0
  32. package/tests/unit_tests/constrained_random_answers/valid.fixtures.js +957 -0
  33. package/tests/unit_tests/constrained_random_answers/valid.test.js +563 -0
  34. package/tests/unit_tests/log.test.js +17 -41
  35. package/_alkiln_meta/gherkin_parsed_example.json +0 -1546
  36. package/_alkiln_meta/shift_logs.js +0 -75
  37. /package/docs/{expected_inernal_results.md → expected_internal_results.md} +0 -0
@@ -160,7 +160,7 @@ jobs:
160
160
  #### Developer note: You can probably leave the rest out
161
161
  #### To learn more, see https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#optional-inputs
162
162
  ALKILN_TAG_EXPRESSION: "${{ env.ALKILN_TAG_EXPRESSION }}"
163
- # ALKILN_VERSION: "5.13.4-feat-textarea-1"
163
+ # ALKILN_VERSION:
164
164
 
165
165
  #### Developer note: Example of making an issue when tests fail
166
166
  #### that includes the text of the failure output file
@@ -76,9 +76,10 @@ jobs:
76
76
  DOCASSEMBLE_DEVELOPER_API_KEY: "${{ env.DOCASSEMBLE_DEVELOPER_API_KEY }}"
77
77
  #### Developer note: See https://assemblyline.suffolklitlab.org/docs/alkiln/writing/#optional-inputs
78
78
  #### You can probably leave this out
79
+ ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO: 10
79
80
  # Internal: docassemble changes sometimes break @a11y tests. That is
80
81
  # a da problem, not ours. We will trigger these tests manually when we
81
82
  # want to check up on this.
82
83
  ALKILN_TAG_EXPRESSION: "${{ env.ALKILN_TAG_EXPRESSION }}"
83
84
  #### Developer note: You can probably leave this out
84
- # ALKILN_VERSION: "5.13.4-feat-textarea-1"
85
+ # ALKILN_VERSION:
package/CHANGELOG.md CHANGED
@@ -45,6 +45,35 @@ Format:
45
45
 
46
46
  <!-- ## [Unreleased] -->
47
47
 
48
+ ## [5.15.0] - 2025-05-22
49
+
50
+ ### Added
51
+
52
+ - Add the `constrained random answers` Step. You must put the Step in a "constrained random test template" Scenario which goes in a "constrained random test template" file - a `.feature` file that starts with "alkiln_random". The file **MUST have ONLY 1 Scenario per template file** at the moment. The Step is pretty strict. If there are irregularities, it will probably fail, but it will fail quickly. It is flexible about number of tests, though, and will default to 1. Closes [#962](https://github.com/SuffolkLITLab/ALKiln/issues/962).
53
+ - Add `ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO` optional environment variable for the above `constrained random answers` Step. Default value is `40` until we hear otherwise.
54
+ - Regular tests that have incorrect syntax will fail more quickly now - very near the start. So will invalid "constrained random test template" files. This will be a little slower for GitHub Sandbox tests right now, but still faster than it has been in the past. Closes [#972](https://github.com/SuffolkLITLab/ALKiln/issues/972).
55
+
56
+ ### Changed
57
+
58
+ - Improve report indentation and tweak styling.
59
+ - Clarify some logs, including addressing bite-sized issues like [#981](https://github.com/SuffolkLITLab/ALKiln/issues/981).
60
+ - The report now shows the name of every Step that gets run in a test.
61
+
62
+ ### Internal
63
+
64
+ - Added: `lib/globals.js` file to hold some shared constant values across the framework. It should NOT manage state. We may want to change the name to `constants.js` or `global_contants.js`. Let's see how it serves us.
65
+ - Added: executable scripts for more setup steps - managing the artifacts path (at the start of a run) and validating and generating files.
66
+ - Changed: `Log` now prioritizes what folder it stores files in in this order:
67
+ 1. Use the argument to use an existing folder and save that to runtime_config.json at root.
68
+ 2. Use the argument to make a new folder with that name and save that to runtime_config.json at root.
69
+ 3. Use the alread-existing folder name value in runtime_config.json at root
70
+ 4. Create a new folder and save that to runtime_config.json at root
71
+ - Changed: Add `.error()` to `Log` for visual clarity when storing an error to throw later. We need to discuss this behavior and its return value. To make that work Logs can now get the `error` prop without throwing an error.
72
+ - Changed: the Story Table step now accepts multiple ids and stops at whatever id it reaches first. I highly recommend that only ALKiln generated tests use this feature. We may avoid documenting it unless authors ask for it.
73
+ - Changed: `.gitignore` and `.npmignore` more things
74
+ - Fixed: log codes checker obob.
75
+ - Fixed: updated `actions/upload-artifact@v3` to `actions/upload-artifact@v4`
76
+
48
77
  ## [5.14.0] - 2025-05-15
49
78
 
50
79
  ### Added
package/action.yml CHANGED
@@ -33,6 +33,10 @@ inputs:
33
33
  description: "The version of docassemblecli to install."
34
34
  required: false
35
35
  default: "0.0.17"
36
+ ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO:
37
+ description: "The maximum number of tests ALKiln will generate for every Scenario that can generate tests."
38
+ required: false
39
+ # Default will be internal to avoid duplication of data
36
40
 
37
41
  outputs:
38
42
  PATH_TO_ARTIFACTS:
@@ -68,6 +72,7 @@ runs:
68
72
  MAX_SECONDS_FOR_SETUP: ${{ inputs.MAX_SECONDS_FOR_SETUP }}
69
73
  SERVER_RELOAD_TIMEOUT_SECONDS: ${{ inputs.SERVER_RELOAD_TIMEOUT_SECONDS }}
70
74
  DOCASSEMBLECLI_VERSION: ${{ inputs.DOCASSEMBLECLI_VERSION }}
75
+ ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO: ${{ inputs.ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO }}
71
76
  shell: bash
72
77
  run: |
73
78
  log="💡 ALK0023 INFO: Set environment variables and create artifacts folder"
@@ -91,6 +96,7 @@ runs:
91
96
  echo "DOCASSEMBLE_DEVELOPER_API_KEY=$DOCASSEMBLE_DEVELOPER_API_KEY" >> $GITHUB_ENV
92
97
  echo "ALKILN_VERSION=$ALKILN_VERSION" >> $GITHUB_ENV
93
98
  echo "MAX_SECONDS_FOR_SETUP=$MAX_SECONDS_FOR_SETUP" >> $GITHUB_ENV
99
+ echo "ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO=$ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO" >> $GITHUB_ENV
94
100
  echo "SERVER_RELOAD_TIMEOUT_SECONDS=$SERVER_RELOAD_TIMEOUT_SECONDS" >> $GITHUB_ENV
95
101
  echo "DOCASSEMBLECLI_VERSION=$DOCASSEMBLECLI_VERSION" >> $GITHUB_ENV
96
102
  # Hard-coded internal ALKiln vars
@@ -100,10 +106,10 @@ runs:
100
106
  run: |
101
107
  log="💡 ALK0024 INFO: Confirm environment variables"
102
108
  echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
103
- vars_log="\nALKiln version is $ALKILN_VERSION\nRepo is $REPO_URL\nBranch ref is $BRANCH_PATH\nMAX_SECONDS_FOR_SETUP is $MAX_SECONDS_FOR_SETUP\nSERVER_RELOAD_TIMEOUT_SECONDS is $SERVER_RELOAD_TIMEOUT_SECONDS\n"
109
+ vars_log='\nALKiln version is ${{ env.ALKILN_VERSION }}\nRepo is "${{ env.REPO_URL }}"\nBranch ref is "${{ env.BRANCH_PATH }}"\nCustom MAX_SECONDS_FOR_SETUP is "${{ env.MAX_SECONDS_FOR_SETUP }}"\nCustom SERVER_RELOAD_TIMEOUT_SECONDS is "${{ env.SERVER_RELOAD_TIMEOUT_SECONDS }}"\nCustom ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO is "${{ env.ALKILN_MAX_RANDOM_TESTS_PER_SCENARIO }}"\n'
104
110
  echo -e "$vars_log" >> "${{ env.DEBUG_PATH }}" && echo -e "$vars_log"
105
111
 
106
- # Install
112
+ # Install ALKiln during GitHub workflow
107
113
  - name: "💡 ALK0025 INFO: Set up node"
108
114
  uses: actions/setup-node@v4
109
115
  with:
@@ -115,8 +121,18 @@ runs:
115
121
  echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
116
122
  npm install -g "@suffolklitlab/alkiln@$ALKILN_VERSION"
117
123
 
118
- # Install on playground
124
+ # Files prep
125
+ - shell: bash
126
+ env:
127
+ ARTIFACT_FOLDER: ${{ env.ARTIFACT_FOLDER }}
128
+ run: |
129
+ log="💡 ALK0275 INFO: Prepare repository test files"
130
+ echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
131
+ alkiln-artifacts --path="${{ env.ARTIFACT_FOLDER }}"
132
+ alkiln-validate
133
+ alkiln-generate
119
134
 
135
+ # Install package on playground
120
136
  # Don't rely on the environment's version of python
121
137
  - uses: actions/setup-python@v5
122
138
  if: ${{ inputs.INSTALL_METHOD == 'playground' }}
@@ -129,7 +145,7 @@ runs:
129
145
  log="💡 ALK0027 INFO: Create a Project and install the package from GitHub"
130
146
  echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
131
147
  pip install "docassemblecli==$DOCASSEMBLECLI_VERSION"
132
- alkiln-setup --path="${{ env.ARTIFACT_FOLDER }}"
148
+ alkiln-setup
133
149
  - name: "🤕 ALK0028 ERROR: Unable to create a Project"
134
150
  if: ${{ inputs.INSTALL_METHOD == 'playground' && failure() }}
135
151
  shell: bash
@@ -138,15 +154,15 @@ runs:
138
154
  long_log="\n\n―――\n🤕 ALK0028 ERROR: Unable to create a Project on your server's testing account or pull your package into it. Check the messages above this line.\n\n"
139
155
  echo -e "$long_log" >> "${{ env.DEBUG_PATH }}" && echo -e "$long_log"
140
156
 
141
- # Server installations - find folders and save session vars
142
- - name: "💡 ALK0029 INFO: Install the GitHub package onto the server"
157
+ # Server installation
158
+ - name: "💡 ALK0029 INFO: Try to install the GitHub package onto the GitHub sandbox server"
143
159
  if: ${{ inputs.INSTALL_METHOD == 'server' }}
144
160
  shell: bash
145
161
  run: |
146
162
  log="💡 ALK0029 INFO: Install the GitHub package onto the server"
147
163
  echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
148
- alkiln-server-install --path="${{ env.ARTIFACT_FOLDER }}"
149
- - name: "🤕 ALK0030 ERROR: Unable to install the package"
164
+ alkiln-server-install
165
+ - name: "🤕 ALK0030 ERROR: Unable to install the package on the GitHub sandbox server"
150
166
  if: ${{ inputs.INSTALL_METHOD == 'server' && failure() }}
151
167
  shell: bash
152
168
  run: |
@@ -162,7 +178,7 @@ runs:
162
178
  run: |
163
179
  log="💡 ALK0031 INFO: Run tests"
164
180
  echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
165
- alkiln-run "$ALKILN_TAG_EXPRESSION" --path="${{ env.ARTIFACT_FOLDER }}"
181
+ alkiln-run "$ALKILN_TAG_EXPRESSION"
166
182
 
167
183
  # on playground, delete project
168
184
  - name: "💡 ALK0032 INFO: Delete the Project from the Playground"
@@ -171,7 +187,7 @@ runs:
171
187
  run: |
172
188
  log="💡 ALK0032 INFO: Delete the Project from the Playground"
173
189
  echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
174
- alkiln-takedown --path="${{ env.ARTIFACT_FOLDER }}"
190
+ alkiln-takedown
175
191
 
176
192
  # Upload artifacts that subscribers can download on the Actions summary page
177
193
  - name: "💡 ALK0033 INFO: Upload artifacts folder"
@@ -51,15 +51,19 @@ runs:
51
51
  run: |
52
52
  log="💡 ALK0018 INFO: Get path names with date and time"
53
53
  timestamp="$(date +'%Y-%m-%d at %Hh%Mm%Ss' -u)"
54
+ # Where to get the contents for the artifact
54
55
  debug_dir="/tmp"
55
- debug_path="$debug_dir/alkiln_docker_logs-${timestamp}UTC.txt"
56
+ debug_logs_path="$debug_dir/alkiln_docker_logs-${timestamp}UTC.txt"
57
+ # Where to put the artifact
56
58
  artifact_folder="alkiln_github_server-${timestamp}UTC"
59
+ echo "debug_logs_path: $debug_logs_path"
60
+ echo "artifact_folder: $artifact_folder"
57
61
 
58
62
  mkdir -p "$debug_dir"
59
63
  mkdir -p "$artifact_folder"
60
- echo -e "$log" >> "$debug_path"
64
+ echo -e "$log" >> "$debug_logs_path"
61
65
 
62
- echo "DEBUG_PATH=$debug_path" >> $GITHUB_ENV
66
+ echo "DEBUG_LOGS_PATH=$debug_logs_path" >> $GITHUB_ENV
63
67
  echo "GITHUB_SERVER_ARTIFACT_NAME=$artifact_folder" >> $GITHUB_ENV
64
68
 
65
69
  - shell: bash
@@ -68,7 +72,7 @@ runs:
68
72
  DOCASSEMBLECLI_VERSION: ${{ inputs.DOCASSEMBLECLI_VERSION }}
69
73
  run: |
70
74
  log="💡 ALK0001 INFO: Set environment variables"
71
- echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
75
+ echo -e "\n$log" >> "${{ env.DEBUG_LOGS_PATH }}"
72
76
 
73
77
  echo "MAX_SECONDS_FOR_DOCKER=$MAX_SECONDS_FOR_DOCKER" >> $GITHUB_ENV
74
78
  echo "DOCASSEMBLECLI_VERSION=$DOCASSEMBLECLI_VERSION" >> $GITHUB_ENV
@@ -81,7 +85,7 @@ runs:
81
85
  shell: bash
82
86
  run: |
83
87
  log="💡 ALK0002 INFO: Create GitHub step output variables"
84
- echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
88
+ echo -e "\n$log" >> "${{ env.DEBUG_LOGS_PATH }}"
85
89
  echo "DOCASSEMBLE_DEVELOPER_API_KEY=$DA_ADMIN_API_KEY" >> "$GITHUB_OUTPUT"
86
90
  echo "DA_ADMIN_EMAIL=$DA_ADMIN_EMAIL" >> "$GITHUB_OUTPUT"
87
91
  echo "DA_ADMIN_PASSWORD=$DA_ADMIN_PASSWORD" >> "$GITHUB_OUTPUT"
@@ -92,19 +96,19 @@ runs:
92
96
  shell: bash
93
97
  run: |
94
98
  log="💡 ALK0003 INFO: Get config"
95
- echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
99
+ echo -e "\n$log" >> "${{ env.DEBUG_LOGS_PATH }}"
96
100
 
97
101
  mkdir /tmp/config
98
102
  # Worth making this silent by defining a variable with > /dev/null...?
99
103
  if [ -n "$CONFIG" ]
100
104
  then
101
105
  log2="💡 ALK0004 INFO: The developer did provide a custom docassemble config file as an input into this action."
102
- echo -e "\n$log2" >> "${{ env.DEBUG_PATH }}" echo "$log2"
106
+ echo -e "\n$log2" >> "${{ env.DEBUG_LOGS_PATH }}" echo "$log2"
103
107
  echo "$CONFIG" > /tmp/config/myconfig.yml
104
108
  echo "CONFIG_ARGS=--env DA_CONFIG=/tmp/config/myconfig.yml --volume /tmp/config:/tmp/config " >> $GITHUB_ENV
105
109
  else
106
110
  log3="💡 ALK0005 INFO: The developer did NOT provide a custom docassemble config file as an input into this action. Docassemble will use its default config."
107
- echo -e "\n$log3" >> "${{ env.DEBUG_PATH }}" echo "$log3"
111
+ echo -e "\n$log3" >> "${{ env.DEBUG_LOGS_PATH }}" echo "$log3"
108
112
  echo "CONFIG_ARGS=" >> $GITHUB_ENV
109
113
  fi
110
114
 
@@ -120,13 +124,13 @@ runs:
120
124
  shell: bash
121
125
  run: |
122
126
  log="💡 ALK0006 INFO: Determine docker logs visibility"
123
- echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
127
+ echo -e "\n$log" >> "${{ env.DEBUG_LOGS_PATH }}"
124
128
  if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
125
129
  echo "OUTPUT_DOCKER=$SHOW_DOCKER_OUTPUT" >> $GITHUB_ENV
126
- echo -e "\n$SHOW_DOCKER_OUTPUT" >> "${{ env.DEBUG_PATH }}"
130
+ echo -e "\n$SHOW_DOCKER_OUTPUT" >> "${{ env.DEBUG_LOGS_PATH }}"
127
131
  else
128
132
  echo "OUTPUT_DOCKER=false" >> $GITHUB_ENV
129
- echo -e "\nfalse" >> "${{ env.DEBUG_PATH }}"
133
+ echo -e "\nfalse" >> "${{ env.DEBUG_LOGS_PATH }}"
130
134
  fi
131
135
 
132
136
  # Messages about output
@@ -136,14 +140,14 @@ runs:
136
140
  run: |
137
141
  # 💡 ALK0007 INFO: ALKiln will now hide docker output
138
142
  log="===\n💡 ALK0007 INFO: ALKiln will now hide docker output to avoid possibly showing details about your config. If you want to get output to see more of what is going on, use \"with:\" and set the input \"SHOW_DOCKER_OUTPUT\" to \"true\". This output will only be visible to those who can already see the action output, like people with admin or write permissions.\n==="
139
- echo -e "\n$log" >> "${{ env.DEBUG_PATH }}" && echo -e "$log"
143
+ echo -e "\n$log" >> "${{ env.DEBUG_LOGS_PATH }}" && echo -e "$log"
140
144
  - name: "💡 ALK0008 INFO: ALKiln will show docker output"
141
145
  if: ${{ env.OUTPUT_DOCKER == 'true' }}
142
146
  shell: bash
143
147
  run: |
144
148
  # 💡 ALK0008 INFO: ALKiln will show docker output
145
149
  log="===\n💡 ALK0008 INFO: ALKiln will show docker output. ALKiln cannot control this output. If you want to prevent output, use \"with:\" and set the input \"SHOW_DOCKER_OUTPUT\" to \"false\". This output will only be visible to those who can already see the action output, like people with admin or write permissions.\n==="
146
- echo -e "\n$log" >> "${{ env.DEBUG_PATH }}" && echo -e "$log"
150
+ echo -e "\n$log" >> "${{ env.DEBUG_LOGS_PATH }}" && echo -e "$log"
147
151
 
148
152
  # TODO: Reduce these to 1 block by putting ` > /dev/null 2>&1` into an env var
149
153
  # No docker output
@@ -154,7 +158,7 @@ runs:
154
158
  shell: bash
155
159
  run: |
156
160
  log="💡 ALK0009 INFO: Download and start docker silently"
157
- echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
161
+ echo -e "\n$log" >> "${{ env.DEBUG_LOGS_PATH }}"
158
162
  docker pull jhpyle/docassemble > /dev/null 2>&1
159
163
  docker run --name docassemble_container \
160
164
  --env DA_ADMIN_EMAIL="$DA_ADMIN_EMAIL" \
@@ -171,7 +175,7 @@ runs:
171
175
  shell: bash
172
176
  run: |
173
177
  log="💡 ALK0010 INFO: Download and start docker"
174
- echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
178
+ echo -e "\n$log" >> "${{ env.DEBUG_LOGS_PATH }}"
175
179
  docker pull jhpyle/docassemble
176
180
  docker run --name docassemble_container \
177
181
  --env DA_ADMIN_EMAIL="$DA_ADMIN_EMAIL" \
@@ -189,13 +193,13 @@ runs:
189
193
  run: |
190
194
  # 💡 ALK0011 INFO: The following messages are not docker output
191
195
  log="💡 ALK0011 INFO: The following messages are NOT docker output, just ALKiln waiting for the server to start"
192
- echo -e "\n$log" >> "${{ env.DEBUG_PATH }}" && echo -e "$log"
196
+ echo -e "\n$log" >> "${{ env.DEBUG_LOGS_PATH }}" && echo -e "$log"
193
197
 
194
198
  - name: "💡 ALK0012 INFO: Waiting for server to start"
195
199
  shell: bash
196
200
  run: |
197
201
  log="💡 ALK0012 INFO: Waiting for server to start"
198
- echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
202
+ echo -e "\n$log" >> "${{ env.DEBUG_LOGS_PATH }}"
199
203
 
200
204
  # Reset the SECONDS variable
201
205
  SECONDS=0
@@ -205,27 +209,27 @@ runs:
205
209
  response="start"
206
210
  while [[ $response != *"200"* ]]; do
207
211
  log2="💡 ALK0013 INFO: Time elapsed: $SECONDS seconds"
208
- echo -e "\n$log2" >> "${{ env.DEBUG_PATH }}" && echo -e "$log2"
212
+ echo -e "\n$log2" >> "${{ env.DEBUG_LOGS_PATH }}" && echo -e "$log2"
209
213
 
210
214
  # Check if max seconds till loading has passed
211
215
  if [[ $SECONDS -ge $MAX_SECONDS_FOR_DOCKER ]]; then
212
216
  log3="🤕 ALK0014 ERROR: Timed out waiting for docker container to serve the site. If you want to give your docker container more timem to install, set the MAX_SECONDS_FOR_DOCKER input for this action."
213
- echo -e "\n$log3" >> "${{ env.DEBUG_PATH }}" && echo -e "$log3"
217
+ echo -e "\n$log3" >> "${{ env.DEBUG_LOGS_PATH }}" && echo -e "$log3"
214
218
  exit 1
215
219
  fi
216
220
 
217
221
  # Set the variable to a new string value in each iteration
218
222
  response=$(curl -o /dev/null -s -w "%{http_code}\n" http://localhost:80/health_check?ready=1)
219
223
  log4="💡 ALK0015 INFO: Response is $response"
220
- echo -e "\n$log4" >> "${{ env.DEBUG_PATH }}" && echo -e "$log4"
224
+ echo -e "\n$log4" >> "${{ env.DEBUG_LOGS_PATH }}" && echo -e "$log4"
221
225
 
222
226
  # Check if the string includes the desired text
223
227
  if [[ $response == *"200"* ]]; then
224
228
  log5="💡 ALK0016 SUCCESS: Success! The docker container is ready!"
225
- echo -e "\n$log5" >> "${{ env.DEBUG_PATH }}" && echo -e "$log5"
229
+ echo -e "\n$log5" >> "${{ env.DEBUG_LOGS_PATH }}" && echo -e "$log5"
226
230
  else
227
231
  log6="💡 ALK0017 INFO: The docker container is not ready yet. Will check again in 30 seconds."
228
- echo -e "\n$log6" >> "${{ env.DEBUG_PATH }}" && echo -e "$log6"
232
+ echo -e "\n$log6" >> "${{ env.DEBUG_LOGS_PATH }}" && echo -e "$log6"
229
233
  sleep 30
230
234
  fi
231
235
 
@@ -260,23 +264,23 @@ runs:
260
264
  shell: bash
261
265
  run: |
262
266
  log="💡 ALK0019 INFO: Create docker artifact data"
263
- echo -e "\n$log" >> "${{ env.DEBUG_PATH }}"
264
- echo "$(docker output docassemble_container)" >> "${{ env.DEBUG_PATH }}"
267
+ echo -e "\n$log" >> "${{ env.DEBUG_LOGS_PATH }}"
268
+ echo "$(docker output docassemble_container)" >> "${{ env.DEBUG_LOGS_PATH }}"
265
269
  - name: "💡 ALK0020 INFO: Upload artifacts folder"
266
270
  if: ${{ always() && env.OUTPUT_DOCKER == 'true' }}
267
271
  uses: actions/upload-artifact@v4
268
272
  with:
269
273
  name: ${{ env.GITHUB_SERVER_ARTIFACT_NAME }}
270
- path: ${{ env.DEBUG_PATH }}
274
+ path: ${{ env.DEBUG_LOGS_PATH }}
271
275
 
272
276
  - shell: bash
273
277
  if: ${{ success() }}
274
278
  run: |
275
279
  log="💡 ALK0021 SUCCESS: ALKiln created the docker container and started the server!"
276
- echo -e "\n$log" >> "${{ env.DEBUG_PATH }}" && echo -e "$log"
280
+ echo -e "\n$log" >> "${{ env.DEBUG_LOGS_PATH }}" && echo -e "$log"
277
281
 
278
282
  - shell: bash
279
283
  if: ${{ failure() }}
280
284
  run: |
281
285
  log="🤕 ALK0022 ERROR: Something went wrong. See above for more details."
282
- echo -e "\n$log" >> "${{ env.DEBUG_PATH }}" && echo -e "$log"
286
+ echo -e "\n$log" >> "${{ env.DEBUG_LOGS_PATH }}" && echo -e "$log"
@@ -223,7 +223,7 @@ This design is working within systems that limit how we can do what we need to d
223
223
 
224
224
  Alternative: Get rid of our support for some of these environments. The temporary GitHub docassemble server environment hasn't been used by a lot of authors. Other than that, the other environments have gotten a lot of use. Even though authors have not yet used the temporary GitHub environment much, they say they want that functionality. The trouble there seems to be complexity with initial set up.
225
225
 
226
- Alternative: Instead of dealing with separate runtimes, have one command and script that wraps all these currently separate processes in one runtime and handles which ones to trigger under what circumstances. If we included `./action_for_github/action.yml` in that command, we would prevent authors from customizing the temporary GitHub docassemble server. That would not be acceptable. To avoid closing off access to server customization, we can only partially integrate these different processes. Also, GitHub actions in general will still have to deal with some core business sometimes. For example, they have to create the artifacts folder name so they can use it later to upload the artifacts. This combined runtime also feels more coupled/entangled and therefore harder to maintain. The need for more command line arguments could make local development more complicated. It is still worth considering.
226
+ Alternative: Instead of dealing with separate runtimes, have one command and script that wraps all these currently separate processes in one runtime and handles which ones to trigger under what circumstances. If we included `./action_for_github/action.yml` in that command, we would prevent authors from customizing the temporary GitHub docassemble server. That would not be acceptable. To avoid closing off access to server customization, we can only partially integrate these different processes. Also, GitHub actions in general will still sometimes have to deal with some core business. For example, they have to create the artifacts folder name so they can use it later to upload the artifacts. This combined runtime also feels more coupled/entangled and therefore harder to maintain. The need for more command line arguments could make local development more complicated. It is still worth considering.
227
227
 
228
228
  <!-- Discuss: How to articulate the entanglement with more specifics and examples. -->
229
229
 
@@ -234,7 +234,7 @@ Alternative script names: `install_package`, `save_server`, `delete_package`.
234
234
  _Security, privacy, observability, etc._
235
235
 
236
236
  - Some tests need to use sensitive information. For example, some tests need a logged-in user and thus ALKiln needs the login info for a user. Different environments store this information differently and there is documentation about how to use sensitive information securely and privately.
237
- - Core ALKiln code[^2] ends up needing to handle some of the complexity of the 4 environments. Example - the `Log` class `path` takes an optional initial argument to set the artifacts path at the beginning of that runtime process. Other parts of the process have to assume that this path already exists. We have tried to abstract environment complexity out to `run_cucumber.js`, the script that wraps the core code, but there is still logic that the core code handles.
237
+ - Core ALKiln code[^2] ends up needing to handle some of the complexity of the 4 environments. Example - the `Log` class `path` takes an optional initial argument to set the artifacts path before the core code runs. The process in the core code (and elsewhere) have to assume that this path already exists and use config values. We have tried to abstract environment complexity out to `run_cucumber.js`, the script that wraps the core code, but there is still logic that the core code handles.
238
238
 
239
239
  ---
240
240
 
@@ -21,115 +21,165 @@ Our 4 environments can be condensed into 3 environments for the purpose of manag
21
21
  - ALKilnInThePlayground
22
22
  - The command line for internal development
23
23
 
24
- The GitHub action creates an artifact folder name and sends it to various scripts that use an instance of the `Log` class to create the folder and save the name. In other environments, an instance of the `Log` class both creates the name, creates the folder, and saves the name. The instance of the `Log` saves the name in `runtime_config.json`. That instance of `Log` and other ALKiln code uses that name to create and store files in that artifacts folder.
24
+ Every environment runs npm commands. Those commands are sometimes run separately and thus trigger separate processes. We must find a way to persist information, like the name of the artifacts folder, across these processes.
25
25
 
26
- The artifact folder name generation code is in 2 places - the GitHub action and ALKiln's core code[^1]. In future, we may reduce that to just one location - the core code.
26
+ The GitHub action creates an artifact folder name and sends it to a script that use an instance of the `Log` class to create the folder and save the name. In other environments, an instance of the `Log` class is what creates the name.
27
27
 
28
- <!-- More complex description that I don't think we need now, but want to double check:
29
- The scripts that GitHub action uses need to store its output in the same artifacts folder. The GitHub action therefore builds the name of the artifact folder and passes that around to the different scripts. The scripts pass the folder name to the `Log` class every time, which saves the folder name in `runtime_config.json`. After that, the core code uses that `json` value to put other artifacts in the same folder. We also have folder-naming code in the core code which we use for other purposes. The GitHub action duplicates that folder-naming code, which is unfortunate.
28
+ The instance of the `Log` saves the name in `runtime_config.json`. That instance of `Log` and other ALKiln code uses that name to create and store files in that artifacts folder.
30
29
 
31
- At the same time, tests that run in ALKilnInThePlayground don't have GitHub to manage the artifact folder name. It only uses the `run_cucumber` script, not any of the others...
30
+ The artifact folder name generation code is in 2 places - the GitHub action and ALKiln's core code[^1]. In future, we may be able to reduce that to just one location - the core code.
32
31
 
33
- Adding to that confusion, when people (like internal ALKiln developers) run tests from their command line, they do use the `setup` script once at first, but then run test suites repeatedly...
32
+ Below are more detailed descriptions of how each environment interacts with the folder name. Where the folder name is created, gets passed, gets saved, and gets used. These descriptions still gloss over many details.
34
33
 
35
- Neither of the last 2 can depend on the `runtime_config.json` folder name that `setup` creates. If they did, all their multiple test runs would save to that first folder. Since both those environments use `run_cucumber.js` alone repeatedly, and since we don't want to duplicate folder-naming behavior between even more scripts, we decided that those non-GitHub environments should be able to let `Log` create a folder name from scratch every time. The `Log` constructor has to be able to accept a `path` argument with a folder name and also to accept an undefined `path` argument.
36
- -->
34
+ The diagrams highlight `Log` to help visualize a common point in all the flows.
37
35
 
38
- A future goal is to remove the need to store the name in the runtime configuration file to reduce that complexity a bit. These flows are up for discussion.
39
36
 
40
- Below are more detailed descriptions of the different paths the folder name takes in the different environments. Where the folder name is created, gets passed, gets saved, and gets used. Note that there's a little glossing over the details. For example, everything saves to `runtime_config.json`, but only the core code[^1] ever uses the value there.
37
+ ### Shared behavior
38
+
39
+ For each environment, the start and end of how they manage the artifacts folder name is different. In the middle, though - once the artifacts folder name is already stored in the `runtime_config` file - the flow is the same.
40
+
41
+ Npm commands that come in the middle have this flow to save logs:
42
+
43
+ ```mermaid
44
+ flowchart LR
45
+
46
+ environment --triggers--> commands["middle</br>commands"]
47
+ commands --trigger--> scripts["package</br>code"]
48
+ scripts --make--> log2["#96;Log#96;"]:::log
49
+ log2 --"gets name</br>from"--> runtime2["runtime config</br>file"]
50
+ log2 --"adds to"--> folder2[folder</br>& files]
51
+
52
+ classDef log fill:#d6fd88,stroke:#000,stroke-width:2px,color:#000
53
+ ```
54
+
55
+ The core code also needs to use the artifacts folder name in order to save both logs and other artifacts:
56
+
57
+ ```mermaid
58
+ flowchart LR
59
+
60
+ core["core</br>code"] --"makes"--> log4["#96;Log#96;"]:::log
61
+ core --"adds to"--> folder3[folder</br>& files]
62
+ core --"gets name</br>from"--> runtime3["runtime config</br>file"]
63
+ log4 --"gets name</br>from"--> runtime3
64
+ log4 --"adds to"--> folder3
65
+
66
+ classDef log fill:#d6fd88,stroke:#000,stroke-width:2px,color:#000
67
+ ```
68
+
69
+ Those are the shared flows. Each environment, though, has its own way to store the name at the start and each environment has its own way to give the author the final artifacts.
41
70
 
42
- The diagrams highlight `Log` to help visualize a common point in all the flows.
43
71
 
44
72
  ### GitHub action
45
73
 
46
- 1. GitHub action creates a new folder name, passes that name to `setup`, which passes that name to `Log`, which creates the artifacts folder and saves the name in `runtime_config.json`. The setup `Log` uses the name to store logs in the folder. The setup uses its `Log`.
47
- 2. GitHub action uses the same folder name, passes that same name to `run_cucumber`, which passes that same name to `Log`. The `runtime_cucumber` process uses that `Log`. The `run_cucumber` process also triggers the core code, which uses the folder name in `runtime_config.json` to create its own `Log`. The core code also uses that name to store other artifact files in the folder.
48
- 3. GitHub action creates the folder name, passes that same name to `takedown`, which passes that same name when instantiating its `Log`. The takedown `Log` uses the name to store logs in the folder.
74
+ The GitHub action starts off with an empty `runtime_config` file. The action creates a new folder name and passes that name to the `artifacts` script, which passes that name to a `Log`. The `Log` creates the artifacts folder and saves the name in `runtime_config.json`.
49
75
 
50
76
  ```mermaid
51
- %% "pass name too" has 2 o's at the end because mermaid makes one of them disappear
77
+ flowchart LR
78
+
79
+ action["GitHub action"] --creates--> name["artifacts</br>folder name"]
80
+ action --"passes</br>name "--> command["'artifacts'</br>command"]
81
+ command --"passes</br>name"--> artifacts["artifacts.js"]
82
+ artifacts --"passes</br>name"--> log1["#96;Log#96;"]:::log
83
+ log1 --"stores name in</br>& uses"--> runtime1["runtime config</br>file"]
84
+ log1 --"creates</br>with name"--> folder1["folder</br>& files"]
85
+ log1 --"adds to"--> folder1
52
86
 
87
+ classDef log fill:#d6fd88,stroke:#000,stroke-width:2px,color:#000
88
+ ```
89
+
90
+ Then other processes use the name from the config to store logs and other files in the artifacts folder (as we've already shown).
91
+
92
+ Finally, the action uses the name in the action context to download the artifacts folder so the user can have access to it after the action is done.
93
+
94
+ ```mermaid
53
95
  flowchart LR
54
- action[action part 1] --create/pass name too--> setup
55
- setup["setup"] --pass name too--> log1["#96;Log#96;"]:::log
56
- log1 --store name in/ignore--> runtime1["runtime config file"]
57
- log1 --create with name--> folder1[folder]
58
-
59
- action2[action part 2] --pass name too--> run["run"]
60
- run --pass name too--> log2["#96;Log#96;"]:::log
61
- log2 --store name in/ignore--> runtime2["runtime config file"]
62
- log2 --use with name--> folder2[folder]
63
- run --> core["core code"]
64
- core --pass name too--> log3["#96;Log#96;"]:::log
65
- core --use with name--> folder2
66
- core --get name from--> runtime2
67
- log3 --use with name--> folder2
68
- log3 --store name in/ignore--> runtime2
69
-
70
- action3[action part 3] --pass name too--> takedown["takedown"]
71
- takedown --pass name too--> log4["#96;Log#96;"]:::log
72
- log4 --store name in/ignore--> runtime3["runtime config file"]
73
- log4 --create with name--> folder5[folder]
96
+
97
+ action["GitHub action"] --previously created--> name["artifacts folder name"]
98
+ action --uses name to get--> folder["folder & files"]
74
99
 
75
100
  classDef log fill:#d6fd88,stroke:#000,stroke-width:2px,color:#000
76
101
  ```
77
102
 
103
+
78
104
  ### ALKilnInThePlayground
79
105
 
80
- 1. ALKilnInThePlayground triggers `run_cucumber` without a folder name which triggers `Log` without a folder name. `Log` creates a new folder name and saves it in `runtime_config.json`. It also creates the artifacts folder. The `run_cucumber` process also triggers the core code, which uses the folder name in `runtime_config.json` to create its own `Log`. The core code also uses that name to store other artifact files in the folder.
106
+ _Note: This should be implemented by the time anyone actually reads this. Here's hoping._
107
+
108
+ ALKilnInThePlayground starts off with an empty `runtime_config` file. ALKilnInThePlayground triggers the `artifacts` command, but without a folder name. The code still creates a `Log` (also without a folder name). The `Log` itself creates the name.
81
109
 
82
110
  ```mermaid
83
111
  flowchart LR
84
- ALKilnInThePlayground --> run["run"]
85
- run --> log2["#96;Log#96;"]:::log
86
- log2 --store name in/ignore--> runtime2["runtime config file"]
87
- log2 --create with name--> folder2[folder]
88
- run --> core["core code"]
89
- core --> log3["#96;Log#96;"]:::log
90
- core --use with name--> folder2
91
- core --get name from--> runtime2
92
- log3 --use with name--> folder2
93
- log3 --store name in/ignore--> runtime2
112
+
113
+ ALKilnInThePlayground --> command["'artifacts'</br>command"]
114
+ command --> artifacts["artifacts.js"]
115
+ artifacts --> log1["#96;Log#96;"]:::log
116
+ log1 --creates--> name["artifacts</br>folder name"]
117
+ log1 --stores name--> runtime1["runtime config file"]
118
+ log1 --"gets name</br>from"--> runtime1["runtime config</br>file"]
119
+ log1 --creates</br>with name--> folder1["folder</br>& files"]
94
120
 
95
121
  classDef log fill:#d6fd88,stroke:#000,stroke-width:2px,color:#000
96
122
  ```
97
123
 
124
+ Then other processes use the name from the config to store logs and other files in the artifacts folder (as we've already shown).
125
+
126
+ Finally, ALKilnInThePlayground itself uses the runtime config file to get the name so it can give the artifacts to the user.
127
+
128
+ ```mermaid
129
+ flowchart LR
130
+
131
+ ALKilnInThePlayground --"gets name from"--> runtime1["runtime config file"]
132
+ ALKilnInThePlayground --"uses name to get"--> folder["folder & files"]
133
+
134
+ classDef log fill:#d6fd88,stroke:#000,stroke-width:2px,color:#000
135
+ ```
136
+
137
+
98
138
  ### Command line
99
139
 
100
- 1. The developer uses the command line to trigger setup without a folder name which triggers `Log` without a folder name. `Log` creates a name and creates the artifacts folder, then stores files in that folder.
101
- 2. The developer uses the command line to trigger `run_cucumber` without a folder name which triggers `Log` without a folder name. `Log` creates and saves a new folder name in `runtime_config.json`, and creates the artifacts folder. The `run_cucumber` process also triggers the core code, which uses the folder name in `runtime_config.json` to create its own `Log`. The core code also uses that name to store other artifact files in the folder.
102
- 3. The developer uses the command line to trigger `takedown` without a folder name which triggers `Log` without a folder name. `Log` creates a name and the artifacts folder, then stores files in that folder.
140
+ The command line flow is similar to ALKilnInThePlayground, but has to deal with a pre-existing runtime config file[^2]. The command line flow overwrites the artifacts folder name on each run.
141
+
142
+ An internal developer uses the command line to trigger the `artifacts` command, but without a folder name. The code still creates a `Log` (also without a folder name). The `Log` itself creates a name and overwrites the current name in the runtime config file.
103
143
 
104
144
  ```mermaid
105
145
  flowchart LR
106
- cmd1[command line] --> setup
107
- setup["setup"] --> log1["#96;Log#96;"]:::log
108
- log1 --store name in/ignore--> runtime1["runtime config file"]
109
- log1 --create with/use with name--> folder1[folder]
110
-
111
- cmd2[command line] --> run["run"]
112
- run --> log2["#96;Log#96;"]:::log
113
- log2 --store name in/ignore--> runtime2["runtime config file"]
114
- log2 --create with name--> folder2[folder]
115
- run --> core["core code"]
116
- core --> log3["#96;Log#96;"]:::log
117
- core --use with name--> folder2
118
- core --get name from--> runtime2
119
- log3 --use with name--> folder2
120
- log3 --store name in/ignore--> runtime2
121
-
122
- cmd3[command line] --> takedown["takedown"]
123
- takedown --> log4["#96;Log#96;"]:::log
124
- log4 --store name in/ignore--> runtime3["runtime config file"]
125
- log4 --create with name--> folder5[folder]
146
+
147
+ dev --> command["'artifacts'</br>command"]
148
+ command --> artifacts["artifacts.js"]
149
+ artifacts --> log1["#96;Log#96;"]:::log
150
+ log1 --creates--> name["artifacts</br>folder name"]
151
+ log1 --"overwrites</br>previous name"--> runtime1["runtime config file"]
152
+ log1 --"gets name</br>from"--> runtime1["runtime config</br>file"]
153
+ log1 --creates</br>with name--> folder1["folder</br>& files"]
126
154
 
127
155
  classDef log fill:#d6fd88,stroke:#000,stroke-width:2px,color:#000
128
156
  ```
129
157
 
158
+ Then other processes use the name from the config to store logs and other files in the artifacts folder (as we've already shown).
159
+
160
+ ALKiln stores the artifacts folder in the root of the local repository folder. The developer has direct access to the file system and can see every new artifacts folder. In fact, they can also see any previous artifacts folders. We avoid adding those artifacts folders to the repo by including the folder name pattern in the `.gitignore` and `.npmignore` files.
161
+
162
+ ```mermaid
163
+ flowchart LR
164
+
165
+ git --🙈--> folder["folders & files"]
166
+ dev --👁️--> folder
167
+ npm --🙉--> folder
168
+
169
+ classDef log fill:#d6fd88,stroke:#000,stroke-width:2px,color:#000
170
+ ```
171
+
172
+
130
173
  ## Alternatives considered
131
174
 
132
- - One script for creating the artifacts folder name: Make a script that saves the folder name to the ALKiln `runtime_config.json`. Then all the other code, including instances of `Log`, would always use `runtime_config.json`. We would want `package.json` scripts for the command line environment that would include getting the name of the folder. That potentially complicates the code and process for internal development. We will see how our current design behaves first.
133
- - Use `Log`'s path name instead of the one in `runtime_config.json`. We thought we would want to save in previous artifacts folders, but it now seems potentially unnecessary. This seems the most viable option for the future, but it is unclear how we can integrate `Log` with all the other files. I wouldn't consider PDFs and screenshots to be logs.
175
+ - Each originator (GitHub, ALKilnInThePlayground, the dev) could always create the name from the outside. This would duplicate work, but would give more fine-grained control.
176
+ - Have `Log` make a different folder name each time and, at the very end, combine the contents of those folders into one folder. Hey, all ideas are welcome here.
177
+
178
+ For name creation:
179
+
180
+ - Avoid GitHub actions creating names. That is, create names only in `artifacts.js` and pass that out again. Needs research.
181
+
134
182
 
135
183
  [^1]: **Core framework code/core code:** the code that implements the Steps in the `.feature` test files.
184
+
185
+ [^2] Keeping the `runtime_config` file around helps greatly improves the local development experience. You can read more in the document that talks about the 4 environments ALKiln supports.