From 928a7fbd49e10dabf7f9c6ab17b58b0e16fbb62f Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 12 Apr 2024 23:07:21 +0300 Subject: [PATCH] chore: organize and refactor mkrepo (#201) Move all the repo generation code to a directory `.mkrepo` and create a script called `./mkrepo.sh` at the root of the repository to execute it. Refactor the code by enriching the API of `Library` to encapsulate all the logic in one place. --- .github/workflows/pull-request-diff.yaml | 7 ++- canary.w => .mkrepo/canary.w | 11 +++-- library.w => .mkrepo/library.w | 51 ++++++++++++++------ generate-workflows.main.w => .mkrepo/main.w | 11 +++-- mergify.w => .mkrepo/mergify.w | 10 ++-- pr-diff.w => .mkrepo/pr-diff.w | 4 +- pr-lint.w => .mkrepo/pr-lint.w | 11 ++++- readme.w => .mkrepo/readme.w | 20 +++----- stale.w => .mkrepo/stale.w | 0 util.extern.d.ts => .mkrepo/util.extern.d.ts | 2 +- util.js => .mkrepo/util.js | 5 +- README.md | 20 ++++++-- mklib.sh | 2 +- mkrepo.sh | 2 + 14 files changed, 101 insertions(+), 55 deletions(-) rename canary.w => .mkrepo/canary.w (87%) rename library.w => .mkrepo/library.w (71%) rename generate-workflows.main.w => .mkrepo/main.w (83%) rename mergify.w => .mkrepo/mergify.w (92%) rename pr-diff.w => .mkrepo/pr-diff.w (84%) rename pr-lint.w => .mkrepo/pr-lint.w (85%) rename readme.w => .mkrepo/readme.w (51%) rename stale.w => .mkrepo/stale.w (100%) rename util.extern.d.ts => .mkrepo/util.extern.d.ts (63%) rename util.js => .mkrepo/util.js (57%) create mode 100755 mkrepo.sh diff --git a/.github/workflows/pull-request-diff.yaml b/.github/workflows/pull-request-diff.yaml index 25794c04..0882d747 100644 --- a/.github/workflows/pull-request-diff.yaml +++ b/.github/workflows/pull-request-diff.yaml @@ -14,8 +14,7 @@ jobs: - name: Install winglang run: npm i -g winglang - name: Update config files - run: wing compile generate-workflows.main.w + run: ./mkrepo.sh - name: Check for missing changes - run: git diff --exit-code || (echo 'Please run "wing compile - generate-workflows.main.w" from the root of the repository, and commit - any changes to your branch.' && exit 1) + run: git diff --exit-code || (echo 'Please run "./mkrepo.sh" from the root of + the repository, and commit any changes to your branch.' && exit 1) diff --git a/canary.w b/.mkrepo/canary.w similarity index 87% rename from canary.w rename to .mkrepo/canary.w index 67e84084..492d8f3d 100644 --- a/canary.w +++ b/.mkrepo/canary.w @@ -1,7 +1,8 @@ bring fs; +bring "./library.w" as l; pub class CanaryWorkflow { - new(workflowdir: str, libs: Array, skipLibs: Array?) { + new(workflowdir: str, libs: Array, skipLibs: Array?) { let testLibSteps = (lib: str): Array => { let var testCommand = "wing test"; @@ -57,13 +58,13 @@ pub class CanaryWorkflow { let jobs = MutJson {}; for lib in libs { - if (skipLibs ?? []).contains(lib) { + if (skipLibs ?? []).contains(lib.name) { continue; } - jobs.set("canary-{lib}", { - name: "Test {lib}", + jobs.set("canary-{lib.name}", { + name: "Test {lib.name}", "runs-on": "ubuntu-latest", - steps: testLibSteps(lib), + steps: testLibSteps(lib.name), }); } diff --git a/library.w b/.mkrepo/library.w similarity index 71% rename from library.w rename to .mkrepo/library.w index 7f9c9673..755100b9 100644 --- a/library.w +++ b/.mkrepo/library.w @@ -2,20 +2,42 @@ bring fs; struct PackageManifest { name: str; + wing: WingOptions?; +} + +struct WingOptions { + platforms: Array?; } pub class Library { + extern "./util.js" static sortedArray(arr: Array): Array; + + pub name: str; + pub dir: str; // relative to root of the repo + pub platforms: Array; + pub buildJob: str; + pub manifest: PackageManifest; // package.json + new(workflowdir: str, libdir: str) { + this.dir = libdir; + this.name = fs.basename(libdir); let pkgjsonpath = "{libdir}/package.json"; let pkgjson = fs.readJson(pkgjsonpath); - let manifest = PackageManifest.fromJson(pkgjson); - log(manifest.name); - let base = fs.basename(libdir); - let expected = "@winglibs/{base}"; - if manifest.name != expected { + this.manifest = PackageManifest.fromJson(pkgjson); + + log(this.manifest.name); + this.buildJob = "build-{this.name}"; + let expected = "@winglibs/{this.name}"; + if this.manifest.name != expected { throw "'name' in {pkgjsonpath} is expected to be {expected}"; } + + this.platforms = Library.sortedArray(this.manifest.wing?.platforms ?? []); + if this.platforms.length == 0 { + throw "\"{this.name}\" winglib does not have a `wing.platforms` field in its package.json."; + } + let addCommonSteps = (steps: MutArray) => { let var testCommand = "wing test"; @@ -62,7 +84,6 @@ pub class Library { run: "wing pack", "working-directory": libdir, }); - }; let releaseSteps = MutArray[]; @@ -86,7 +107,7 @@ pub class Library { } }); - let tagName = "{base}-v\$\{\{ env.WINGLIB_VERSION \}\}"; + let tagName = "{this.name}-v\$\{\{ env.WINGLIB_VERSION \}\}"; let githubTokenWithAuth = "\$\{\{ secrets.PROJEN_GITHUB_TOKEN }}"; releaseSteps.push({ @@ -102,7 +123,7 @@ pub class Library { name: "GitHub release", uses: "softprops/action-gh-release@v1", with: { - name: "{base} v\$\{\{ env.WINGLIB_VERSION \}\}", + name: "{this.name} v\$\{\{ env.WINGLIB_VERSION \}\}", tag_name: tagName, files: "*.tgz", token: githubTokenWithAuth, @@ -110,12 +131,12 @@ pub class Library { }); let releaseJobs = MutJson {}; - releaseJobs.set("build-{base}", { + releaseJobs.set(this.buildJob, { "runs-on": "ubuntu-latest", steps: releaseSteps.copy(), }); - fs.writeYaml("{workflowdir}/{base}-release.yaml", { - name: "{base}-release", + fs.writeYaml("{workflowdir}/{this.name}-release.yaml", { + name: "{this.name}-release", on: { push: { branches: ["main"], @@ -129,12 +150,14 @@ pub class Library { }); let pullJobs = MutJson {}; - pullJobs.set("build-{base}", { + + pullJobs.set("build-{this.name}", { "runs-on": "ubuntu-latest", steps: pullSteps.copy(), }); - fs.writeYaml("{workflowdir}/{base}-pull.yaml", { - name: "{base}-pull", + + fs.writeYaml("{workflowdir}/{this.name}-pull.yaml", { + name: "{this.name}-pull", on: { pull_request: { paths: ["{libdir}/**"], diff --git a/generate-workflows.main.w b/.mkrepo/main.w similarity index 83% rename from generate-workflows.main.w rename to .mkrepo/main.w index 38fbffd2..45597571 100644 --- a/generate-workflows.main.w +++ b/.mkrepo/main.w @@ -13,16 +13,19 @@ let workflowdir = ".github/workflows"; fs.remove(workflowdir); fs.mkdir(workflowdir); -let libs = MutArray[]; +let libs = MutArray[]; for file in fs.readdir(".") { + if file.startsWith(".") { + continue; + } + if !fs.exists("{file}/package.json") { - log("skipping {file}"); continue; } - new l.Library(workflowdir, file) as file; - libs.push(file); + let lib = new l.Library(workflowdir, file) as file; + libs.push(lib); } readme.update(libs.copy()); diff --git a/mergify.w b/.mkrepo/mergify.w similarity index 92% rename from mergify.w rename to .mkrepo/mergify.w index 2b11a83b..60ef91e9 100644 --- a/mergify.w +++ b/.mkrepo/mergify.w @@ -1,14 +1,16 @@ bring fs; +bring "./library.w" as l; pub class MergifyWorkflow { - new(libs: Array) { + new(libs: Array) { let buildChecks = MutArray[]; buildChecks.push("check-success=Validate PR title"); buildChecks.push("check-success=Check for mutations"); + for lib in libs { - buildChecks.push("-check-failure=build-{lib}"); - buildChecks.push("-check-pending=build-{lib}"); - buildChecks.push("-check-stale=build-{lib}"); + buildChecks.push("-check-failure={lib.buildJob}"); + buildChecks.push("-check-pending={lib.buildJob}"); + buildChecks.push("-check-stale={lib.buildJob}"); } fs.writeYaml(".mergify.yml", { diff --git a/pr-diff.w b/.mkrepo/pr-diff.w similarity index 84% rename from pr-diff.w rename to .mkrepo/pr-diff.w index 4d1ae565..38cfb12d 100644 --- a/pr-diff.w +++ b/.mkrepo/pr-diff.w @@ -28,11 +28,11 @@ pub class PullRequestDiffWorkflow { }, { "name": "Update config files", - "run": "wing compile generate-workflows.main.w", + "run": "./mkrepo.sh", }, { "name": "Check for missing changes", - "run": "git diff --exit-code || (echo 'Please run \"wing compile generate-workflows.main.w\" from the root of the repository, and commit any changes to your branch.' && exit 1)", + "run": "git diff --exit-code || (echo 'Please run \"./mkrepo.sh\" from the root of the repository, and commit any changes to your branch.' && exit 1)", }, ], }, diff --git a/pr-lint.w b/.mkrepo/pr-lint.w similarity index 85% rename from pr-lint.w rename to .mkrepo/pr-lint.w index d13a6933..97846fbc 100644 --- a/pr-lint.w +++ b/.mkrepo/pr-lint.w @@ -1,7 +1,8 @@ bring fs; +bring "./library.w" as l; pub class PullRequestLintWorkflow { - new(workflowdir: str, libs: Array) { + new(workflowdir: str, libs: Array) { let var types = MutArray[ "feat", "fix", @@ -10,7 +11,13 @@ pub class PullRequestLintWorkflow { "rfc", "revert", ]; - types = types.concat(libs.copyMut()); + + let names = MutArray[]; + for l in libs { + names.push(l.name); + } + + types = types.concat(names); fs.writeYaml("{workflowdir}/pull-request-lint.yaml", { name: "Pull Request Lint", diff --git a/readme.w b/.mkrepo/readme.w similarity index 51% rename from readme.w rename to .mkrepo/readme.w index b47bd8b4..77b1ae08 100644 --- a/readme.w +++ b/.mkrepo/readme.w @@ -1,10 +1,10 @@ bring fs; +bring "./library.w" as l; pub class Util { extern "./util.js" static arraySlice(arr: Array, start: num, end: num): MutArray; - extern "./util.js" static arraySort(arr: MutArray): void; - pub static update(libraries: Array) { + pub static update(libraries: Array) { let readme = fs.readFile("README.md"); let lines = readme.split("\n"); @@ -20,20 +20,14 @@ pub class Util { newLines.push("| Library | npm package | Platforms |"); newLines.push("| --- | --- | --- |"); for lib in libraries { - let var line = "| [{lib}](./{lib})"; - line += " | [@winglibs/{lib}](https://www.npmjs.com/package/@winglibs/{lib})"; - let pkgJson = fs.readFile("{lib}/package.json"); - let pkg = Json.parse(pkgJson); - let platforms: MutArray = unsafeCast(pkg.tryGet("wing")?.tryGet("platforms")) ?? []; - if platforms.length == 0 { - throw "\"{lib}\" winglib does not have a `wing.platforms` field in its package.json."; - } - Util.arraySort(platforms); - line += " | " + platforms.join(", ") + " |"; + let var line = "| [{lib.name}](./{lib.dir})"; + line += " | [@winglibs/{lib.name}](https://www.npmjs.com/package/@winglibs/{lib.name})"; + let pkg = lib.manifest; + line += " | " + lib.platforms.join(", ") + " |"; newLines.push(line); } newLines.push(""); - newLines.push("_Generated with `wing compile generate-workflows.w`. To update the list of supported platforms for a winglib, please update the \"wing\" section in its package.json file._"); + newLines.push("_Generated with `mkrepo.sh`. To update the list of supported platforms for a winglib, please update the \"wing\" section in its package.json file._"); newLines.push(""); let finalLines = newLines.concat(Util.arraySlice(lines, end, lines.length)); diff --git a/stale.w b/.mkrepo/stale.w similarity index 100% rename from stale.w rename to .mkrepo/stale.w diff --git a/util.extern.d.ts b/.mkrepo/util.extern.d.ts similarity index 63% rename from util.extern.d.ts rename to .mkrepo/util.extern.d.ts index f1164a7a..83c8c2c9 100644 --- a/util.extern.d.ts +++ b/.mkrepo/util.extern.d.ts @@ -1,4 +1,4 @@ export default interface extern { arraySlice: (arr: (readonly (string)[]), start: number, end: number) => (string)[], - arraySort: (arr: (string)[]) => void, + sortedArray: (arr: (readonly (string)[])) => (readonly (string)[]), } diff --git a/util.js b/.mkrepo/util.js similarity index 57% rename from util.js rename to .mkrepo/util.js index 2da5a851..0871965d 100644 --- a/util.js +++ b/.mkrepo/util.js @@ -1,6 +1,7 @@ exports.arraySlice = function(array, start, end) { return Array.prototype.slice.call(array, start, end); }; -exports.arraySort = function(array) { - return Array.prototype.sort.call(array); + +exports.sortedArray = function(array) { + return array.sort(); } diff --git a/README.md b/README.md index f3a51677..6874ac30 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ Welcome! You've arrived to the warm and cozy home of the *Wing Trusted Library Ecosystem*. -This repository hosts the code for [Wing](https://winglang.io) libraries that we consider trusted -and that meet our community's quality bar. +This repository hosts the code for [Wing](https://winglang.io) libraries (also called "winglibs") +that we consider trusted and that meet our community's quality bar. One of the cool things about trusted libraries is that we take care of building, testing and publishing them for you. @@ -35,10 +35,24 @@ publishing them for you. | [vite](./vite) | [@winglibs/vite](https://www.npmjs.com/package/@winglibs/vite) | sim, tf-aws | | [websockets](./websockets) | [@winglibs/websockets](https://www.npmjs.com/package/@winglibs/websockets) | awscdk, sim, tf-aws | -_Generated with `wing compile generate-workflows.w`. To update the list of supported platforms for a winglib, please update the "wing" section in its package.json file._ +_Generated with `mkrepo.sh`. To update the list of supported platforms for a winglib, please update the "wing" section in its package.json file._ +## How is this repository structured? + +The code for each library is located in a subdirectory named after the library. For example, the +`websockets` library is located under [`./websockets`](./websockets/). + +Wing libraries are published to npm under the `@winglibs` scope, and there's a `package.json` file +in the library's directory. + +A set of GitHub Workflows are maintained for each library under the [.github](./github/) directory. +These workflows, as well as other artifacts in this repository (such as the table of contents in +this README) are are generated using a tool called `mkrepo`, which can be executed using the +`./mkrepo.sh` script at the root of this repository. The source code for this tool is can be found +under [.mkrepo](./.mkrepo/) (and it is written in Wing of course). + ## How do I add a new library? It's so damn easy. diff --git a/mklib.sh b/mklib.sh index 2cf3a151..6756100d 100755 --- a/mklib.sh +++ b/mklib.sh @@ -76,7 +76,7 @@ HERE cp ./LICENSE $1/ -wing compile generate-workflows.main.w +./mkrepo.sh rm -fr target/ cd $1 diff --git a/mkrepo.sh b/mkrepo.sh new file mode 100755 index 00000000..befabf6b --- /dev/null +++ b/mkrepo.sh @@ -0,0 +1,2 @@ +#!/bin/sh +wing compile .mkrepo/main.w \ No newline at end of file