Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
446 commits
Select commit Hold shift + click to select a range
5e0461a
Workflow again.....
leeyi45 Aug 3, 2025
358c31d
Try again
leeyi45 Aug 3, 2025
561627c
pls work
leeyi45 Aug 3, 2025
4ea7757
Trying another fix
leeyi45 Aug 3, 2025
2ed0a62
Does this work?????
leeyi45 Aug 3, 2025
ca64d00
Fix broken pipe character
leeyi45 Aug 3, 2025
baaada2
Try and fix the git root path not working
leeyi45 Aug 3, 2025
17ed52e
I really don't know what is going on
leeyi45 Aug 3, 2025
fc696f2
now im really confused
leeyi45 Aug 3, 2025
6a0d7e0
Testing again
leeyi45 Aug 3, 2025
d2a719e
Is the check for changes function throwing an error?
leeyi45 Aug 3, 2025
9e7baf7
I think I figured it out
leeyi45 Aug 3, 2025
661dc91
Add formatting to the summary output
leeyi45 Aug 3, 2025
0d7735b
Check that the find package job produces appropriate outputs
leeyi45 Aug 3, 2025
92e5c92
Fix action.yml file not recording outputs
leeyi45 Aug 3, 2025
ed2beb0
Attempt 1 at creating workflows for tabs
leeyi45 Aug 3, 2025
174983c
Add postinstall scripts to bundles
leeyi45 Aug 3, 2025
ecf67f5
Fix things certain dependencies not being specified correctly
leeyi45 Aug 3, 2025
72fe640
Once again, fix more missing dependencies
leeyi45 Aug 3, 2025
9081a13
Add bundles to workflow file
leeyi45 Aug 3, 2025
82cf7f8
Fix missing dependencies again
leeyi45 Aug 3, 2025
ed773a3
Try out a new composite action
leeyi45 Aug 4, 2025
a01c1a0
Fix broken action not checking code out
leeyi45 Aug 4, 2025
bb0dbc1
Add required shell parameter
leeyi45 Aug 4, 2025
2db7fc2
Update incorrect action input name
leeyi45 Aug 4, 2025
8dbc63d
Fix init action not installing deps
leeyi45 Aug 4, 2025
7b8db40
Not me trying to see why this action doesn't work
leeyi45 Aug 4, 2025
4069d32
Fix incorrect keyword
leeyi45 Aug 4, 2025
b0eff8e
Not sure why playwright is being weird
leeyi45 Aug 4, 2025
64d0584
Checking again
leeyi45 Aug 4, 2025
843801c
Apparently github actions does weird things
leeyi45 Aug 4, 2025
49017ea
Patch uniqid to remove its node dependency
leeyi45 Aug 4, 2025
827d837
what's broken this time?
leeyi45 Aug 4, 2025
884487b
So why are the tests not running
leeyi45 Aug 4, 2025
9355d32
Try fixing the comparison checks again
leeyi45 Aug 4, 2025
42705ce
Fix whatever is broken
leeyi45 Aug 4, 2025
9100bbf
Add test dependencies to buildtools so that they're installed when te…
leeyi45 Aug 4, 2025
5ff41cc
Linting yml
leeyi45 Aug 4, 2025
be46185
Remove the old install-deps action
leeyi45 Aug 4, 2025
80449f1
Update the buildtools test
leeyi45 Aug 4, 2025
498e291
Add a static type file for lint plugin
leeyi45 Aug 4, 2025
c5cd95b
Fix broken lintplugin build
leeyi45 Aug 4, 2025
90714c3
Include peer dependencies as dev dependencies for lint plugin
leeyi45 Aug 4, 2025
387cbbe
Try fixing the communication bundle
leeyi45 Aug 4, 2025
575e7b4
Add test coverage testing to workflow
leeyi45 Aug 4, 2025
dcbfd54
Fix coverage reporters being broken
leeyi45 Aug 4, 2025
04aee64
Fix test timeouts again
leeyi45 Aug 4, 2025
7e93564
Add coverage provider to repotools
leeyi45 Aug 4, 2025
19611fa
Fix some broken linting and refactor test config to repotools
leeyi45 Aug 6, 2025
acf42e4
Add the new lint rule
leeyi45 Aug 6, 2025
df703d3
Forgot to add something to dev dependencies again.
leeyi45 Aug 6, 2025
51423c0
Resolve vite to the same version using resolutions
leeyi45 Aug 6, 2025
4b30c0f
Update github actions and docs
leeyi45 Aug 6, 2025
785a0e4
Update lint plugin
leeyi45 Aug 6, 2025
cebfeb7
Figure out what went wrong with the info action
leeyi45 Aug 6, 2025
c2ca1b9
Use yield instead of return
leeyi45 Aug 6, 2025
35d5f34
Add tests to the workflow
leeyi45 Aug 7, 2025
d075987
Need to change the test environment for the actions
leeyi45 Aug 7, 2025
ebb8d9f
Change how things are saved as artifacts
leeyi45 Aug 7, 2025
56f0246
Added building docs to bundle job
leeyi45 Aug 7, 2025
aab6c5d
Fix wrong command for bundles
leeyi45 Aug 7, 2025
b885d76
Allow TypeAliases to be exported but excluded from JSON output
leeyi45 Aug 7, 2025
aaf74f1
Update test for buildtools to account for TypeAliases
leeyi45 Aug 7, 2025
969e858
Add linting configs to the docs
leeyi45 Aug 7, 2025
01552b5
Try a new way for determining changes
leeyi45 Aug 7, 2025
c75f5ae
Fix missing name check
leeyi45 Aug 7, 2025
15c3d41
Fix issues with not skipping __
leeyi45 Aug 7, 2025
12da06a
Fix bundles and tabs package not being handled correctly
leeyi45 Aug 7, 2025
2b8b79e
Still trying to fix a broken check
leeyi45 Aug 7, 2025
434a37c
Needed to move the check to another function
leeyi45 Aug 7, 2025
c60359b
Put the check back in the previous place
leeyi45 Aug 7, 2025
4feea8c
Check was still broken
leeyi45 Aug 7, 2025
b5c9f21
Fix incorrect packages being displayed
leeyi45 Aug 7, 2025
67e50db
I missed an s
leeyi45 Aug 7, 2025
25ff249
Fix incorrect types being passed around
leeyi45 Aug 7, 2025
08a8f63
Fix maxdepth parameter not being checked properly
leeyi45 Aug 7, 2025
5f238b7
Use memoize to remove unnecessary calls to git
leeyi45 Aug 7, 2025
ac229bd
Mock memoize
leeyi45 Aug 7, 2025
f99658c
Try fix something that's broken
leeyi45 Aug 7, 2025
689fb24
Why is this stil broken :(
leeyi45 Aug 7, 2025
5411b28
Work please :(
leeyi45 Aug 7, 2025
20bf4dd
Fix package names being incorrect
leeyi45 Aug 7, 2025
21018aa
Finalize a topo sort algorithm to determine changes
leeyi45 Aug 8, 2025
a23afae
Figure out if docserver and devserver are being accurately represented
leeyi45 Aug 8, 2025
62b911f
Does comparing to a string value work?
leeyi45 Aug 8, 2025
82bca31
Add new linting rule and fix documentation being broken
leeyi45 Aug 9, 2025
0d54296
Remove a file that was accidentally committed
leeyi45 Aug 9, 2025
d80cf63
Fix missing type in manifest and mkdir call in manifest builder
leeyi45 Aug 9, 2025
385a3e5
Fix the still broken test
leeyi45 Aug 9, 2025
2abda8d
Fix tests not being compatible with Windows paths joining
leeyi45 Aug 9, 2025
b8d64b2
Try running library tests on windows-latest as well with the workflow
leeyi45 Aug 9, 2025
3bcfdd4
Update shell configuration for workflows
leeyi45 Aug 9, 2025
5242c61
Fix the OS comparison test
leeyi45 Aug 9, 2025
0bb7536
Fix shell not being input correctly into init action
leeyi45 Aug 9, 2025
40b979e
Will adding corepack to the PATH work?
leeyi45 Aug 9, 2025
2da6a75
Does enabling corepack after setting up node work?
leeyi45 Aug 9, 2025
955d30c
Still screwing around with corepack
leeyi45 Aug 9, 2025
a61c2bb
Try again with the other things
leeyi45 Aug 9, 2025
3156f2d
What happens if I -Force?
leeyi45 Aug 9, 2025
867c51d
Try a different corepack command
leeyi45 Aug 9, 2025
ac286a9
Try which
leeyi45 Aug 9, 2025
411654c
Fix issues on Windows
RichDom2185 Aug 9, 2025
1a98c97
More testing
leeyi45 Aug 9, 2025
b2387f6
Try hardcoding the yarn version
leeyi45 Aug 9, 2025
0698790
Just corepack install?
leeyi45 Aug 9, 2025
cd704d5
Would an npm install work?
leeyi45 Aug 9, 2025
d635892
I genuinely still don't know why powershell won't use yarn properly
leeyi45 Aug 9, 2025
92be334
Try something new with corepack enable
leeyi45 Aug 9, 2025
9a3df60
Fix docs on Windows
RichDom2185 Aug 9, 2025
cc44e75
Fix the command not running properly
leeyi45 Aug 9, 2025
0fb9836
Combine all the windows things into a single step
leeyi45 Aug 9, 2025
f2130a2
Maybe yarn was installed globally?
leeyi45 Aug 9, 2025
dc5f09d
Fix folder already exists
RichDom2185 Aug 9, 2025
02abd79
Does this work?
leeyi45 Aug 9, 2025
0870811
Make a windows version of the directory paths available
leeyi45 Aug 9, 2025
848be2d
Add a cwd check
leeyi45 Aug 9, 2025
c719288
Fix more TypeDoc
RichDom2185 Aug 9, 2025
1cd4346
Update docs about corepack
leeyi45 Aug 9, 2025
a20bd59
Update installation docs
leeyi45 Aug 9, 2025
643c342
Continue to try fixing the workflow
leeyi45 Aug 9, 2025
72e6c0e
Check working directory
leeyi45 Aug 9, 2025
8b06cf8
I have no idea why one evaluates to true and the other evalutes to false
leeyi45 Aug 9, 2025
fa85736
Check cwd
leeyi45 Aug 9, 2025
3841105
Remove all the windows directory stuff and just use yarn workspaces i…
leeyi45 Aug 9, 2025
f378383
Update test configs
leeyi45 Aug 9, 2025
cdf70e0
Try adding a new matcher for resolving paths
leeyi45 Aug 9, 2025
2bcf0dc
Update the buildtools tests for windows compatibility
leeyi45 Aug 10, 2025
a9f2d80
Add a "same path" comparer
leeyi45 Aug 10, 2025
e583162
Continue fixing tests to make them work on windows
leeyi45 Aug 10, 2025
f6847ad
Still fixing tests....
leeyi45 Aug 10, 2025
f11b4c4
Add some logging
leeyi45 Aug 10, 2025
773cd4c
Try and fix the markdown tree tests
leeyi45 Aug 10, 2025
ac00019
Fix the tsc thing
leeyi45 Aug 10, 2025
a2b03d9
Re-enable the full workflow
leeyi45 Aug 10, 2025
a08edba
Continue to try fix the doc server not building
leeyi45 Aug 10, 2025
21a0d30
Still trying to figure the docserver out
leeyi45 Aug 10, 2025
985d58a
Echo the changes value for docserver
leeyi45 Aug 10, 2025
388f14f
Use fromJSON
leeyi45 Aug 10, 2025
759a012
Returning a mapping doesn't work
leeyi45 Aug 10, 2025
90229db
Disable everything except for docserver
leeyi45 Aug 10, 2025
84a3c8f
Try using fromJSON in a different place
leeyi45 Aug 10, 2025
e1593c7
As a whole workflow, this should now work
leeyi45 Aug 10, 2025
6110d5c
Update deploy workflow
leeyi45 Aug 10, 2025
7e27aef
Update docs
leeyi45 Aug 10, 2025
e316080
Add the memory space option to lint:all
leeyi45 Aug 10, 2025
7117b7c
Remove unnecessary patch
leeyi45 Aug 10, 2025
ede60f0
Update lib/repotools/src/manifest.ts
RichDom2185 Aug 10, 2025
315a49e
Revert "Remove unnecessary patch"
RichDom2185 Aug 10, 2025
3e5b9b2
Reformat some Markdown files for readability
RichDom2185 Aug 10, 2025
d2ed1a5
Reformat more Markdown files
RichDom2185 Aug 10, 2025
0c8edb2
Reformat even more Markdown files
RichDom2185 Aug 10, 2025
b8b5ab2
Reformat remaining Markdown files
RichDom2185 Aug 10, 2025
25fe416
Update doc server and remove yarnhook
leeyi45 Aug 11, 2025
c0a6137
Add http server command to buildtools
leeyi45 Aug 11, 2025
e8b7ea1
Update libs and docs about focused installations
leeyi45 Aug 12, 2025
29e3198
Fix lint issue
leeyi45 Aug 12, 2025
dc62eba
Finally got linting code blocks in markdown files to work
leeyi45 Aug 12, 2025
16e46be
Fix dead links
leeyi45 Aug 12, 2025
c7e8765
Enable lint global to output stats too
leeyi45 Aug 12, 2025
e39dc33
Add a CSV formatter for ESLint statistics
leeyi45 Aug 12, 2025
1f1f9a4
Fix some docs
leeyi45 Aug 12, 2025
b30801a
Hide pathname from mqtt pic
leeyi45 Aug 12, 2025
b5e8328
Fix some flaws with the devserver
leeyi45 Aug 12, 2025
615f7b4
Update unittest bundle and tab to allow multiple and nested calls to …
leeyi45 Aug 12, 2025
4560af3
Reformat Markdown files
RichDom2185 Aug 12, 2025
5583e18
Fix AR bundle
RichDom2185 Aug 13, 2025
838ef37
Add a new action that rebuilds the tabs for the devserver if necessary
leeyi45 Aug 13, 2025
3833f37
Fix action always rebuilding artifact
leeyi45 Aug 13, 2025
b863da9
Will changing the order work?
leeyi45 Aug 13, 2025
0c50c75
Forgot to enable corepack
leeyi45 Aug 13, 2025
b518abd
Add manifest building
leeyi45 Aug 13, 2025
9c42e37
Cleanup
RichDom2185 Aug 13, 2025
c52eec3
Fix devserver workflow not working and modules-lib install taking for…
leeyi45 Aug 18, 2025
6a436b6
Add description to github actions package
leeyi45 Aug 18, 2025
11abc90
Time to figure out why playwright detection isn't working
leeyi45 Aug 18, 2025
a4e264a
Turns out I am just dumb and left playwright out of the curve tab's d…
leeyi45 Aug 18, 2025
ef48e95
Use headless install of playwright instead
leeyi45 Aug 18, 2025
78d3781
Miscellanous changes
leeyi45 Aug 18, 2025
51c5fb4
Update docs and lint configuration for quotes
leeyi45 Aug 19, 2025
1315c90
Fix the inconsistent semicolon delimiting in typescript types and int…
leeyi45 Aug 19, 2025
e61e287
Remove useless workspaces and modify templates to include all scripts
leeyi45 Aug 19, 2025
cd8845f
Test playwright caching
leeyi45 Aug 19, 2025
1d66fd2
Try another way to parse json
leeyi45 Aug 19, 2025
1960a43
Try installing the tab package
leeyi45 Aug 19, 2025
2e13ce2
Try focusing everything at once
leeyi45 Aug 19, 2025
4f04d86
Check if the playwright directory is found
leeyi45 Aug 19, 2025
2b96862
Fix error handling not working
leeyi45 Aug 19, 2025
df25d9b
Maybe this will work
leeyi45 Aug 19, 2025
9122f93
Try playwright tool caching
leeyi45 Aug 19, 2025
cc4a4ff
Use the workspace command instead
leeyi45 Aug 19, 2025
c937fa4
Fix using the wrong playwright option
leeyi45 Aug 19, 2025
086281d
Does adding the mkdirP call work?
leeyi45 Aug 19, 2025
a822167
Use cache instead of tool-cache
leeyi45 Aug 19, 2025
a638335
Remove tool-cache
leeyi45 Aug 19, 2025
b43125c
Restore everything else and stop using caching for playwright
leeyi45 Aug 19, 2025
138f19f
Add missing repotools tests
leeyi45 Aug 25, 2025
464d99c
Remove testing related tests since we can't really mock vite
leeyi45 Aug 25, 2025
6e28860
Update some dependencies
leeyi45 Aug 29, 2025
18b9db6
Fix it and test being able to be called recursively
leeyi45 Aug 29, 2025
75057b2
Add doc info on describe function titles
leeyi45 Aug 29, 2025
16a1834
Format the summary produced by the info action to be better
leeyi45 Sep 1, 2025
0eb51a9
Fix base url not working correctly
leeyi45 Sep 1, 2025
ace06f2
Fix the url not working again
leeyi45 Sep 1, 2025
286b1ff
Fix url handling again
leeyi45 Sep 1, 2025
b833da5
Add tests for rune bundle and tab
leeyi45 Sep 2, 2025
3861c2c
Update test coverage configuration
leeyi45 Sep 2, 2025
a52469e
Merge remote-tracking branch 'origin/tab-cleanup' into yarn-workspaces
leeyi45 Sep 2, 2025
ccbd65f
Add tests for plotly and painter tabs
leeyi45 Sep 2, 2025
b247e12
Fix issue with configs not being cloned properly
leeyi45 Sep 2, 2025
5e04913
Fix curve bundle functions and tests
leeyi45 Sep 2, 2025
db01b2e
Add anaglyph rune test
leeyi45 Sep 2, 2025
59babe6
Fix tests not working correctly
leeyi45 Sep 2, 2025
a903cc8
Add tests for sound and stereo_sound bundles
leeyi45 Sep 2, 2025
c7b3f09
Add tests to repl
leeyi45 Sep 2, 2025
641c8d7
Update some documentation
leeyi45 Sep 2, 2025
be6ae5f
Try adding a github actions reporter
leeyi45 Sep 3, 2025
b79c08b
Fix incorrect build
leeyi45 Sep 3, 2025
786aef1
Remove the requirement to build the reporter
leeyi45 Sep 3, 2025
f083a29
Try a version with actions/core bundled
leeyi45 Sep 3, 2025
6d3f074
Add the uncovered lines information
leeyi45 Sep 3, 2025
790805c
Fix linting and some other things
leeyi45 Sep 3, 2025
fa6982f
Sort test coverage output
leeyi45 Sep 3, 2025
dfcae9f
Try adding some colors
leeyi45 Sep 3, 2025
50731d6
More formatting
leeyi45 Sep 3, 2025
e53d0a1
Fix nested td in html
leeyi45 Sep 3, 2025
2ab4b64
Reformat uncovered lines list
leeyi45 Sep 3, 2025
4152dad
Hide uncovered lines in a summary
leeyi45 Sep 3, 2025
57914a5
Final modifications
leeyi45 Sep 3, 2025
43e69a4
Update documenation for the vitest coverage reporter
leeyi45 Sep 3, 2025
2e6738e
Remove the dependency on actions/core
leeyi45 Sep 3, 2025
59d59b1
Use fs directly since istanbul context writer doesn't support appending
leeyi45 Sep 3, 2025
feb1bd4
Add a summary reporter for tests
leeyi45 Sep 3, 2025
7981a8f
Fix broken paths
leeyi45 Sep 3, 2025
e40606d
Fix an undefined check?
leeyi45 Sep 3, 2025
a580b8f
Try another reporter implementation
leeyi45 Sep 3, 2025
3f74088
Fix continue to fix formatting
leeyi45 Sep 3, 2025
48952f4
Fix formatting again
leeyi45 Sep 3, 2025
90cf4d3
Fix test formatter
leeyi45 Sep 3, 2025
84d50f9
More formatting fixes
leeyi45 Sep 3, 2025
83f3c55
Found the way to get the file name
leeyi45 Sep 3, 2025
e5e1ff3
Fix filepath
leeyi45 Sep 3, 2025
48706cf
Add start time for test modules
leeyi45 Sep 3, 2025
0f693c4
Try to fix the start times
leeyi45 Sep 3, 2025
56839f4
Add slow indicator
leeyi45 Sep 3, 2025
a5280f5
Add docs about test coverage
leeyi45 Sep 3, 2025
718f769
Change defineTab type to be generic
leeyi45 Sep 4, 2025
c939817
Fix stereo sound tab not retrieving the correct module state
leeyi45 Sep 4, 2025
1f7206b
Update test reporter to follow the summary format
leeyi45 Sep 4, 2025
f9beead
Add the silent option to tests
leeyi45 Sep 4, 2025
fcc0332
Fix tests for curve and rune tabs and unittest
leeyi45 Sep 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
17 changes: 17 additions & 0 deletions .github/actions/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// @ts-check
import getBuildCommand from '@sourceacademy/modules-repotools/builder';

const buildCommand = getBuildCommand({
bundle: true,
entryPoints: [
{ in: './src/info/index.ts', out: 'info' },
{ in: './src/load-artifacts/index.ts', out: 'load' }
],
format: 'esm',
outdir: 'dist',
packages: 'external',
platform: 'node',
target: 'node20',
});

await buildCommand.parseAsync();
24 changes: 24 additions & 0 deletions .github/actions/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "@sourceacademy/modules-github-actions",
"description": "Github Actions for the modules repository",
"private": true,
"type": "module",
"devDependencies": {
"@sourceacademy/modules-repotools": "workspace:^",
"@types/node": "^22.15.30",
"typescript": "^5.8.2",
"vitest": "^3.2.3"
},
"dependencies": {
"@actions/artifact": "^2.3.2",
"@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1",
"lodash": "^4.17.21"
},
"scripts": {
"build": "node ./build.js",
"postinstall": "yarn build",
"test": "vitest",
"tsc": "tsc --project ./tsconfig.json"
}
}
30 changes: 30 additions & 0 deletions .github/actions/src/__tests__/git.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import * as exec from '@actions/exec';
import { describe, expect, it, vi } from 'vitest';
import * as git from '../commons.js';

vi.mock(import('lodash/memoize.js'), () => ({
default: (x: any) => x
}) as any);

const mockedExecOutput = vi.spyOn(exec, 'getExecOutput');

describe(git.checkForChanges, () => {
function mockChanges(value: boolean) {
mockedExecOutput.mockResolvedValueOnce({
exitCode: value ? 1 : 0, stdout: '', stderr: ''
});
}

it('should return true if git diff exits with non zero code', async () => {
mockChanges(true);
await expect(git.checkForChanges('/')).resolves.toEqual(true);
expect(mockedExecOutput).toHaveBeenCalledOnce();
});

it('should return false if git diff exits with 0', async () => {
mockChanges(false);

await expect(git.checkForChanges('/')).resolves.toEqual(false);
expect(mockedExecOutput).toHaveBeenCalledOnce();
});
});
87 changes: 87 additions & 0 deletions .github/actions/src/commons.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { getExecOutput } from '@actions/exec';
import memoize from 'lodash/memoize.js';

export interface RawPackageRecord {
directory: string;
hasChanges: boolean;
package: {
name: string;
devDependencies: Record<string, string>;
dependencies: Record<string, string>;
};
}

interface BasePackageRecord {
/**
* Directory within which the `package.json` file was found
*/
directory: string;

/**
* Full scoped package name
*/
name: string;
/**
* `true` if git detected changes from within the package's subdirectories,
* `false` otherwise
*/
changes: boolean;
/**
* `true` if playwright is present under devDependencies. This means that the package
* might need playwright for its tests
*/
needsPlaywright: boolean;
}

export interface BundlePackageRecord extends BasePackageRecord {
bundleName: string;
}

export interface TabPackageRecord extends BasePackageRecord {
tabName: string;
}

export type PackageRecord = BundlePackageRecord | TabPackageRecord | BasePackageRecord;

export function isPackageRecord(obj: unknown): obj is PackageRecord {
if (typeof obj !== 'object' || obj === null) return false;

if (!('directory' in obj) || typeof obj.directory !== 'string') return false;
if (!('name' in obj) || typeof obj.name !== 'string') return false;
if (!('changes' in obj) || typeof obj.changes !== 'boolean') return false;
if (!('needsPlaywright' in obj) || typeof obj.needsPlaywright !== 'boolean') return false;

if ('bundleName' in obj && typeof obj.bundleName !== 'string') return false;
if ('tabName' in obj && typeof obj.tabName !== 'string') return false;

return true;
}

export function isPackageRecordArray(obj: unknown): obj is PackageRecord[] {
return Array.isArray(obj) && !obj.some(each => !isPackageRecord(each));
}

// Not using the repotools version since this uses @action/exec instead of
// calling execFile from child_process

export async function getGitRoot() {
const { stdout } = await getExecOutput('git rev-parse --show-toplevel');
return stdout.trim();
}

/**
* Returns `true` if there are changes present in the given directory relative to
* the master branch\
* Used to determine, particularly for libraries if running tests and tsc are necessary
*/
export const checkForChanges = memoize(async (directory: string) => {
const { exitCode } = await getExecOutput(
'git',
['--no-pager', 'diff', '--quiet', 'origin/master', '--', directory],
{
failOnStdErr: false,
ignoreReturnCode: true
}
);
return exitCode !== 0;
});
204 changes: 204 additions & 0 deletions .github/actions/src/info/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
import type { Dirent } from 'fs';
import fs from 'fs/promises';
import pathlib from 'path';
import { describe, expect, test, vi } from 'vitest';
import * as git from '../../commons.js';
import { getAllPackages, getRawPackages } from '../index.js';

const mockedCheckChanges = vi.spyOn(git, 'checkForChanges');

class NodeError extends Error {
constructor(public readonly code: string) {
super();
}
}

const mockDirectory: Record<string, string | Record<string, unknown>> = {
'package.json': JSON.stringify({
name: '@sourceacademy/modules'
}),
lib: {
'modules-lib': {
'package.json': JSON.stringify({
name: '@sourceacademy/modules-lib'
}),
}
},
src: {
bundles: {
bundle0: {
'package.json': JSON.stringify({
name: '@sourceacademy/bundle-bundle0',
devDependencies: {
'@sourceacademy/modules-lib': 'workspace:^'
}
})
},
},
tabs: {
tab0: {
'package.json': JSON.stringify({
name: '@sourceacademy/tab-Tab0',
dependencies: {
'@sourceacademy/bundle-bundle0': 'workspace:^'
},
devDependencies: {
playwright: '^1.54.0'
}
})
}
}
}
};

function mockReaddir(path: string) {
function recurser(segments: string[], obj: string | Record<string, unknown>): Promise<Dirent[]> {
if (segments.length === 0) {
if (typeof obj === 'string') throw new NodeError('ENOTDIR');

const dirents = Object.entries(obj)
.map(([name, each]): Dirent => {
if (typeof each === 'string') {
return {
isFile: () => true,
isDirectory: () => false,
name,
} as Dirent;
}

return {
isFile: () => false,
isDirectory: () => true,
name
} as Dirent;
});

return Promise.resolve(dirents);
}

if (typeof obj === 'string') throw new NodeError('ENOENT');

const [seg0, ...remainingSegments] = segments;
return recurser(remainingSegments, obj[seg0] as string | Record<string, unknown>);
}

const segments = path.split(pathlib.sep);
return recurser(segments, { root: mockDirectory });
}

function mockReadFile(path: string) {
function recurser(segments: string[], obj: string | Record<string, unknown>): Promise<string> {
if (segments.length === 0) {
if (typeof obj !== 'string') throw new NodeError('EISDIR');
return Promise.resolve(obj);
}

if (typeof obj === 'string') throw new NodeError('ENOENT');

const [seg0, ...remainingSegments] = segments;
return recurser(remainingSegments, obj[seg0] as string | Record<string, unknown>);
}

const segments = path.split(pathlib.sep);
return recurser(segments, { root: mockDirectory });
}

vi.spyOn(fs, 'readdir').mockImplementation(mockReaddir as any);
vi.spyOn(fs, 'readFile').mockImplementation(mockReadFile as any);

describe(getRawPackages, () => {
test('maxDepth = 1', async () => {
mockedCheckChanges.mockResolvedValueOnce(true);
const results = Object.entries(await getRawPackages('root', 1));
expect(fs.readdir).toHaveBeenCalledTimes(3);
expect(results.length).toEqual(1);

const [[name, packageData]] = results;
expect(name).toEqual('@sourceacademy/modules');
expect(packageData.hasChanges).toEqual(true);
expect(git.checkForChanges).toHaveBeenCalledOnce();
});

test('maxDepth = 3', async () => {
mockedCheckChanges.mockResolvedValue(true);
const results = await getRawPackages('root', 3);
expect(Object.values(results).length).toEqual(4);
expect(fs.readdir).toHaveBeenCalledTimes(8);

expect(results).toHaveProperty('@sourceacademy/bundle-bundle0');
const bundleResult = results['@sourceacademy/bundle-bundle0'];
expect(bundleResult.hasChanges).toEqual(true);

expect(results).toHaveProperty('@sourceacademy/tab-Tab0');
const tabResult = results['@sourceacademy/tab-Tab0'];
expect(tabResult.hasChanges).toEqual(true);

expect(results).toHaveProperty('@sourceacademy/modules-lib');
const libResult = results['@sourceacademy/modules-lib'];
expect(libResult.hasChanges).toEqual(true);
});

test('hasChanges fields accurately reflects value returned from checkChanges', async () => {
mockedCheckChanges.mockImplementation(p => {
switch (p) {
case 'root/src/bundles/bundle0':
return Promise.resolve(false);
case 'root/src/tabs/tab0':
return Promise.resolve(false);
case 'root':
return Promise.resolve(true);
}

return Promise.resolve(false);
});

const results = await getRawPackages('root');
expect(Object.keys(results).length).toEqual(4);

expect(results).toHaveProperty('@sourceacademy/modules');
expect(results['@sourceacademy/modules'].hasChanges).toEqual(true);

expect(results).toHaveProperty('@sourceacademy/bundle-bundle0');
expect(results['@sourceacademy/bundle-bundle0'].hasChanges).toEqual(false);

expect(results).toHaveProperty('@sourceacademy/tab-Tab0');
expect(results['@sourceacademy/tab-Tab0'].hasChanges).toEqual(false);

expect(results).toHaveProperty('@sourceacademy/modules-lib');
expect(results['@sourceacademy/modules-lib'].hasChanges).toEqual(false);
});
});

describe(getAllPackages, () => {
test('Transitive change dependencies', async () => {
mockedCheckChanges.mockImplementation(p => {
switch (p) {
case 'root/lib/modules-lib':
return Promise.resolve(true);
case 'root/src/bundles/bundle0':
return Promise.resolve(false);
case 'root/src/tabs/tab0':
return Promise.resolve(false);
case 'root':
return Promise.resolve(false);
}

return Promise.resolve(false);
});

const { packages: results } = await getAllPackages('root');
expect(Object.keys(results).length).toEqual(4);

expect(results).toHaveProperty('@sourceacademy/modules');
expect(results['@sourceacademy/modules'].changes).toEqual(false);

expect(results).toHaveProperty('@sourceacademy/bundle-bundle0');
expect(results['@sourceacademy/bundle-bundle0'].changes).toEqual(true);

expect(results).toHaveProperty('@sourceacademy/tab-Tab0');
expect(results['@sourceacademy/tab-Tab0'].changes).toEqual(true);

expect(results).toHaveProperty('@sourceacademy/modules-lib');
expect(results['@sourceacademy/modules-lib'].changes).toEqual(true);
});
});
Loading
Loading