- commit
- 54f6fc8
- parent
- cab4009
- author
- Jacob Bolda
- date
- 2024-01-30 04:05:41 +0000 UTC
ecosystem CI tests (#36) * initial CI setup * fix CI workflow name * consistent CI workflow name with file name * script to symlink and CI workflow update to run build * fix folder name in example dir * try --refresh-lockfile * try with npm * try with --no-lockfile * try with npm including build * npm run build * run as matrix * don't fail fast * skip remove of ./npm/node_modules * do file: install for parcel instead * keep node_modules for parcel * matrix out path chunks * lint fix * another lint fix * fix CI name * install both examples * dynamically pull matching branch * nested folder * quiet script * throw on failed reponse * pass branch * more error context * bad boop * name branch step * lint * build and test examples * remove GITHUB_TOKEN * directly append in script * add logs * dump output * dump output file * dump step * .outputs * lint * really need to fix my local linter * add a bit to the readme * rename .scripts/ to scripts/ * update script references
5 files changed,
+159,
-1
+73,
-0
1@@ -0,0 +1,73 @@
2+name: test-ecosystem
3+
4+on:
5+ push:
6+ branches: main
7+ pull_request:
8+ branches: main
9+
10+permissions:
11+ contents: read
12+
13+jobs:
14+ test-ecosystem:
15+ name: ${{ matrix.example.repo }}/${{ matrix.example.folder }}
16+ runs-on: ubuntu-latest
17+ strategy:
18+ fail-fast: false
19+ matrix:
20+ example:
21+ - owner: neurosnap
22+ repo: starfx-examples
23+ folder: vite-react
24+ - owner: neurosnap
25+ repo: starfx-examples
26+ folder: parcel-react
27+ - owner: neurosnap
28+ repo: starfx-examples
29+ folder: tests-rtl
30+ steps:
31+ - name: checkout main repo
32+ uses: actions/checkout@v4
33+ with:
34+ repository: "neurosnap/starfx"
35+ path: "starfx"
36+
37+ - name: setup deno
38+ uses: denoland/setup-deno@v1
39+ with:
40+ deno-version: v1.x
41+
42+ # determines branch and sets it as output available through the `id`
43+ - name: dynamically determine ${{ matrix.example.owner }}/${{ matrix.example.repo }} branch
44+ id: conditionalBranch
45+ run: deno run -A ./starfx/scripts/branch-exists.ts $GITHUB_HEAD_REF neurosnap/starfx-examples
46+
47+ - name: checkout ${{ matrix.example.owner }}/${{ matrix.example.repo }} on ${{ steps.conditionalBranch.outputs.branch }}
48+ uses: actions/checkout@v4
49+ with:
50+ repository: ${{ matrix.example.owner }}/${{ matrix.example.repo }}
51+ path: ${{ matrix.example.repo }}
52+ ref: ${{ steps.conditionalBranch.outputs.branch }}
53+
54+ - name: bundle for npm
55+ run: deno task npm 0.0.0
56+ working-directory: starfx
57+
58+ # install in example repos
59+ - name: install ${{ matrix.example.owner }}/${{ matrix.example.repo }}
60+ working-directory: ${{ matrix.example.repo }}/${{ matrix.example.folder }}
61+ run: npm install
62+
63+ # symlink example repos
64+ - name: symlink built assets
65+ run: deno task sync-build-to install ${{ matrix.example.repo }}/${{ matrix.example.folder }}
66+ working-directory: starfx
67+
68+ # run build and test in example repos
69+ - name: build ${{ matrix.example.owner }}/${{ matrix.example.repo }}
70+ working-directory: ${{ matrix.example.repo }}/${{ matrix.example.folder }}
71+ run: npm run build --if-present
72+ - name: test ${{ matrix.example.owner }}/${{ matrix.example.repo }}
73+ working-directory: ${{ matrix.example.repo }}/${{ matrix.example.folder }}
74+ run: npm run test --if-present
+2,
-1
1@@ -2,7 +2,8 @@
2 "tasks": {
3 "types": "deno run --allow-write ./api-type-template.ts",
4 "npm": "deno run -A ./npm.ts",
5- "test": "deno test --allow-env --allow-read"
6+ "test": "deno test --allow-env --allow-read",
7+ "sync-build-to": "deno run -A ./scripts/sync.ts"
8 },
9 "lint": {
10 "exclude": ["npm/", "examples/"],
+52,
-0
1@@ -0,0 +1,52 @@
2+import { call, main, type Operation } from "./deps.ts";
3+
4+await main(function* (): Operation<void> {
5+ // based on env created from ${{ secrets.GITHUB_TOKEN }} in CI
6+ const token = Deno.env.get("GITHUB_TOKEN");
7+ const [branch, ownerRepo] = Deno.args;
8+ console.dir({ branch, ownerRepo });
9+
10+ const response = yield* call(
11+ fetch(`https://api.github.com/repos/${ownerRepo}/branches`, {
12+ headers: {
13+ Accept: "application/vnd.github+json",
14+ "X-GitHub-Api-Version": "2022-11-28",
15+ // the token isn't required but helps with rate limiting
16+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
17+ },
18+ }),
19+ );
20+
21+ if (response.ok) {
22+ const branches = yield* call(response.json());
23+ const branchList = branches.map((branch: { name: string }) => branch.name);
24+ // for CI debug purposes
25+ console.dir({ branchList });
26+ // GitHub Actions maintains the step output through a file which you append keys into
27+ // the path that file is available as an env var
28+ if (Deno.env.get("CI")) {
29+ const output = Deno.env.get("GITHUB_OUTPUT");
30+ if (!output) throw new Error("$GITHUB_OUTPUT is not set");
31+ const encoder = new TextEncoder();
32+ if (branchList.includes(branch)) {
33+ const data = encoder.encode(`branch=${branch}`);
34+ yield* call(Deno.writeFile(output, data, { append: true }));
35+ } else {
36+ const data = encoder.encode("branch=main");
37+ yield* call(Deno.writeFile(output, data, { append: true }));
38+ }
39+ }
40+ // always log out the branch for both CI and local running
41+ if (branchList.includes(branch)) {
42+ console.log(`branch=${branch}`);
43+ } else {
44+ console.log(`branch=main`);
45+ }
46+ } else {
47+ console.error(
48+ `Error trying to fetch https://api.github.com/repos/${ownerRepo}/branches and check for ${branch}`,
49+ );
50+ const text = yield* call(response.text());
51+ throw new Error(text);
52+ }
53+});
+2,
-0
1@@ -0,0 +1,2 @@
2+export type { Operation } from "https://deno.land/x/effection@3.0.0-beta.3/mod.ts";
3+export { call, main } from "https://deno.land/x/effection@3.0.0-beta.3/mod.ts";
+30,
-0
1@@ -0,0 +1,30 @@
2+import { call, main, type Operation } from "./deps.ts";
3+
4+await main(function* (): Operation<void> {
5+ const [syncMethod, folderFromArgs] = Deno.args;
6+ const folder = folderFromArgs ?? "starfx-examples/vite-react";
7+ const dir = `../${folder}/node_modules/starfx`;
8+ const npmAssets = yield* call(Deno.realPath("./npm"));
9+
10+ if (syncMethod === "install") {
11+ // parcel doesn't handle symlinks well, do a `file:` install instead
12+ const command = new Deno.Command("npm", {
13+ args: ["add", "starfx@file:../../starfx/npm", "--install-links"],
14+ cwd: `../${folder}`,
15+ stderr: "piped",
16+ stdout: "piped",
17+ });
18+ yield* call(command.output());
19+ } else if (syncMethod === "symlink") {
20+ // this option is primarily for local usage
21+ try {
22+ yield* call(Deno.remove(dir, { recursive: true }));
23+ } catch (_error) {
24+ // assume that the folder does not exist
25+ }
26+
27+ // create a symlink to the `dir` which should allow
28+ // this example to run with the build assets
29+ yield* call(Deno.symlink(npmAssets, dir));
30+ }
31+});