PRO-8756: monorepo workflows - #5179
Conversation
Co-authored-by: Jed <vjeudy@protonmail.com>
|
Yes it shouldn't but always skeptical, the nightly test run fixes the issue I think. I'll review the core when I have a minute :) another question: is there any tool handling this logic already? |
| }); | ||
|
|
||
| function runGit(command) { | ||
| return execSync(`git ${command}`, { |
Check warning
Code scanning / CodeQL
Shell command built from environment values Medium test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 10 months ago
To fix this issue, avoid concatenating user- or environment-derived values directly into a shell command string. Instead, pass the subcommand and arguments as an array to execFileSync (or execFile). This approach avoids shell interpretation and ensures that arguments with spaces or special characters are handled safely. Specifically, update runGit(command) to take either: (a) a command string and split it into args safely, or (b) a subcommand and arguments explicitly, or (c) accept an argument array. Since callers like gitAdd and gitCommit currently pass a command string, the cleanest safe fix is to update all these to build their argument arrays and pass them to runGit, which then invokes 'git' with those arguments using execFileSync (or execSync). Make sure to replace all invocations of runGit in the file accordingly.
Changes needed:
- Update
runGitto take an arguments array instead of a string. - Update all calls to
runGitto pass argument arrays rather than strings. - Escape/safely handle commit message (
git commit -m) and paths for add. - No new external dependencies are needed.
| @@ -142,8 +142,8 @@ | ||
| }); | ||
| }); | ||
|
|
||
| function runGit(command) { | ||
| return execSync(`git ${command}`, { | ||
| function runGit(args) { | ||
| return execFileSync('git', args, { | ||
| cwd: repoRoot, | ||
| encoding: 'utf8', | ||
| env: gitEnv, | ||
| @@ -154,15 +154,15 @@ | ||
| function gitAdd(filePath) { | ||
| const relative = path.relative(repoRoot, filePath); | ||
| const gitPath = relative.split(path.sep).join(path.posix.sep); | ||
| runGit(`add ${gitPath}`); | ||
| runGit(['add', gitPath]); | ||
| } | ||
|
|
||
| function gitCommit(message) { | ||
| runGit(`commit -m "${message}"`); | ||
| runGit(['commit', '-m', message]); | ||
| } | ||
|
|
||
| function ensureCleanWorkingTree() { | ||
| const status = runGit('status --porcelain'); | ||
| const status = runGit(['status', '--porcelain']); | ||
| if (status) { | ||
| throw new Error('Working tree must be clean before running impact tests.'); | ||
| } |
…rophecms/apostrophe into pro-8756-monorepo-switch-workflows
ValJed
left a comment
There was a problem hiding this comment.
Few questions, looks good!
| } | ||
|
|
||
| const commitMessages = output.split('\n'); | ||
| return commitMessages.some((msg) => /\[force ci\]/i.test(msg)); |
There was a problem hiding this comment.
So any commit on your PR containing this force ci will make them all run all the time (for this PR).
Something in the title of the PR would have been easier to track but not sure we can do that. I think it's ok but I don't see use case especially with the daily run.
There was a problem hiding this comment.
It's just a quick way to solve "not forget to run all tests for my change for some strange reason" . This follows the convention for github owned (skip ci)
| }).trim(); | ||
| return mergeBase || ''; | ||
| } catch (error) { | ||
| return ''; |
There was a problem hiding this comment.
[detail] Could be null for clarity since we check if it exist later.
| - name: Install pnpm | ||
| uses: pnpm/action-setup@v4 | ||
| with: | ||
| version: 10.18.0 |
There was a problem hiding this comment.
the pnpm version could be an env too maybe?
There was a problem hiding this comment.
That would be a great future improvement, yes. But we can leave it for when we bump pnpm
| with: | ||
| name: pnpm-lock | ||
| path: pnpm-lock.yaml | ||
| retention-days: 30 |
There was a problem hiding this comment.
Why 30 days? Is is shared between CI runs?
There was a problem hiding this comment.
It doesn't matter, it's overridden on every run and used down the pipeline.
|
|
||
| const GLOBAL_IMPACT_PATHS = new Set([ | ||
| 'package.json', | ||
| // Keep it, although it's not under version control - be explicit. |
There was a problem hiding this comment.
Yes but I see you use cache for the pnpm-lock file?
There was a problem hiding this comment.
It's generated on every run in the setup phase, reused in all other phases, including the test matrix jobs
| }, | ||
| "apostropheTestConfig": { | ||
| "requiresMongo": false | ||
| } |
There was a problem hiding this comment.
I suppose that everytime there are mocha tests we need mongo? (Not sure we might have unit tests).
If yes and if we follow a convention, any package without a script mocha could skip mongo. Your solution is clearer but I'm not sure people will think about updating this.
There was a problem hiding this comment.
I think declaring explicitly what a package needs is a better way to go. For mongo it makes sense to explicitly opt-out, as most of the packages do require it.
* main: (26 commits) more (#5207) adds permission.isAdmin (#5192) Skip string choices, disallow type change (#5203) Fix stylelint dependency conflict (#5199) oops old version number in main (#5201) just merging back the changelog (#5198) PRO-8758: soft-redirect and url encoding (#5191) Fix admin UI crashes (#5195) PRO-8756: monorepo workflows (#5179) PRO-8768: relative paths for the good operating systems (#5194) bump express-cache-on-demand to 1.0.4 (#5190) the video is no longer available, use apostrophecms channel video wit… (#5183) add changelog for pro-8751 (#5187) pro 8751 schema update (#5176) Pro 8761 i18n static tests (#5185) Pro 8756 monorepo switch (#5177) release 4.24.0 (#5173) PRO-8743: windows fix 2b: back off on the file:/// URLs for vite (#5169) add batch failure notifications (#5157) PRO-8735 PR take 2 (#5168) ...
* main: (26 commits) more (#5207) adds permission.isAdmin (#5192) Skip string choices, disallow type change (#5203) Fix stylelint dependency conflict (#5199) oops old version number in main (#5201) just merging back the changelog (#5198) PRO-8758: soft-redirect and url encoding (#5191) Fix admin UI crashes (#5195) PRO-8756: monorepo workflows (#5179) PRO-8768: relative paths for the good operating systems (#5194) bump express-cache-on-demand to 1.0.4 (#5190) the video is no longer available, use apostrophecms channel video wit… (#5183) add changelog for pro-8751 (#5187) pro 8751 schema update (#5176) Pro 8761 i18n static tests (#5185) Pro 8756 monorepo switch (#5177) release 4.24.0 (#5173) PRO-8743: windows fix 2b: back off on the file:/// URLs for vite (#5169) add batch failure notifications (#5157) PRO-8735 PR take 2 (#5168) ...
Summary
Brings a tooling for detecting the change impact and provide a matrix for performant testing in GitHub Actions (only test what makes sense).
Detection
testscript in theirpackage.jsonwill participate[force ci](case insensitive) is found in a commit message, all packages will be testedOptimization & Configuration
The following configuration in any
package/*/package.json`will determine what services are needed during the CI test run for that package. The above showcases the default behavior if no configuration is found.
NODE_VERSIONS_JSON: "[20,22,24]"andMONGODB_VERSIONS_JSON: '["7","8"]'environment variables inmonorepo.ymlcontrol the version matrix of the respective runtime.REDIS_VERSION: "7"defines the Redis version (when in use).The services are pulled from the docker repository and cached for a month. No additional network requests will be made until cache miss.
Technical details
.github/workflows/scripts/detect-impacted-packages.mjs, which diff-checks against the default branch, expands dependent packages, and feeds GitHub’s matrix jobs; mocha test ensures proper behavior. Example output..github/workflows/scripts/expand-runtime-matrix.mjsto merge the detected packages matrix with the nodejs and mongodb version matrix. Example output[force ci]to force testing of all monorepo packages that havetestpackage JSON script.run_allworkflow-dispatch flag plus nightly FORCE_ALL runs so we can still exercise the full workspace on demand.What are the specific steps to test this change?
pnpm install) so the repo scripts/tests are available.npx mocha .github/workflows/scripts/test-impacted-packages.mjsand confirm all detector tests pass.DEFAULT_BRANCH=main BASE_SHA=$(git merge-base HEAD origin/main) node .github/workflows/scripts/detect-impacted-packages.mjs, and verify the JSON output only lists that package and its dependents.What kind of change does this PR introduce?
(Check at least one)
Make sure the PR fulfills these requirements:
If adding a new feature without an already open issue, it's best to open a feature request issue first and wait for approval before working on it.
Other information: