diff --git a/.github/workflows/canary.yaml b/.github/workflows/canary.yaml index 59242098..3c19cf66 100644 --- a/.github/workflows/canary.yaml +++ b/.github/workflows/canary.yaml @@ -67,6 +67,27 @@ jobs: - name: Test run: wing test working-directory: checks + canary-eventbridge: + name: Test eventbridge + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + sparse-checkout: eventbridge + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 20.x + registry-url: https://registry.npmjs.org + - name: Install winglang + run: npm i -g winglang + - name: Install dependencies + run: npm install --include=dev + working-directory: eventbridge + - name: Test + run: wing test + working-directory: eventbridge canary-fifoqueue: name: Test fifoqueue runs-on: ubuntu-latest @@ -109,6 +130,27 @@ jobs: - name: Test run: wing test working-directory: github + canary-lock: + name: Test lock + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + sparse-checkout: lock + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 20.x + registry-url: https://registry.npmjs.org + - name: Install winglang + run: npm i -g winglang + - name: Install dependencies + run: npm install --include=dev + working-directory: lock + - name: Test + run: wing test + working-directory: lock canary-ngrok: name: Test ngrok runs-on: ubuntu-latest @@ -214,6 +256,27 @@ jobs: - name: Test run: wing test working-directory: sagemaker + canary-simtools: + name: Test simtools + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + sparse-checkout: simtools + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 20.x + registry-url: https://registry.npmjs.org + - name: Install winglang + run: npm i -g winglang + - name: Install dependencies + run: npm install --include=dev + working-directory: simtools + - name: Test + run: wing test + working-directory: simtools canary-vite: name: Test vite runs-on: ubuntu-latest diff --git a/.github/workflows/eventbridge-pull.yaml b/.github/workflows/eventbridge-pull.yaml index 4a133ffb..d4e97cba 100644 --- a/.github/workflows/eventbridge-pull.yaml +++ b/.github/workflows/eventbridge-pull.yaml @@ -4,7 +4,7 @@ on: paths: - eventbridge/** jobs: - build: + build-eventbridge: runs-on: ubuntu-latest steps: - name: Checkout @@ -14,7 +14,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v3 with: - node-version: 18.x + node-version: 20.x registry-url: https://registry.npmjs.org - name: Install winglang run: npm i -g winglang diff --git a/.github/workflows/eventbridge-release.yaml b/.github/workflows/eventbridge-release.yaml index 92b3bd3a..1c40e6e9 100644 --- a/.github/workflows/eventbridge-release.yaml +++ b/.github/workflows/eventbridge-release.yaml @@ -5,8 +5,9 @@ on: - main paths: - eventbridge/** + - "!eventbridge/package-lock.json" jobs: - build: + build-eventbridge: runs-on: ubuntu-latest steps: - name: Checkout @@ -16,7 +17,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v3 with: - node-version: 18.x + node-version: 20.x registry-url: https://registry.npmjs.org - name: Install winglang run: npm i -g winglang @@ -29,9 +30,25 @@ jobs: - name: Pack run: wing pack working-directory: eventbridge + - name: Get package version + run: echo WINGLIB_VERSION=$(node -p "require('./package.json').version") >> + "$GITHUB_ENV" + working-directory: eventbridge - name: Publish run: npm publish --access=public --registry https://registry.npmjs.org --tag latest *.tgz working-directory: eventbridge env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Tag commit + uses: tvdias/github-tagger@v0.0.1 + with: + repo-token: ${{ secrets.PROJEN_GITHUB_TOKEN }} + tag: eventbridge-v${{ env.WINGLIB_VERSION }} + - name: GitHub release + uses: softprops/action-gh-release@v1 + with: + name: eventbridge v${{ env.WINGLIB_VERSION }} + tag_name: eventbridge-v${{ env.WINGLIB_VERSION }} + files: "*.tgz" + token: ${{ secrets.PROJEN_GITHUB_TOKEN }} diff --git a/.github/workflows/lock-pull.yaml b/.github/workflows/lock-pull.yaml index 8f41b4d3..ae31af7d 100644 --- a/.github/workflows/lock-pull.yaml +++ b/.github/workflows/lock-pull.yaml @@ -4,7 +4,7 @@ on: paths: - lock/** jobs: - build: + build-lock: runs-on: ubuntu-latest steps: - name: Checkout @@ -14,7 +14,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v3 with: - node-version: 18.x + node-version: 20.x registry-url: https://registry.npmjs.org - name: Install winglang run: npm i -g winglang diff --git a/.github/workflows/lock-release.yaml b/.github/workflows/lock-release.yaml index 3c45344d..55210ab4 100644 --- a/.github/workflows/lock-release.yaml +++ b/.github/workflows/lock-release.yaml @@ -5,8 +5,9 @@ on: - main paths: - lock/** + - "!lock/package-lock.json" jobs: - build: + build-lock: runs-on: ubuntu-latest steps: - name: Checkout @@ -16,7 +17,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v3 with: - node-version: 18.x + node-version: 20.x registry-url: https://registry.npmjs.org - name: Install winglang run: npm i -g winglang @@ -29,9 +30,25 @@ jobs: - name: Pack run: wing pack working-directory: lock + - name: Get package version + run: echo WINGLIB_VERSION=$(node -p "require('./package.json').version") >> + "$GITHUB_ENV" + working-directory: lock - name: Publish run: npm publish --access=public --registry https://registry.npmjs.org --tag latest *.tgz working-directory: lock env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Tag commit + uses: tvdias/github-tagger@v0.0.1 + with: + repo-token: ${{ secrets.PROJEN_GITHUB_TOKEN }} + tag: lock-v${{ env.WINGLIB_VERSION }} + - name: GitHub release + uses: softprops/action-gh-release@v1 + with: + name: lock v${{ env.WINGLIB_VERSION }} + tag_name: lock-v${{ env.WINGLIB_VERSION }} + files: "*.tgz" + token: ${{ secrets.PROJEN_GITHUB_TOKEN }} diff --git a/.github/workflows/simtools-pull.yaml b/.github/workflows/simtools-pull.yaml new file mode 100644 index 00000000..e8b06565 --- /dev/null +++ b/.github/workflows/simtools-pull.yaml @@ -0,0 +1,29 @@ +name: simtools-pull +on: + pull_request: + paths: + - simtools/** +jobs: + build-simtools: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + sparse-checkout: simtools + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 20.x + registry-url: https://registry.npmjs.org + - name: Install winglang + run: npm i -g winglang + - name: Install dependencies + run: npm install --include=dev + working-directory: simtools + - name: Test + run: wing test + working-directory: simtools + - name: Pack + run: wing pack + working-directory: simtools diff --git a/.github/workflows/simtools-release.yaml b/.github/workflows/simtools-release.yaml new file mode 100644 index 00000000..ef31dcc1 --- /dev/null +++ b/.github/workflows/simtools-release.yaml @@ -0,0 +1,54 @@ +name: simtools-release +on: + push: + branches: + - main + paths: + - simtools/** + - "!simtools/package-lock.json" +jobs: + build-simtools: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + sparse-checkout: simtools + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 20.x + registry-url: https://registry.npmjs.org + - name: Install winglang + run: npm i -g winglang + - name: Install dependencies + run: npm install --include=dev + working-directory: simtools + - name: Test + run: wing test + working-directory: simtools + - name: Pack + run: wing pack + working-directory: simtools + - name: Get package version + run: echo WINGLIB_VERSION=$(node -p "require('./package.json').version") >> + "$GITHUB_ENV" + working-directory: simtools + - name: Publish + run: npm publish --access=public --registry https://registry.npmjs.org --tag + latest *.tgz + working-directory: simtools + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Tag commit + uses: tvdias/github-tagger@v0.0.1 + with: + repo-token: ${{ secrets.PROJEN_GITHUB_TOKEN }} + tag: simtools-v${{ env.WINGLIB_VERSION }} + - name: GitHub release + uses: softprops/action-gh-release@v1 + with: + name: simtools v${{ env.WINGLIB_VERSION }} + tag_name: simtools-v${{ env.WINGLIB_VERSION }} + files: "*.tgz" + token: ${{ secrets.PROJEN_GITHUB_TOKEN }} diff --git a/.mergify.yml b/.mergify.yml index b10827f4..bc0d934c 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -44,12 +44,18 @@ pull_request_rules: - -check-failure=build-containers - -check-pending=build-containers - -check-stale=build-containers + - -check-failure=build-eventbridge + - -check-pending=build-eventbridge + - -check-stale=build-eventbridge - -check-failure=build-fifoqueue - -check-pending=build-fifoqueue - -check-stale=build-fifoqueue - -check-failure=build-github - -check-pending=build-github - -check-stale=build-github + - -check-failure=build-lock + - -check-pending=build-lock + - -check-stale=build-lock - -check-failure=build-ngrok - -check-pending=build-ngrok - -check-stale=build-ngrok @@ -65,6 +71,9 @@ pull_request_rules: - -check-failure=build-sagemaker - -check-pending=build-sagemaker - -check-stale=build-sagemaker + - -check-failure=build-simtools + - -check-pending=build-simtools + - -check-stale=build-simtools - -check-failure=build-vite - -check-pending=build-vite - -check-stale=build-vite @@ -98,12 +107,18 @@ pull_request_rules: - -check-failure=build-containers - -check-pending=build-containers - -check-stale=build-containers + - -check-failure=build-eventbridge + - -check-pending=build-eventbridge + - -check-stale=build-eventbridge - -check-failure=build-fifoqueue - -check-pending=build-fifoqueue - -check-stale=build-fifoqueue - -check-failure=build-github - -check-pending=build-github - -check-stale=build-github + - -check-failure=build-lock + - -check-pending=build-lock + - -check-stale=build-lock - -check-failure=build-ngrok - -check-pending=build-ngrok - -check-stale=build-ngrok @@ -119,6 +134,9 @@ pull_request_rules: - -check-failure=build-sagemaker - -check-pending=build-sagemaker - -check-stale=build-sagemaker + - -check-failure=build-simtools + - -check-pending=build-simtools + - -check-stale=build-simtools - -check-failure=build-vite - -check-pending=build-vite - -check-stale=build-vite diff --git a/containers/package-lock.json b/containers/package-lock.json index 5a1aa38e..ea40dc32 100644 --- a/containers/package-lock.json +++ b/containers/package-lock.json @@ -1,12 +1,12 @@ { "name": "@winglibs/containers", - "version": "0.0.21", + "version": "0.0.23", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@winglibs/containers", - "version": "0.0.21", + "version": "0.0.23", "license": "MIT", "dependencies": { "@cdktf/provider-aws": "^18.0.5", diff --git a/containers/package.json b/containers/package.json index 7935a6b6..500c357e 100644 --- a/containers/package.json +++ b/containers/package.json @@ -1,6 +1,6 @@ { "name": "@winglibs/containers", - "version": "0.0.22", + "version": "0.0.23", "description": "Container support for Wing", "repository": { "type": "git", diff --git a/containers/workload.sim.w b/containers/workload.sim.w index 2870b3a4..d8aba665 100644 --- a/containers/workload.sim.w +++ b/containers/workload.sim.w @@ -8,7 +8,6 @@ bring "./utils.w" as utils; pub class Workload_sim { publicUrlKey: str?; internalUrlKey: str?; - containerIdKey: str; pub publicUrl: str?; pub internalUrl: str?; @@ -18,12 +17,12 @@ pub class Workload_sim { imageTag: str; public: bool; state: sim.State; - + new(props: api.WorkloadProps) { this.appDir = utils.entrypointDir(this); this.props = props; this.state = new sim.State(); - this.containerIdKey = "container_id"; + let containerName = util.uuidv4(); let hash = utils.resolveContentHash(this, props); if let hash = hash { @@ -50,109 +49,117 @@ pub class Workload_sim { this.internalUrlKey = key; } - let s = new cloud.Service(inflight () => { - this.start(); - return () => { this.stop(); }; - }); - - std.Node.of(s).hidden = true; - std.Node.of(this.state).hidden = true; - } - - inflight start(): void { - log("starting workload..."); + let containerService = new cloud.Service(inflight () => { + log("starting workload..."); - let opts = this.props; + let opts = this.props; - // if this a reference to a local directory, build the image from a docker file - if utils.isPathInflight(opts.image) { - // check if the image is already built - try { - utils.shell("docker", ["inspect", this.imageTag]); - log("image {this.imageTag} already exists"); - } catch { - log("building locally from {opts.image} and tagging {this.imageTag}..."); - utils.shell("docker", ["build", "-t", this.imageTag, opts.image], this.appDir); - } - } else { - try { - utils.shell("docker", ["inspect", this.imageTag]); - log("image {this.imageTag} already exists"); - } catch { - log("pulling {this.imageTag}"); - utils.shell("docker", ["pull", this.imageTag]); + // if this a reference to a local directory, build the image from a docker file + if utils.isPathInflight(opts.image) { + // check if the image is already built + try { + utils.shell("docker", ["inspect", this.imageTag]); + log("image {this.imageTag} already exists"); + } catch { + log("building locally from {opts.image} and tagging {this.imageTag}..."); + utils.shell("docker", ["build", "-t", this.imageTag, opts.image], this.appDir); + } + } else { + try { + utils.shell("docker", ["inspect", this.imageTag]); + log("image {this.imageTag} already exists"); + } catch { + log("pulling {this.imageTag}"); + utils.shell("docker", ["pull", this.imageTag]); + } } - } - // start the new container - let dockerRun = MutArray[]; - dockerRun.push("run"); - dockerRun.push("--detach"); + // start the new container + let dockerRun = MutArray[]; + dockerRun.push("run"); + dockerRun.push("--detach"); + dockerRun.push("--rm"); - if let port = opts.port { - dockerRun.push("-p"); - dockerRun.push("{port}"); - } + dockerRun.push("--name", containerName); - if let env = opts.env { - if env.size() > 0 { - dockerRun.push("-e"); - for k in env.keys() { - dockerRun.push("{k}={env.get(k)!}"); - } + if let port = opts.port { + dockerRun.push("-p"); + dockerRun.push("{port}"); } - } - - dockerRun.push(this.imageTag); - if let runArgs = this.props.args { - for a in runArgs { - dockerRun.push(a); + if let env = opts.env { + if env.size() > 0 { + dockerRun.push("-e"); + for k in env.keys() { + dockerRun.push("{k}={env.get(k)!}"); + } + } } - } - log("starting container from image {this.imageTag}"); - log("docker {dockerRun.join(" ")}"); - let containerId = utils.shell("docker", dockerRun.copy()).trim(); - this.state.set(this.containerIdKey, containerId); + dockerRun.push(this.imageTag); - log("containerId={containerId}"); + if let runArgs = this.props.args { + for a in runArgs { + dockerRun.push(a); + } + } - let out = Json.parse(utils.shell("docker", ["inspect", containerId])); + log("starting container from image {this.imageTag}"); + log("docker {dockerRun.join(" ")}"); + utils.shell("docker", dockerRun.copy()); + + log("containerName={containerName}"); + + return () => { + utils.shell("docker", ["rm", "-f", containerName]); + }; + }) as "ContainerService"; + std.Node.of(containerService).hidden = true; + + let readinessService = new cloud.Service(inflight () => { + let opts = this.props; + let var out: Json? = nil; + util.waitUntil(inflight () => { + try { + out = Json.parse(utils.shell("docker", ["inspect", containerName])); + return true; + } catch { + log("something went wrong"); + return false; + } + }, interval: 0.1s); - if let port = opts.port { - let hostPort = out.tryGetAt(0)?.tryGet("NetworkSettings")?.tryGet("Ports")?.tryGet("{port}/tcp")?.tryGetAt(0)?.tryGet("HostPort")?.tryAsStr(); - if !hostPort? { - throw "Container does not listen to port {port}"; - } + if let port = opts.port { + let hostPort = out?.tryGetAt(0)?.tryGet("NetworkSettings")?.tryGet("Ports")?.tryGet("{port}/tcp")?.tryGetAt(0)?.tryGet("HostPort")?.tryAsStr(); + if !hostPort? { + throw "Container does not listen to port {port}"; + } - let publicUrl = "http://localhost:{hostPort!}"; + let publicUrl = "http://localhost:{hostPort!}"; - if let k = this.publicUrlKey { - this.state.set(k, publicUrl); - } + if let k = this.publicUrlKey { + this.state.set(k, publicUrl); + } - if let k = this.internalUrlKey { - this.state.set(k, "http://host.docker.internal:{hostPort!}"); - } + if let k = this.internalUrlKey { + this.state.set(k, "http://host.docker.internal:{hostPort!}"); + } - if let readiness = opts.readiness { - let readinessUrl = "{publicUrl}{readiness}"; - log("waiting for container to be ready: {readinessUrl}..."); - util.waitUntil(inflight () => { - try { - return http.get(readinessUrl).ok; - } catch { - return false; - } - }, interval: 0.1s); + if let readiness = opts.readiness { + let readinessUrl = "{publicUrl}{readiness}"; + log("waiting for container to be ready: {readinessUrl}..."); + util.waitUntil(inflight () => { + try { + return http.get(readinessUrl).ok; + } catch { + return false; + } + }, interval: 0.1s); + } } - } - } + }) as "ReadinessService"; + std.Node.of(readinessService).hidden = true; - inflight stop() { - let containerId = this.state.get(this.containerIdKey).asStr(); - log("stopping container {containerId}"); - utils.shell("docker", ["rm", "-f", containerId]); + std.Node.of(this.state).hidden = true; } -} \ No newline at end of file +} diff --git a/postgres/package.json b/postgres/package.json index 381de879..0be396d8 100644 --- a/postgres/package.json +++ b/postgres/package.json @@ -1,6 +1,6 @@ { "name": "@winglibs/postgres", - "version": "0.0.7", + "version": "0.0.8", "description": "Postgres support for Wing", "repository": { "type": "git", @@ -18,7 +18,7 @@ "dependencies": { "@rybickic/cdktf-provider-neon": "^1.0.0", "@cdktf/provider-aws": "^18.0.4", - "@winglibs/containers": "^0.0.18", + "@winglibs/containers": "^0.0.22", "pg": "^8.11.3" }, "license": "MIT" diff --git a/redis/package.json b/redis/package.json index 09cdd1ad..ff8156f1 100644 --- a/redis/package.json +++ b/redis/package.json @@ -1,6 +1,6 @@ { "name": "@winglibs/redis", - "version": "0.0.3", + "version": "0.0.4", "description": "Redis resource for Wing", "repository": { "type": "git", @@ -13,7 +13,7 @@ }, "license": "MIT", "dependencies": { - "@winglibs/containers": "^0.0.18", + "@winglibs/containers": "^0.0.22", "redis": "^4.6.11" } } diff --git a/simtools/.gitignore b/simtools/.gitignore new file mode 100644 index 00000000..297fdef9 --- /dev/null +++ b/simtools/.gitignore @@ -0,0 +1,2 @@ +target/ +node_modules/ diff --git a/simtools/LICENSE b/simtools/LICENSE new file mode 100644 index 00000000..a875f479 --- /dev/null +++ b/simtools/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Wing + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/simtools/README.md b/simtools/README.md new file mode 100644 index 00000000..af5c7b2f --- /dev/null +++ b/simtools/README.md @@ -0,0 +1,53 @@ +# simtools + +This library is a set of tools that are supposed to make the user of the simulator a happier developer. + +For the time being, it contains only one function, `addMacro()`. + +## Using `addMacro` + +This function adds a Macro into the target resource's interaction pane in Wing Console. +Every macro that is added is seen as a button on the right side panel. + +The following code: +```wing +bring cloud; +bring simtools; + +let bucket = new cloud.Bucket(); + +simtools.addMacro(bucket, "Clean", inflight () => { + for i in bucket.list() { + bucket.delete(i); + } +}); + +simtools.addMacro(bucket, "Populate", inflight () => { + for i in 1..10 { + bucket.put("{i}.txt", "This is {i}"); + } +}); +``` + +Will create two buttons on the Bucket resource on the right side panel: +* Clean +* Populate + +![image](https://github.com/winglang/winglibs/assets/1727147/909be141-f0f3-4c7c-aa1b-9c7ba5aae560) + + + +## Prerequisites + +* [winglang](https://winglang.io). + +## Installation + +```sh +npm i @winglibs/simtools +``` + + +## License + +This library is licensed under the [MIT License](./LICENSE). diff --git a/simtools/lib.test.w b/simtools/lib.test.w new file mode 100644 index 00000000..1a9a4b36 --- /dev/null +++ b/simtools/lib.test.w @@ -0,0 +1,16 @@ +bring cloud; +bring "./lib.w" as simtools; + +let bucket = new cloud.Bucket(); + +simtools.addMacro(bucket, "Clean", inflight () => { + for i in bucket.list() { + bucket.delete(i); + } +}); + +simtools.addMacro(bucket, "Populate", inflight () => { + for i in 1..10 { + bucket.put("{i}.txt", "This is {i}"); + } +}); diff --git a/simtools/lib.w b/simtools/lib.w new file mode 100644 index 00000000..3669849d --- /dev/null +++ b/simtools/lib.w @@ -0,0 +1,10 @@ +bring ui; +bring util; + +pub class Util { + pub static addMacro(target: std.IResource, name: str, fn: inflight ():void ){ + if util.env("WING_TARGET") == "sim" { + new ui.Button(name, fn) as name in target; + } + } +} diff --git a/simtools/package.json b/simtools/package.json new file mode 100644 index 00000000..42a3ece4 --- /dev/null +++ b/simtools/package.json @@ -0,0 +1,15 @@ +{ + "name": "@winglibs/simtools", + "description": "Wing simulator utility library", + "version": "0.0.1", + "repository": { + "type": "git", + "url": "https://github.com/winglang/winglibs.git", + "directory": "simtools" + }, + "author": { + "name": "Eyal Keren", + "email": "eyalk@wing.cloud" + }, + "license": "MIT" +}