From 32dcabc9cce514e4c0ccc09d1fb4ec8ba2671fe9 Mon Sep 17 00:00:00 2001 From: Tsiry Sandratraina Date: Mon, 4 Mar 2024 06:31:37 +0000 Subject: [PATCH] make it work with Node.js and Bun fix example --- .github/workflows/ci.yml | 14 +- .github/workflows/example.yml | 2 +- .github/workflows/zenith.yml | 10 + README.md | 11 +- ci.ts | 7 +- deno.json | 3 + deno.lock | 205 +++++++ deps.ts | 52 +- example/.fluentci/deno.lock | 205 +++++++ example/.fluentci/deps.ts | 52 +- example/.fluentci/sdk/builder.ts | 5 +- example/.fluentci/sdk/client.gen.ts | 511 ++++++++++++++---- .../sdk/common/errors/DaggerSDKError.ts | 46 ++ .../errors/DockerImageRefValidationError.ts | 28 + .../EngineSessionConnectParamsParseError.ts | 31 ++ .../EngineSessionConnectionTimeoutError.ts | 31 ++ .../errors/EngineSessionErrorOptions.ts | 20 + .../.fluentci/sdk/common/errors/ExecError.ts | 54 ++ .../sdk/common/errors/GraphQLRequestError.ts | 36 ++ .../errors/InitEngineSessionBinaryError.ts | 17 + .../common/errors/NotAwaitedRequestError.ts | 17 + .../errors/TooManyNestedObjectsError.ts | 27 + .../sdk/common/errors/UnknownDaggerError.ts | 17 + .../sdk/common/errors/errors-codes.ts | 63 +++ example/.fluentci/sdk/common/errors/index.ts | 12 + example/.fluentci/sdk/common/errors/types.ts | 16 + example/.fluentci/sdk/common/utils.ts | 4 + example/.fluentci/src/dagger/jobs.ts | 22 +- example/.fluentci/src/dagger/lib.ts | 3 +- example/.fluentci/src/dagger/pipeline.ts | 7 +- example/apply.gql | 9 - example/init.gql | 9 - example/plan.gql | 9 - example/validate.gql | 5 - sdk/builder.ts | 5 +- sdk/client.gen.ts | 511 ++++++++++++++---- sdk/common/errors/DaggerSDKError.ts | 46 ++ .../errors/DockerImageRefValidationError.ts | 28 + .../EngineSessionConnectParamsParseError.ts | 31 ++ .../EngineSessionConnectionTimeoutError.ts | 31 ++ .../errors/EngineSessionErrorOptions.ts | 20 + sdk/common/errors/ExecError.ts | 54 ++ sdk/common/errors/GraphQLRequestError.ts | 36 ++ .../errors/InitEngineSessionBinaryError.ts | 17 + sdk/common/errors/NotAwaitedRequestError.ts | 17 + .../errors/TooManyNestedObjectsError.ts | 27 + sdk/common/errors/UnknownDaggerError.ts | 17 + sdk/common/errors/errors-codes.ts | 63 +++ sdk/common/errors/index.ts | 12 + sdk/common/errors/types.ts | 16 + sdk/common/utils.ts | 4 + src/dagger/jobs.ts | 16 +- src/dagger/lib.ts | 3 +- src/dagger/pipeline.ts | 7 +- 54 files changed, 2180 insertions(+), 341 deletions(-) create mode 100644 example/.fluentci/sdk/common/errors/DaggerSDKError.ts create mode 100644 example/.fluentci/sdk/common/errors/DockerImageRefValidationError.ts create mode 100644 example/.fluentci/sdk/common/errors/EngineSessionConnectParamsParseError.ts create mode 100644 example/.fluentci/sdk/common/errors/EngineSessionConnectionTimeoutError.ts create mode 100644 example/.fluentci/sdk/common/errors/EngineSessionErrorOptions.ts create mode 100644 example/.fluentci/sdk/common/errors/ExecError.ts create mode 100644 example/.fluentci/sdk/common/errors/GraphQLRequestError.ts create mode 100644 example/.fluentci/sdk/common/errors/InitEngineSessionBinaryError.ts create mode 100644 example/.fluentci/sdk/common/errors/NotAwaitedRequestError.ts create mode 100644 example/.fluentci/sdk/common/errors/TooManyNestedObjectsError.ts create mode 100644 example/.fluentci/sdk/common/errors/UnknownDaggerError.ts create mode 100644 example/.fluentci/sdk/common/errors/errors-codes.ts create mode 100644 example/.fluentci/sdk/common/errors/index.ts create mode 100644 example/.fluentci/sdk/common/errors/types.ts create mode 100644 example/.fluentci/sdk/common/utils.ts delete mode 100644 example/apply.gql delete mode 100644 example/init.gql delete mode 100644 example/plan.gql delete mode 100644 example/validate.gql create mode 100644 sdk/common/errors/DaggerSDKError.ts create mode 100644 sdk/common/errors/DockerImageRefValidationError.ts create mode 100644 sdk/common/errors/EngineSessionConnectParamsParseError.ts create mode 100644 sdk/common/errors/EngineSessionConnectionTimeoutError.ts create mode 100644 sdk/common/errors/EngineSessionErrorOptions.ts create mode 100644 sdk/common/errors/ExecError.ts create mode 100644 sdk/common/errors/GraphQLRequestError.ts create mode 100644 sdk/common/errors/InitEngineSessionBinaryError.ts create mode 100644 sdk/common/errors/NotAwaitedRequestError.ts create mode 100644 sdk/common/errors/TooManyNestedObjectsError.ts create mode 100644 sdk/common/errors/UnknownDaggerError.ts create mode 100644 sdk/common/errors/errors-codes.ts create mode 100644 sdk/common/errors/index.ts create mode 100644 sdk/common/errors/types.ts create mode 100644 sdk/common/utils.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98cf2b5..a7b526e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,6 @@ # Do not edit this file directly. It is generated by https://deno.land/x/fluent_github_actions -name: Tests +name: ci on: push: branches: @@ -14,9 +14,19 @@ jobs: uses: fluentci-io/setup-fluentci@v4 - name: Run Dagger Pipelines run: | - fluentci run deno_pipeline + fluentci run deno_pipeline fmt test dagger -m github.com/fluent-ci-templates/terraform-pipeline@main functions - name: Upload to Codecov run: fluentci run codecov_pipeline env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + publish: + needs: tests + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@v4 + - name: Publish package + run: npx jsr publish --allow-slow-types diff --git a/.github/workflows/example.yml b/.github/workflows/example.yml index 1f9b8da..92c57f6 100644 --- a/.github/workflows/example.yml +++ b/.github/workflows/example.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v2 - uses: denoland/setup-deno@v1 with: - deno-version: v1.37 + deno-version: v1.41 - name: Setup Fluent CI CLI run: deno install -A -r https://cli.fluentci.io -n fluentci - name: Setup Dagger diff --git a/.github/workflows/zenith.yml b/.github/workflows/zenith.yml index 1508c09..7f336b8 100644 --- a/.github/workflows/zenith.yml +++ b/.github/workflows/zenith.yml @@ -28,3 +28,13 @@ jobs: working-directory: example env: DAGGER_CLOUD_TOKEN: ${{ secrets.DAGGER_CLOUD_TOKEN }} + publish: + needs: tests + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@v4 + - name: Publish package + run: npx jsr publish --allow-slow-types diff --git a/README.md b/README.md index 016d55a..454242b 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![fluentci pipeline](https://img.shields.io/badge/dynamic/json?label=pkg.fluentci.io&labelColor=%23000&color=%23460cf1&url=https%3A%2F%2Fapi.fluentci.io%2Fv1%2Fpipeline%2Fterraform_pipeline&query=%24.version)](https://pkg.fluentci.io/terraform_pipeline) ![deno compatibility](https://shield.deno.dev/deno/^1.37) [![dagger-min-version](https://img.shields.io/badge/dagger-v0.10.0-blue?color=3D66FF&labelColor=000000)](https://dagger.io) +[![ci](https://github.com/fluent-ci-templates/terraform-pipeline/actions/workflows/ci.yml/badge.svg)](https://github.com/fluent-ci-templates/terraform-pipeline/actions/workflows/ci.yml) A ready-to-use CI/CD Pipeline for managing your infrastructure with [Terraform](https://www.terraform.io/). @@ -28,7 +29,7 @@ Now you can run the pipeline with: fluentci run . ``` -## Dagger Module +## 🧩 Dagger Module Use as a [Dagger](https://dagger.io) module: @@ -51,7 +52,7 @@ dagger call apply --src . \ --google-application-credentials /path/to/credentials.json ``` -## Environment variables +## 🛠️ Environment variables | Variable | Description | | --------------------------- | -------------------------------------------------- | @@ -74,7 +75,7 @@ dagger call apply --src . \ | TF_PLUGIN_CACHE_DIR | The Terraform plugin cache directory | | TF_IGNORE | Display ignored files and directories | -## Jobs +## ✨ Jobs | Job | Description | | --------- | -------------------------------------- | @@ -108,12 +109,12 @@ apply( ): Promise ``` -## Programmatic usage +## 👨‍💻 Programmatic usage You can also use this pipeline programmatically: ```ts -import { init, validate, plan, apply } from "https://pkg.fluentci.io/terraform_pipeline@v0.6.5/mod.ts"; +import { init, validate, plan, apply } from "jsr:@fluentci/terraform"; await init(); await validate(); diff --git a/ci.ts b/ci.ts index 0934195..c7773d0 100644 --- a/ci.ts +++ b/ci.ts @@ -1,9 +1,4 @@ -import { - init, - validate, - plan, - apply, -} from "https://pkg.fluentci.io/terraform_pipeline@v0.6.5/mod.ts"; +import { init, validate, plan, apply } from "jsr:@fluentci/terraform"; await init(); await validate(); diff --git a/deno.json b/deno.json index e0e77b5..3e8b0d4 100644 --- a/deno.json +++ b/deno.json @@ -1,4 +1,7 @@ { + "name": "@fluentci/terraform", + "version": "0.7.0", + "exports": "./mod.ts", "importMap": "import_map.json", "tasks": { "esm:add": "deno run -A https://esm.sh/v128 add", diff --git a/deno.lock b/deno.lock index 1a439e8..fd9c639 100644 --- a/deno.lock +++ b/deno.lock @@ -1,5 +1,210 @@ { "version": "3", + "packages": { + "specifiers": { + "jsr:@std/assert@^0.217.0": "jsr:@std/assert@0.217.0", + "jsr:@std/assert@^0.218.2": "jsr:@std/assert@0.218.2", + "jsr:@std/flags@0.218.2": "jsr:@std/flags@0.218.2", + "jsr:@std/fmt@0.218.2": "jsr:@std/fmt@0.218.2", + "jsr:@std/fmt@^0.217.0": "jsr:@std/fmt@0.217.0", + "jsr:@std/fmt@^0.218.2": "jsr:@std/fmt@0.218.2", + "jsr:@std/path@0.218.2": "jsr:@std/path@0.218.2", + "jsr:@std/testing@0.217.0": "jsr:@std/testing@0.217.0", + "jsr:@std/testing@0.218.2": "jsr:@std/testing@0.218.2", + "jsr:@tsirysndr/env-js@0.1.2": "jsr:@tsirysndr/env-js@0.1.2", + "jsr:@tsirysndr/env-js@0.1.3": "jsr:@tsirysndr/env-js@0.1.3", + "jsr:@tsirysndr/exit-js@0.1.0": "jsr:@tsirysndr/exit-js@0.1.0", + "jsr:@tsirysndr/fluent-az-pipelines@0.3": "jsr:@tsirysndr/fluent-az-pipelines@0.3.0", + "jsr:@tsirysndr/fluent-circleci@0.3": "jsr:@tsirysndr/fluent-circleci@0.3.0", + "jsr:@tsirysndr/fluent-codepipeline@0.3": "jsr:@tsirysndr/fluent-codepipeline@0.3.0", + "jsr:@tsirysndr/fluent-gh-actions@0.3": "jsr:@tsirysndr/fluent-gh-actions@0.3.0", + "jsr:@tsirysndr/fluent-gitlab-ci@0.5": "jsr:@tsirysndr/fluent-gitlab-ci@0.5.0", + "npm:graphql-request@6.1.0": "npm:graphql-request@6.1.0_graphql@16.8.1", + "npm:graphql@16.8.1": "npm:graphql@16.8.1", + "npm:lodash@4.17.21": "npm:lodash@4.17.21", + "npm:node-color-log@11.0.2": "npm:node-color-log@11.0.2", + "npm:stringify-tree@1.1.1": "npm:stringify-tree@1.1.1", + "npm:yaml@2.3.1": "npm:yaml@2.3.1", + "npm:zod@3.22.1": "npm:zod@3.22.1" + }, + "jsr": { + "@std/assert@0.217.0": { + "integrity": "c98e279362ca6982d5285c3b89517b757c1e3477ee9f14eb2fdf80a45aaa9642", + "dependencies": [ + "jsr:@std/fmt@^0.217.0" + ] + }, + "@std/assert@0.218.2": { + "integrity": "7f0a5a1a8cf86607cd6c2c030584096e1ffad27fc9271429a8cb48cfbdee5eaf", + "dependencies": [ + "jsr:@std/fmt@^0.218.2" + ] + }, + "@std/flags@0.218.2": { + "integrity": "0d4e8ac15e7dfede26153c63a6d55d0aad56ae88beb2ede38c14c775dfc5b25e", + "dependencies": [ + "jsr:@std/assert@^0.218.2" + ] + }, + "@std/fmt@0.217.0": { + "integrity": "cb99f82500b8da20202fedfa8bb94dd0222e81f0494ed9087de20ee3d8a39a8d" + }, + "@std/fmt@0.218.2": { + "integrity": "99526449d2505aa758b6cbef81e7dd471d8b28ec0dcb1491d122b284c548788a" + }, + "@std/path@0.218.2": { + "integrity": "b568fd923d9e53ad76d17c513e7310bda8e755a3e825e6289a0ce536404e2662", + "dependencies": [ + "jsr:@std/assert@^0.218.2" + ] + }, + "@std/testing@0.217.0": { + "integrity": "97508b254ca1888d512215288bfb3f192a4e6e84336ba56b189c7862258a058b", + "dependencies": [ + "jsr:@std/assert@^0.217.0" + ] + }, + "@std/testing@0.218.2": { + "integrity": "49410b23584c924533786e6c117d71486c1daa65f4911fd6cfc95e4edba9de7f", + "dependencies": [ + "jsr:@std/assert@^0.218.2" + ] + }, + "@tsirysndr/env-js@0.1.2": { + "integrity": "16a8cf4e60c8b43f4d62dd762006de40d56e5b144a56c0954a11f99ee12c5d3a" + }, + "@tsirysndr/env-js@0.1.3": { + "integrity": "53d7f072a9b97aef27e219917fcd38fae520cac931f0d9f86753e07b9c862d06" + }, + "@tsirysndr/exit-js@0.1.0": { + "integrity": "4ea378ce2575931426bcf60d4588c9e9cf489fa93d3907cd9ee60feb38960230" + }, + "@tsirysndr/fluent-az-pipelines@0.3.0": { + "integrity": "a2a23089a186b0f04e45daa7a9df98527c54b845842c1ebe3b7f2cf03e5aec0d", + "dependencies": [ + "jsr:@std/testing@0.217.0", + "npm:yaml@2.3.1", + "npm:zod@3.22.1" + ] + }, + "@tsirysndr/fluent-circleci@0.3.0": { + "integrity": "f2ab207d83b7b2a728a6708a51c3ad93cf2d89b08a13460793e3b6c7af8f5dd9", + "dependencies": [ + "jsr:@std/testing@0.217.0", + "npm:yaml@2.3.1", + "npm:zod@3.22.1" + ] + }, + "@tsirysndr/fluent-codepipeline@0.3.0": { + "integrity": "3050df3fed469d6791831a0a83529de77732d14c27f4a1446788de2c740c73df", + "dependencies": [ + "jsr:@std/testing@0.217.0", + "npm:yaml@2.3.1", + "npm:zod@3.22.1" + ] + }, + "@tsirysndr/fluent-gh-actions@0.3.0": { + "integrity": "2eaff18fbe9b25042fbb321d3bec61a34a15f736ec95bd2da214dcd1c3b8d5cd", + "dependencies": [ + "jsr:@std/testing@0.217.0", + "npm:yaml@2.3.1", + "npm:zod@3.22.1" + ] + }, + "@tsirysndr/fluent-gitlab-ci@0.5.0": { + "integrity": "57e7d231375902358d2bd5b63766f8ffb7030157a9e3764d5e0b0fb7533dd3f9", + "dependencies": [ + "jsr:@std/testing@0.217.0", + "npm:yaml@2.3.1", + "npm:zod@3.22.1" + ] + } + }, + "npm": { + "@graphql-typed-document-node/core@3.2.0_graphql@16.8.1": { + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "dependencies": { + "graphql": "graphql@16.8.1" + } + }, + "@types/lodash.flatten@4.4.9": { + "integrity": "sha512-JCW9xofpn9oJfFSccpBRF8IrB5guqmcKZIa7J9DnZqLd9wgGYbewaYnjbNw3Fb+St8BHVsnGmmS0A3j99LII3Q==", + "dependencies": { + "@types/lodash": "@types/lodash@4.14.202" + } + }, + "@types/lodash@4.14.202": { + "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", + "dependencies": {} + }, + "cross-fetch@3.1.8": { + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dependencies": { + "node-fetch": "node-fetch@2.7.0" + } + }, + "graphql-request@6.1.0_graphql@16.8.1": { + "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", + "dependencies": { + "@graphql-typed-document-node/core": "@graphql-typed-document-node/core@3.2.0_graphql@16.8.1", + "cross-fetch": "cross-fetch@3.1.8", + "graphql": "graphql@16.8.1" + } + }, + "graphql@16.8.1": { + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", + "dependencies": {} + }, + "lodash.flatten@4.4.0": { + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dependencies": {} + }, + "lodash@4.17.21": { + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dependencies": {} + }, + "node-color-log@11.0.2": { + "integrity": "sha512-+gD5pQpVpEkEA3He9STku4VL1EO9SaOW3HElumCd3xWorulnfr2053NCSVwPCXrkwI5ihPYucQxSCSOuS1q+Eg==", + "dependencies": {} + }, + "node-fetch@2.7.0": { + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "whatwg-url@5.0.0" + } + }, + "stringify-tree@1.1.1": { + "integrity": "sha512-lVfVX+HJ9Gx2NUv0vJTRhqCPYlgzbdR25MF34Md1Bjq6jvJocOLgfHhusYtBSKi/bwpkgLGjtF/dVZlBbA6oZw==", + "dependencies": { + "@types/lodash.flatten": "@types/lodash.flatten@4.4.9", + "lodash.flatten": "lodash.flatten@4.4.0" + } + }, + "tr46@0.0.3": { + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dependencies": {} + }, + "webidl-conversions@3.0.1": { + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dependencies": {} + }, + "whatwg-url@5.0.0": { + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "tr46@0.0.3", + "webidl-conversions": "webidl-conversions@3.0.1" + } + }, + "yaml@2.3.1": { + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "dependencies": {} + }, + "zod@3.22.1": { + "integrity": "sha512-+qUhAMl414+Elh+fRNtpU+byrwjDFOS1N7NioLY+tSlcADTx4TkCUua/hxJvxwDXcV4397/nZ420jy4n4+3WUg==", + "dependencies": {} + } + } + }, "remote": { "https://cdn.jsdelivr.net/gh/tsirysndr/tar@v0.1.1/deps.ts": "096395daebc7ed8a18f0484e4ffcc3a7f70e50946735f7df9611a7fcfd8272cc", "https://cdn.jsdelivr.net/gh/tsirysndr/tar@v0.1.1/mod.ts": "e269d71c72ae68e82c1960e5db2a0c7419c97c9683ef717de0ab75d90f364713", diff --git a/deps.ts b/deps.ts index 1ec36cc..c41a356 100644 --- a/deps.ts +++ b/deps.ts @@ -1,25 +1,24 @@ -export { assertEquals } from "https://deno.land/std@0.191.0/testing/asserts.ts"; +export { assertEquals } from "jsr:@std/testing@0.218.2/asserts"; export type { DirectoryID, SecretID } from "./sdk/client.gen.ts"; -export { Directory, Secret, File, Container, dag } from "./sdk/client.gen.ts"; -export { connect, uploadContext } from "https://sdk.fluentci.io/v0.3.0/mod.ts"; -export { brightGreen } from "https://deno.land/std@0.191.0/fmt/colors.ts"; -export { withDevbox } from "https://nix.fluentci.io/v0.5.3/src/dagger/steps.ts"; -export { stringifyTree } from "https://esm.sh/stringify-tree@1.1.1"; -import gql from "https://esm.sh/graphql-tag@2.12.6"; +export { Container, File, Directory, Secret, dag } from "./sdk/client.gen.ts"; +export { brightGreen } from "jsr:@std/fmt@0.218.2/colors"; +export { stringifyTree } from "npm:stringify-tree@1.1.1"; +import { gql } from "npm:graphql-request@6.1.0"; export { gql }; -export { - dirname, - join, - resolve, -} from "https://deno.land/std@0.203.0/path/mod.ts"; -export { parse } from "https://deno.land/std@0.205.0/flags/mod.ts"; -export { snakeCase, camelCase } from "https://cdn.skypack.dev/lodash"; +export { dirname, join, resolve } from "jsr:@std/path@0.218.2"; +export { parse } from "jsr:@std/flags@0.218.2"; -export { - ClientError, - GraphQLClient, -} from "https://esm.sh/v128/graphql-request@6.1.0"; +import * as _ from "npm:lodash@4.17.21"; +const snakeCase = _.default.snakeCase; +const camelCase = _.default.camelCase; +export { snakeCase, camelCase }; + +import * as env from "jsr:@tsirysndr/env-js@0.1.3"; +export { env }; +export { exit } from "jsr:@tsirysndr/exit-js@0.1.0"; + +export { ClientError, GraphQLClient } from "npm:graphql-request@6.1.0"; export { DaggerSDKError, UnknownDaggerError, @@ -33,15 +32,10 @@ export { EngineSessionConnectionTimeoutError, NotAwaitedRequestError, ERROR_CODES, -} from "https://esm.sh/@dagger.io/dagger@0.9.3"; - -export type { - CallbackFct, - ConnectOpts, -} from "https://sdk.fluentci.io/v0.3.0/mod.ts"; +} from "./sdk/common/errors/index.ts"; -export * as FluentGitlabCI from "https://deno.land/x/fluent_gitlab_ci@v0.4.2/mod.ts"; -export * as FluentGithubActions from "https://deno.land/x/fluent_github_actions@v0.2.1/mod.ts"; -export * as FluentCircleCI from "https://deno.land/x/fluent_circleci@v0.2.5/mod.ts"; -export * as FluentAzurePipelines from "https://deno.land/x/fluent_azure_pipelines@v0.2.0/mod.ts"; -export * as FluentAWSCodePipeline from "https://deno.land/x/fluent_aws_codepipeline@v0.2.3/mod.ts"; +export * as FluentGitlabCI from "jsr:@tsirysndr/fluent-gitlab-ci@0.5"; +export * as FluentGithubActions from "jsr:@tsirysndr/fluent-gh-actions@0.3"; +export * as FluentCircleCI from "jsr:@tsirysndr/fluent-circleci@0.3"; +export * as FluentAzurePipelines from "jsr:@tsirysndr/fluent-az-pipelines@0.3"; +export * as FluentAWSCodePipeline from "jsr:@tsirysndr/fluent-codepipeline@0.3"; diff --git a/example/.fluentci/deno.lock b/example/.fluentci/deno.lock index 1a439e8..fd9c639 100644 --- a/example/.fluentci/deno.lock +++ b/example/.fluentci/deno.lock @@ -1,5 +1,210 @@ { "version": "3", + "packages": { + "specifiers": { + "jsr:@std/assert@^0.217.0": "jsr:@std/assert@0.217.0", + "jsr:@std/assert@^0.218.2": "jsr:@std/assert@0.218.2", + "jsr:@std/flags@0.218.2": "jsr:@std/flags@0.218.2", + "jsr:@std/fmt@0.218.2": "jsr:@std/fmt@0.218.2", + "jsr:@std/fmt@^0.217.0": "jsr:@std/fmt@0.217.0", + "jsr:@std/fmt@^0.218.2": "jsr:@std/fmt@0.218.2", + "jsr:@std/path@0.218.2": "jsr:@std/path@0.218.2", + "jsr:@std/testing@0.217.0": "jsr:@std/testing@0.217.0", + "jsr:@std/testing@0.218.2": "jsr:@std/testing@0.218.2", + "jsr:@tsirysndr/env-js@0.1.2": "jsr:@tsirysndr/env-js@0.1.2", + "jsr:@tsirysndr/env-js@0.1.3": "jsr:@tsirysndr/env-js@0.1.3", + "jsr:@tsirysndr/exit-js@0.1.0": "jsr:@tsirysndr/exit-js@0.1.0", + "jsr:@tsirysndr/fluent-az-pipelines@0.3": "jsr:@tsirysndr/fluent-az-pipelines@0.3.0", + "jsr:@tsirysndr/fluent-circleci@0.3": "jsr:@tsirysndr/fluent-circleci@0.3.0", + "jsr:@tsirysndr/fluent-codepipeline@0.3": "jsr:@tsirysndr/fluent-codepipeline@0.3.0", + "jsr:@tsirysndr/fluent-gh-actions@0.3": "jsr:@tsirysndr/fluent-gh-actions@0.3.0", + "jsr:@tsirysndr/fluent-gitlab-ci@0.5": "jsr:@tsirysndr/fluent-gitlab-ci@0.5.0", + "npm:graphql-request@6.1.0": "npm:graphql-request@6.1.0_graphql@16.8.1", + "npm:graphql@16.8.1": "npm:graphql@16.8.1", + "npm:lodash@4.17.21": "npm:lodash@4.17.21", + "npm:node-color-log@11.0.2": "npm:node-color-log@11.0.2", + "npm:stringify-tree@1.1.1": "npm:stringify-tree@1.1.1", + "npm:yaml@2.3.1": "npm:yaml@2.3.1", + "npm:zod@3.22.1": "npm:zod@3.22.1" + }, + "jsr": { + "@std/assert@0.217.0": { + "integrity": "c98e279362ca6982d5285c3b89517b757c1e3477ee9f14eb2fdf80a45aaa9642", + "dependencies": [ + "jsr:@std/fmt@^0.217.0" + ] + }, + "@std/assert@0.218.2": { + "integrity": "7f0a5a1a8cf86607cd6c2c030584096e1ffad27fc9271429a8cb48cfbdee5eaf", + "dependencies": [ + "jsr:@std/fmt@^0.218.2" + ] + }, + "@std/flags@0.218.2": { + "integrity": "0d4e8ac15e7dfede26153c63a6d55d0aad56ae88beb2ede38c14c775dfc5b25e", + "dependencies": [ + "jsr:@std/assert@^0.218.2" + ] + }, + "@std/fmt@0.217.0": { + "integrity": "cb99f82500b8da20202fedfa8bb94dd0222e81f0494ed9087de20ee3d8a39a8d" + }, + "@std/fmt@0.218.2": { + "integrity": "99526449d2505aa758b6cbef81e7dd471d8b28ec0dcb1491d122b284c548788a" + }, + "@std/path@0.218.2": { + "integrity": "b568fd923d9e53ad76d17c513e7310bda8e755a3e825e6289a0ce536404e2662", + "dependencies": [ + "jsr:@std/assert@^0.218.2" + ] + }, + "@std/testing@0.217.0": { + "integrity": "97508b254ca1888d512215288bfb3f192a4e6e84336ba56b189c7862258a058b", + "dependencies": [ + "jsr:@std/assert@^0.217.0" + ] + }, + "@std/testing@0.218.2": { + "integrity": "49410b23584c924533786e6c117d71486c1daa65f4911fd6cfc95e4edba9de7f", + "dependencies": [ + "jsr:@std/assert@^0.218.2" + ] + }, + "@tsirysndr/env-js@0.1.2": { + "integrity": "16a8cf4e60c8b43f4d62dd762006de40d56e5b144a56c0954a11f99ee12c5d3a" + }, + "@tsirysndr/env-js@0.1.3": { + "integrity": "53d7f072a9b97aef27e219917fcd38fae520cac931f0d9f86753e07b9c862d06" + }, + "@tsirysndr/exit-js@0.1.0": { + "integrity": "4ea378ce2575931426bcf60d4588c9e9cf489fa93d3907cd9ee60feb38960230" + }, + "@tsirysndr/fluent-az-pipelines@0.3.0": { + "integrity": "a2a23089a186b0f04e45daa7a9df98527c54b845842c1ebe3b7f2cf03e5aec0d", + "dependencies": [ + "jsr:@std/testing@0.217.0", + "npm:yaml@2.3.1", + "npm:zod@3.22.1" + ] + }, + "@tsirysndr/fluent-circleci@0.3.0": { + "integrity": "f2ab207d83b7b2a728a6708a51c3ad93cf2d89b08a13460793e3b6c7af8f5dd9", + "dependencies": [ + "jsr:@std/testing@0.217.0", + "npm:yaml@2.3.1", + "npm:zod@3.22.1" + ] + }, + "@tsirysndr/fluent-codepipeline@0.3.0": { + "integrity": "3050df3fed469d6791831a0a83529de77732d14c27f4a1446788de2c740c73df", + "dependencies": [ + "jsr:@std/testing@0.217.0", + "npm:yaml@2.3.1", + "npm:zod@3.22.1" + ] + }, + "@tsirysndr/fluent-gh-actions@0.3.0": { + "integrity": "2eaff18fbe9b25042fbb321d3bec61a34a15f736ec95bd2da214dcd1c3b8d5cd", + "dependencies": [ + "jsr:@std/testing@0.217.0", + "npm:yaml@2.3.1", + "npm:zod@3.22.1" + ] + }, + "@tsirysndr/fluent-gitlab-ci@0.5.0": { + "integrity": "57e7d231375902358d2bd5b63766f8ffb7030157a9e3764d5e0b0fb7533dd3f9", + "dependencies": [ + "jsr:@std/testing@0.217.0", + "npm:yaml@2.3.1", + "npm:zod@3.22.1" + ] + } + }, + "npm": { + "@graphql-typed-document-node/core@3.2.0_graphql@16.8.1": { + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "dependencies": { + "graphql": "graphql@16.8.1" + } + }, + "@types/lodash.flatten@4.4.9": { + "integrity": "sha512-JCW9xofpn9oJfFSccpBRF8IrB5guqmcKZIa7J9DnZqLd9wgGYbewaYnjbNw3Fb+St8BHVsnGmmS0A3j99LII3Q==", + "dependencies": { + "@types/lodash": "@types/lodash@4.14.202" + } + }, + "@types/lodash@4.14.202": { + "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", + "dependencies": {} + }, + "cross-fetch@3.1.8": { + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dependencies": { + "node-fetch": "node-fetch@2.7.0" + } + }, + "graphql-request@6.1.0_graphql@16.8.1": { + "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", + "dependencies": { + "@graphql-typed-document-node/core": "@graphql-typed-document-node/core@3.2.0_graphql@16.8.1", + "cross-fetch": "cross-fetch@3.1.8", + "graphql": "graphql@16.8.1" + } + }, + "graphql@16.8.1": { + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", + "dependencies": {} + }, + "lodash.flatten@4.4.0": { + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dependencies": {} + }, + "lodash@4.17.21": { + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dependencies": {} + }, + "node-color-log@11.0.2": { + "integrity": "sha512-+gD5pQpVpEkEA3He9STku4VL1EO9SaOW3HElumCd3xWorulnfr2053NCSVwPCXrkwI5ihPYucQxSCSOuS1q+Eg==", + "dependencies": {} + }, + "node-fetch@2.7.0": { + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "whatwg-url@5.0.0" + } + }, + "stringify-tree@1.1.1": { + "integrity": "sha512-lVfVX+HJ9Gx2NUv0vJTRhqCPYlgzbdR25MF34Md1Bjq6jvJocOLgfHhusYtBSKi/bwpkgLGjtF/dVZlBbA6oZw==", + "dependencies": { + "@types/lodash.flatten": "@types/lodash.flatten@4.4.9", + "lodash.flatten": "lodash.flatten@4.4.0" + } + }, + "tr46@0.0.3": { + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dependencies": {} + }, + "webidl-conversions@3.0.1": { + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dependencies": {} + }, + "whatwg-url@5.0.0": { + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "tr46@0.0.3", + "webidl-conversions": "webidl-conversions@3.0.1" + } + }, + "yaml@2.3.1": { + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "dependencies": {} + }, + "zod@3.22.1": { + "integrity": "sha512-+qUhAMl414+Elh+fRNtpU+byrwjDFOS1N7NioLY+tSlcADTx4TkCUua/hxJvxwDXcV4397/nZ420jy4n4+3WUg==", + "dependencies": {} + } + } + }, "remote": { "https://cdn.jsdelivr.net/gh/tsirysndr/tar@v0.1.1/deps.ts": "096395daebc7ed8a18f0484e4ffcc3a7f70e50946735f7df9611a7fcfd8272cc", "https://cdn.jsdelivr.net/gh/tsirysndr/tar@v0.1.1/mod.ts": "e269d71c72ae68e82c1960e5db2a0c7419c97c9683ef717de0ab75d90f364713", diff --git a/example/.fluentci/deps.ts b/example/.fluentci/deps.ts index 1ec36cc..c41a356 100644 --- a/example/.fluentci/deps.ts +++ b/example/.fluentci/deps.ts @@ -1,25 +1,24 @@ -export { assertEquals } from "https://deno.land/std@0.191.0/testing/asserts.ts"; +export { assertEquals } from "jsr:@std/testing@0.218.2/asserts"; export type { DirectoryID, SecretID } from "./sdk/client.gen.ts"; -export { Directory, Secret, File, Container, dag } from "./sdk/client.gen.ts"; -export { connect, uploadContext } from "https://sdk.fluentci.io/v0.3.0/mod.ts"; -export { brightGreen } from "https://deno.land/std@0.191.0/fmt/colors.ts"; -export { withDevbox } from "https://nix.fluentci.io/v0.5.3/src/dagger/steps.ts"; -export { stringifyTree } from "https://esm.sh/stringify-tree@1.1.1"; -import gql from "https://esm.sh/graphql-tag@2.12.6"; +export { Container, File, Directory, Secret, dag } from "./sdk/client.gen.ts"; +export { brightGreen } from "jsr:@std/fmt@0.218.2/colors"; +export { stringifyTree } from "npm:stringify-tree@1.1.1"; +import { gql } from "npm:graphql-request@6.1.0"; export { gql }; -export { - dirname, - join, - resolve, -} from "https://deno.land/std@0.203.0/path/mod.ts"; -export { parse } from "https://deno.land/std@0.205.0/flags/mod.ts"; -export { snakeCase, camelCase } from "https://cdn.skypack.dev/lodash"; +export { dirname, join, resolve } from "jsr:@std/path@0.218.2"; +export { parse } from "jsr:@std/flags@0.218.2"; -export { - ClientError, - GraphQLClient, -} from "https://esm.sh/v128/graphql-request@6.1.0"; +import * as _ from "npm:lodash@4.17.21"; +const snakeCase = _.default.snakeCase; +const camelCase = _.default.camelCase; +export { snakeCase, camelCase }; + +import * as env from "jsr:@tsirysndr/env-js@0.1.3"; +export { env }; +export { exit } from "jsr:@tsirysndr/exit-js@0.1.0"; + +export { ClientError, GraphQLClient } from "npm:graphql-request@6.1.0"; export { DaggerSDKError, UnknownDaggerError, @@ -33,15 +32,10 @@ export { EngineSessionConnectionTimeoutError, NotAwaitedRequestError, ERROR_CODES, -} from "https://esm.sh/@dagger.io/dagger@0.9.3"; - -export type { - CallbackFct, - ConnectOpts, -} from "https://sdk.fluentci.io/v0.3.0/mod.ts"; +} from "./sdk/common/errors/index.ts"; -export * as FluentGitlabCI from "https://deno.land/x/fluent_gitlab_ci@v0.4.2/mod.ts"; -export * as FluentGithubActions from "https://deno.land/x/fluent_github_actions@v0.2.1/mod.ts"; -export * as FluentCircleCI from "https://deno.land/x/fluent_circleci@v0.2.5/mod.ts"; -export * as FluentAzurePipelines from "https://deno.land/x/fluent_azure_pipelines@v0.2.0/mod.ts"; -export * as FluentAWSCodePipeline from "https://deno.land/x/fluent_aws_codepipeline@v0.2.3/mod.ts"; +export * as FluentGitlabCI from "jsr:@tsirysndr/fluent-gitlab-ci@0.5"; +export * as FluentGithubActions from "jsr:@tsirysndr/fluent-gh-actions@0.3"; +export * as FluentCircleCI from "jsr:@tsirysndr/fluent-circleci@0.3"; +export * as FluentAzurePipelines from "jsr:@tsirysndr/fluent-az-pipelines@0.3"; +export * as FluentAWSCodePipeline from "jsr:@tsirysndr/fluent-codepipeline@0.3"; diff --git a/example/.fluentci/sdk/builder.ts b/example/.fluentci/sdk/builder.ts index f06951a..10182d6 100644 --- a/example/.fluentci/sdk/builder.ts +++ b/example/.fluentci/sdk/builder.ts @@ -1,5 +1,6 @@ import { createGQLClient } from "./client.ts"; import { Context } from "./context.ts"; +import { env } from "../deps.ts"; /** * @hidden @@ -10,9 +11,9 @@ export function initDefaultContext(): Context { let ctx = new Context(); // Prefer DAGGER_SESSION_PORT if set - const daggerSessionPort = Deno.env.get("DAGGER_SESSION_PORT"); + const daggerSessionPort = env.get("DAGGER_SESSION_PORT"); if (daggerSessionPort) { - const sessionToken = Deno.env.get("DAGGER_SESSION_TOKEN"); + const sessionToken = env.get("DAGGER_SESSION_TOKEN"); if (!sessionToken) { throw new Error( "DAGGER_SESSION_TOKEN must be set when using DAGGER_SESSION_PORT" diff --git a/example/.fluentci/sdk/client.gen.ts b/example/.fluentci/sdk/client.gen.ts index ae06cef..5e20f82 100644 --- a/example/.fluentci/sdk/client.gen.ts +++ b/example/.fluentci/sdk/client.gen.ts @@ -127,7 +127,7 @@ export type ContainerBuildOpts = { * * They will be mounted at /run/secrets/[secret-name] in the build container * - * They can be accessed in the Dockerfile using the "secret" mount type and mount path /run/secrets/[secret-name], e.g. RUN --mount=type=secret,id=my-secret curl http://example.com?token=$(cat /run/secrets/my-secret) + * They can be accessed in the Dockerfile using the "secret" mount type and mount path /run/secrets/[secret-name], e.g. RUN --mount=type=secret,id=my-secret curl [http://example.com?token=$(cat /run/secrets/my-secret)](http://example.com?token=$(cat /run/secrets/my-secret)) */ secrets?: Secret[]; }; @@ -306,6 +306,22 @@ export type ContainerWithFileOpts = { owner?: string; }; +export type ContainerWithFilesOpts = { + /** + * Permission given to the copied files (e.g., 0600). + */ + permissions?: number; + + /** + * A user:group to set for the files. + * + * The user and group can either be an ID (1000:1000) or a name (foo:bar). + * + * If the group is omitted, it defaults to the same as the user. + */ + owner?: string; +}; + export type ContainerWithMountedCacheOpts = { /** * Identifier of the directory to use as the cache volume's root. @@ -439,13 +455,13 @@ export type CurrentModuleID = string & { __CurrentModuleID: never }; export type DirectoryAsModuleOpts = { /** - * An optional subpath of the directory which contains the module's source code. + * An optional subpath of the directory which contains the module's configuration file. * * This is needed when the module code is in a subdirectory but requires parent directories to be loaded in order to execute. For example, the module source code may need a go.mod, project.toml, package.json, etc. file from a parent directory. * * If not set, the module source code is loaded from the root of the directory. */ - sourceSubpath?: string; + sourceRootPath?: string; }; export type DirectoryDockerBuildOpts = { @@ -515,6 +531,13 @@ export type DirectoryWithFileOpts = { permissions?: number; }; +export type DirectoryWithFilesOpts = { + /** + * Permission given to the copied files (e.g., 0600). + */ + permissions?: number; +}; + export type DirectoryWithNewDirectoryOpts = { /** * Permission granted to the created directory (e.g., 0777). @@ -852,11 +875,6 @@ export type ClientModuleDependencyOpts = { }; export type ClientModuleSourceOpts = { - /** - * An explicitly set root directory for the module source. This is required to load local sources as modules; other source types implicitly encode the root directory and do not require this. - */ - rootDirectory?: Directory; - /** * If true, enforce that the source is a stable version for source kinds that support versioning. */ @@ -875,6 +893,10 @@ export type ClientPipelineOpts = { labels?: PipelineLabel[]; }; +export type ClientSecretOpts = { + accessor?: string; +}; + /** * The `SecretID` scalar type represents an identifier for an object of type Secret. */ @@ -1184,7 +1206,7 @@ export class Container extends BaseClient { * * They will be mounted at /run/secrets/[secret-name] in the build container * - * They can be accessed in the Dockerfile using the "secret" mount type and mount path /run/secrets/[secret-name], e.g. RUN --mount=type=secret,id=my-secret curl http://example.com?token=$(cat /run/secrets/my-secret) + * They can be accessed in the Dockerfile using the "secret" mount type and mount path /run/secrets/[secret-name], e.g. RUN --mount=type=secret,id=my-secret curl [http://example.com?token=$(cat /run/secrets/my-secret)](http://example.com?token=$(cat /run/secrets/my-secret)) */ build = (context: Directory, opts?: ContainerBuildOpts): Container => { return new Container({ @@ -1993,6 +2015,34 @@ export class Container extends BaseClient { }); }; + /** + * Retrieves this container plus the contents of the given files copied to the given path. + * @param path Location where copied files should be placed (e.g., "/src"). + * @param sources Identifiers of the files to copy. + * @param opts.permissions Permission given to the copied files (e.g., 0600). + * @param opts.owner A user:group to set for the files. + * + * The user and group can either be an ID (1000:1000) or a name (foo:bar). + * + * If the group is omitted, it defaults to the same as the user. + */ + withFiles = ( + path: string, + sources: File[], + opts?: ContainerWithFilesOpts + ): Container => { + return new Container({ + queryTree: [ + ...this._queryTree, + { + operation: "withFiles", + args: { path, sources, ...opts }, + }, + ], + ctx: this._ctx, + }); + }; + /** * Indicate that subsequent operations should be featured more prominently in the UI. */ @@ -2719,7 +2769,7 @@ export class Directory extends BaseClient { /** * Load the directory as a Dagger module - * @param opts.sourceSubpath An optional subpath of the directory which contains the module's source code. + * @param opts.sourceRootPath An optional subpath of the directory which contains the module's configuration file. * * This is needed when the module code is in a subdirectory but requires parent directories to be loaded in order to execute. For example, the module source code may need a go.mod, project.toml, package.json, etc. file from a parent directory. * @@ -2956,6 +3006,29 @@ export class Directory extends BaseClient { }); }; + /** + * Retrieves this directory plus the contents of the given files copied to the given path. + * @param path Location where copied files should be placed (e.g., "/src"). + * @param sources Identifiers of the files to copy. + * @param opts.permissions Permission given to the copied files (e.g., 0600). + */ + withFiles = ( + path: string, + sources: File[], + opts?: DirectoryWithFilesOpts + ): Directory => { + return new Directory({ + queryTree: [ + ...this._queryTree, + { + operation: "withFiles", + args: { path, sources, ...opts }, + }, + ], + ctx: this._ctx, + }); + }; + /** * Retrieves this directory plus a new directory created at the given path. * @param path Location of the directory created (e.g., "/logs"). @@ -4167,7 +4240,7 @@ export class GitModuleSource extends BaseClient { private readonly _cloneURL?: string = undefined; private readonly _commit?: string = undefined; private readonly _htmlURL?: string = undefined; - private readonly _sourceSubpath?: string = undefined; + private readonly _rootSubpath?: string = undefined; private readonly _version?: string = undefined; /** @@ -4179,7 +4252,7 @@ export class GitModuleSource extends BaseClient { _cloneURL?: string, _commit?: string, _htmlURL?: string, - _sourceSubpath?: string, + _rootSubpath?: string, _version?: string ) { super(parent); @@ -4188,7 +4261,7 @@ export class GitModuleSource extends BaseClient { this._cloneURL = _cloneURL; this._commit = _commit; this._htmlURL = _htmlURL; - this._sourceSubpath = _sourceSubpath; + this._rootSubpath = _rootSubpath; this._version = _version; } @@ -4255,6 +4328,21 @@ export class GitModuleSource extends BaseClient { return response; }; + /** + * The directory containing everything needed to load load and use the module. + */ + contextDirectory = (): Directory => { + return new Directory({ + queryTree: [ + ...this._queryTree, + { + operation: "contextDirectory", + }, + ], + ctx: this._ctx, + }); + }; + /** * The URL to the source's git repo in a web browser */ @@ -4277,18 +4365,18 @@ export class GitModuleSource extends BaseClient { }; /** - * The path to the module source code dir specified by this source relative to the source's root directory. + * The path to the root of the module source under the context directory. This directory contains its configuration file. It also contains its source code (possibly as a subdirectory). */ - sourceSubpath = async (): Promise => { - if (this._sourceSubpath) { - return this._sourceSubpath; + rootSubpath = async (): Promise => { + if (this._rootSubpath) { + return this._rootSubpath; } const response: Awaited = await computeQuery( [ ...this._queryTree, { - operation: "sourceSubpath", + operation: "rootSubpath", }, ], await this._ctx.connection() @@ -5074,7 +5162,7 @@ export class ListTypeDef extends BaseClient { */ export class LocalModuleSource extends BaseClient { private readonly _id?: LocalModuleSourceID = undefined; - private readonly _sourceSubpath?: string = undefined; + private readonly _rootSubpath?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. @@ -5082,12 +5170,12 @@ export class LocalModuleSource extends BaseClient { constructor( parent?: { queryTree?: QueryTree[]; ctx: Context }, _id?: LocalModuleSourceID, - _sourceSubpath?: string + _rootSubpath?: string ) { super(parent); this._id = _id; - this._sourceSubpath = _sourceSubpath; + this._rootSubpath = _rootSubpath; } /** @@ -5112,18 +5200,33 @@ export class LocalModuleSource extends BaseClient { }; /** - * The path to the module source code dir specified by this source. + * The directory containing everything needed to load load and use the module. */ - sourceSubpath = async (): Promise => { - if (this._sourceSubpath) { - return this._sourceSubpath; + contextDirectory = (): Directory => { + return new Directory({ + queryTree: [ + ...this._queryTree, + { + operation: "contextDirectory", + }, + ], + ctx: this._ctx, + }); + }; + + /** + * The path to the root of the module source under the context directory. This directory contains its configuration file. It also contains its source code (possibly as a subdirectory). + */ + rootSubpath = async (): Promise => { + if (this._rootSubpath) { + return this._rootSubpath; } const response: Awaited = await computeQuery( [ ...this._queryTree, { - operation: "sourceSubpath", + operation: "rootSubpath", }, ], await this._ctx.connection() @@ -5282,14 +5385,29 @@ export class Module_ extends BaseClient { }; /** - * The module's root directory containing the config file for it and its source (possibly as a subdir). It includes any generated code or updated config files created after initial load, but not any files/directories that were unchanged after sdk codegen was run. + * The generated files and directories made on top of the module source's context directory. + */ + generatedContextDiff = (): Directory => { + return new Directory({ + queryTree: [ + ...this._queryTree, + { + operation: "generatedContextDiff", + }, + ], + ctx: this._ctx, + }); + }; + + /** + * The module source's context plus any configuration and source files created by codegen. */ - generatedSourceRootDirectory = (): Directory => { + generatedContextDirectory = (): Directory => { return new Directory({ queryTree: [ ...this._queryTree, { - operation: "generatedSourceRootDirectory", + operation: "generatedContextDirectory", }, ], ctx: this._ctx, @@ -5482,23 +5600,6 @@ export class Module_ extends BaseClient { }); }; - /** - * Update the module configuration to use the given dependencies. - * @param dependencies The dependency modules to install. - */ - withDependencies = (dependencies: ModuleDependency[]): Module_ => { - return new Module_({ - queryTree: [ - ...this._queryTree, - { - operation: "withDependencies", - args: { dependencies }, - }, - ], - ctx: this._ctx, - }); - }; - /** * Retrieves the module with the given description * @param description The description to set @@ -5532,23 +5633,6 @@ export class Module_ extends BaseClient { }); }; - /** - * Update the module configuration to use the given name. - * @param name The name to use. - */ - withName = (name: string): Module_ => { - return new Module_({ - queryTree: [ - ...this._queryTree, - { - operation: "withName", - args: { name }, - }, - ], - ctx: this._ctx, - }); - }; - /** * This module plus the given Object type and associated functions. */ @@ -5565,23 +5649,6 @@ export class Module_ extends BaseClient { }); }; - /** - * Update the module configuration to use the given SDK. - * @param sdk The SDK to use. - */ - withSDK = (sdk: string): Module_ => { - return new Module_({ - queryTree: [ - ...this._queryTree, - { - operation: "withSDK", - args: { sdk }, - }, - ], - ctx: this._ctx, - }); - }; - /** * Retrieves the module with basic configuration loaded if present. * @param source The module source to initialize from. @@ -5694,9 +5761,13 @@ export class ModuleDependency extends BaseClient { export class ModuleSource extends BaseClient { private readonly _id?: ModuleSourceID = undefined; private readonly _asString?: string = undefined; + private readonly _configExists?: boolean = undefined; private readonly _kind?: ModuleSourceKind = undefined; private readonly _moduleName?: string = undefined; - private readonly _subpath?: string = undefined; + private readonly _moduleOriginalName?: string = undefined; + private readonly _resolveContextPathFromCaller?: string = undefined; + private readonly _sourceRootSubpath?: string = undefined; + private readonly _sourceSubpath?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. @@ -5705,17 +5776,25 @@ export class ModuleSource extends BaseClient { parent?: { queryTree?: QueryTree[]; ctx: Context }, _id?: ModuleSourceID, _asString?: string, + _configExists?: boolean, _kind?: ModuleSourceKind, _moduleName?: string, - _subpath?: string + _moduleOriginalName?: string, + _resolveContextPathFromCaller?: string, + _sourceRootSubpath?: string, + _sourceSubpath?: string ) { super(parent); this._id = _id; this._asString = _asString; + this._configExists = _configExists; this._kind = _kind; this._moduleName = _moduleName; - this._subpath = _subpath; + this._moduleOriginalName = _moduleOriginalName; + this._resolveContextPathFromCaller = _resolveContextPathFromCaller; + this._sourceRootSubpath = _sourceRootSubpath; + this._sourceSubpath = _sourceSubpath; } /** @@ -5806,7 +5885,81 @@ export class ModuleSource extends BaseClient { }; /** - * The directory containing the actual module's source code, as determined from the root directory and subpath. + * Returns whether the module source has a configuration file. + */ + configExists = async (): Promise => { + if (this._configExists) { + return this._configExists; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "configExists", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + + /** + * The directory containing everything needed to load load and use the module. + */ + contextDirectory = (): Directory => { + return new Directory({ + queryTree: [ + ...this._queryTree, + { + operation: "contextDirectory", + }, + ], + ctx: this._ctx, + }); + }; + + /** + * The dependencies of the module source. Includes dependencies from the configuration and any extras from withDependencies calls. + */ + dependencies = async (): Promise => { + type dependencies = { + id: ModuleDependencyID; + }; + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "dependencies", + }, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response.map( + (r) => + new ModuleDependency( + { + queryTree: [ + { + operation: "loadModuleDependencyFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + + /** + * The directory containing the module configuration and source code (source code may be in a subdir). * @param path The path from the source directory to select. */ directory = (path: string): Directory => { @@ -5844,7 +5997,7 @@ export class ModuleSource extends BaseClient { }; /** - * If set, the name of the module this source references + * If set, the name of the module this source references, including any overrides at runtime by callers. */ moduleName = async (): Promise => { if (this._moduleName) { @@ -5864,6 +6017,48 @@ export class ModuleSource extends BaseClient { return response; }; + /** + * The original name of the module this source references, as defined in the module configuration. + */ + moduleOriginalName = async (): Promise => { + if (this._moduleOriginalName) { + return this._moduleOriginalName; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "moduleOriginalName", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + + /** + * The path to the module source's context directory on the caller's filesystem. Only valid for local sources. + */ + resolveContextPathFromCaller = async (): Promise => { + if (this._resolveContextPathFromCaller) { + return this._resolveContextPathFromCaller; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "resolveContextPathFromCaller", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + /** * Resolve the provided module source arg as a dependency relative to this module source. * @param dep The dependency module source to resolve. @@ -5882,14 +6077,14 @@ export class ModuleSource extends BaseClient { }; /** - * The root directory of the module source that contains its configuration and source code (which may be in a subdirectory of this root). + * Load the source from its path on the caller's filesystem, including only needed+configured files and directories. Only valid for local sources. */ - rootDirectory = (): Directory => { - return new Directory({ + resolveFromCaller = (): ModuleSource => { + return new ModuleSource({ queryTree: [ ...this._queryTree, { - operation: "rootDirectory", + operation: "resolveFromCaller", }, ], ctx: this._ctx, @@ -5897,18 +6092,39 @@ export class ModuleSource extends BaseClient { }; /** - * The path to the module subdirectory containing the actual module's source code. + * The path relative to context of the root of the module source, which contains dagger.json. It also contains the module implementation source code, but that may or may not being a subdir of this root. + */ + sourceRootSubpath = async (): Promise => { + if (this._sourceRootSubpath) { + return this._sourceRootSubpath; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "sourceRootSubpath", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + + /** + * The path relative to context of the module implementation source code. */ - subpath = async (): Promise => { - if (this._subpath) { - return this._subpath; + sourceSubpath = async (): Promise => { + if (this._sourceSubpath) { + return this._sourceSubpath; } const response: Awaited = await computeQuery( [ ...this._queryTree, { - operation: "subpath", + operation: "sourceSubpath", }, ], await this._ctx.connection() @@ -5917,6 +6133,91 @@ export class ModuleSource extends BaseClient { return response; }; + /** + * Update the module source with a new context directory. Only valid for local sources. + * @param dir The directory to set as the context directory. + */ + withContextDirectory = (dir: Directory): ModuleSource => { + return new ModuleSource({ + queryTree: [ + ...this._queryTree, + { + operation: "withContextDirectory", + args: { dir }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Append the provided dependencies to the module source's dependency list. + * @param dependencies The dependencies to append. + */ + withDependencies = (dependencies: ModuleDependency[]): ModuleSource => { + return new ModuleSource({ + queryTree: [ + ...this._queryTree, + { + operation: "withDependencies", + args: { dependencies }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Update the module source with a new name. + * @param name The name to set. + */ + withName = (name: string): ModuleSource => { + return new ModuleSource({ + queryTree: [ + ...this._queryTree, + { + operation: "withName", + args: { name }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Update the module source with a new SDK. + * @param sdk The SDK to set. + */ + withSDK = (sdk: string): ModuleSource => { + return new ModuleSource({ + queryTree: [ + ...this._queryTree, + { + operation: "withSDK", + args: { sdk }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Update the module source with a new source subpath. + * @param path The path to set as the source subpath. + */ + withSourceSubpath = (path: string): ModuleSource => { + return new ModuleSource({ + queryTree: [ + ...this._queryTree, + { + operation: "withSourceSubpath", + args: { path }, + }, + ], + ctx: this._ctx, + }); + }; + /** * Call the provided function with current ModuleSource. * @@ -6312,6 +6613,23 @@ export class Client extends BaseClient { }); }; + /** + * Retrieves a container builtin to the engine. + * @param digest Digest of the image manifest + */ + builtinContainer = (digest: string): Container => { + return new Container({ + queryTree: [ + ...this._queryTree, + { + operation: "builtinContainer", + args: { digest }, + }, + ], + ctx: this._ctx, + }); + }; + /** * Constructs a cache volume for a given cache key. * @param key A string identifier to target this cache volume (e.g., "modules-cache"). @@ -7119,7 +7437,6 @@ export class Client extends BaseClient { /** * Create a new module source instance from a source ref string. * @param refString The string ref representation of the module source - * @param opts.rootDirectory An explicitly set root directory for the module source. This is required to load local sources as modules; other source types implicitly encode the root directory and do not require this. * @param opts.stable If true, enforce that the source is a stable version for source kinds that support versioning. */ moduleSource = ( @@ -7160,13 +7477,13 @@ export class Client extends BaseClient { /** * Reference a secret by name. */ - secret = (name: string): Secret => { + secret = (name: string, opts?: ClientSecretOpts): Secret => { return new Secret({ queryTree: [ ...this._queryTree, { operation: "secret", - args: { name }, + args: { name, ...opts }, }, ], ctx: this._ctx, diff --git a/example/.fluentci/sdk/common/errors/DaggerSDKError.ts b/example/.fluentci/sdk/common/errors/DaggerSDKError.ts new file mode 100644 index 0000000..f2f009d --- /dev/null +++ b/example/.fluentci/sdk/common/errors/DaggerSDKError.ts @@ -0,0 +1,46 @@ +import { log } from "../utils.ts"; +import { ErrorCodes, ErrorNames } from "./errors-codes.ts"; + +export interface DaggerSDKErrorOptions { + cause?: Error; +} + +/** + * The base error. Every other error inherits this error. + */ +export abstract class DaggerSDKError extends Error { + /** + * The name of the dagger error. + */ + abstract readonly name: ErrorNames; + + /** + * The dagger specific error code. + * Use this to identify dagger errors programmatically. + */ + abstract readonly code: ErrorCodes; + + /** + * The original error, which caused the DaggerSDKError. + */ + cause?: Error; + + protected constructor(message: string, options?: DaggerSDKErrorOptions) { + super(message); + this.cause = options?.cause; + } + + /** + * @hidden + */ + get [Symbol.toStringTag]() { + return this.name; + } + + /** + * Pretty prints the error + */ + printStackTrace() { + log(this.stack); + } +} diff --git a/example/.fluentci/sdk/common/errors/DockerImageRefValidationError.ts b/example/.fluentci/sdk/common/errors/DockerImageRefValidationError.ts new file mode 100644 index 0000000..6f45b46 --- /dev/null +++ b/example/.fluentci/sdk/common/errors/DockerImageRefValidationError.ts @@ -0,0 +1,28 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts" +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts" + +interface DockerImageRefValidationErrorOptions extends DaggerSDKErrorOptions { + ref: string +} + +/** + * This error is thrown if the passed image reference does not pass validation and is not compliant with the + * DockerImage constructor. + */ +export class DockerImageRefValidationError extends DaggerSDKError { + name = ERROR_NAMES.DockerImageRefValidationError + code = ERROR_CODES.DockerImageRefValidationError + + /** + * The docker image reference, which caused the error. + */ + ref: string + + /** + * @hidden + */ + constructor(message: string, options: DockerImageRefValidationErrorOptions) { + super(message, options) + this.ref = options?.ref + } +} diff --git a/example/.fluentci/sdk/common/errors/EngineSessionConnectParamsParseError.ts b/example/.fluentci/sdk/common/errors/EngineSessionConnectParamsParseError.ts new file mode 100644 index 0000000..8acd47a --- /dev/null +++ b/example/.fluentci/sdk/common/errors/EngineSessionConnectParamsParseError.ts @@ -0,0 +1,31 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +interface EngineSessionConnectParamsParseErrorOptions + extends DaggerSDKErrorOptions { + parsedLine: string; +} + +/** + * This error is thrown if the EngineSession does not manage to parse the required connection parameters from the session binary + */ +export class EngineSessionConnectParamsParseError extends DaggerSDKError { + name = ERROR_NAMES.EngineSessionConnectParamsParseError; + code = ERROR_CODES.EngineSessionConnectParamsParseError; + + /** + * the line, which caused the error during parsing, if the error was caused because of parsing. + */ + parsedLine: string; + + /** + * @hidden + */ + constructor( + message: string, + options: EngineSessionConnectParamsParseErrorOptions + ) { + super(message, options); + this.parsedLine = options.parsedLine; + } +} diff --git a/example/.fluentci/sdk/common/errors/EngineSessionConnectionTimeoutError.ts b/example/.fluentci/sdk/common/errors/EngineSessionConnectionTimeoutError.ts new file mode 100644 index 0000000..e2550ac --- /dev/null +++ b/example/.fluentci/sdk/common/errors/EngineSessionConnectionTimeoutError.ts @@ -0,0 +1,31 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +interface EngineSessionConnectionTimeoutErrorOptions + extends DaggerSDKErrorOptions { + timeOutDuration: number; +} + +/** + * This error is thrown if the EngineSession does not manage to parse the required port successfully because the sessions connection timed out. + */ +export class EngineSessionConnectionTimeoutError extends DaggerSDKError { + name = ERROR_NAMES.EngineSessionConnectionTimeoutError; + code = ERROR_CODES.EngineSessionConnectionTimeoutError; + + /** + * The duration until the timeout occurred in ms. + */ + timeOutDuration: number; + + /** + * @hidden + */ + constructor( + message: string, + options: EngineSessionConnectionTimeoutErrorOptions + ) { + super(message, options); + this.timeOutDuration = options.timeOutDuration; + } +} diff --git a/example/.fluentci/sdk/common/errors/EngineSessionErrorOptions.ts b/example/.fluentci/sdk/common/errors/EngineSessionErrorOptions.ts new file mode 100644 index 0000000..ba0ec90 --- /dev/null +++ b/example/.fluentci/sdk/common/errors/EngineSessionErrorOptions.ts @@ -0,0 +1,20 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +type EngineSessionErrorOptions = DaggerSDKErrorOptions; + +/** + * This error is thrown if the EngineSession does not manage to parse the required port successfully because a EOF is read before any valid port. + * This usually happens if no connection can be established. + */ +export class EngineSessionError extends DaggerSDKError { + name = ERROR_NAMES.EngineSessionError; + code = ERROR_CODES.EngineSessionError; + + /** + * @hidden + */ + constructor(message: string, options?: EngineSessionErrorOptions) { + super(message, options); + } +} diff --git a/example/.fluentci/sdk/common/errors/ExecError.ts b/example/.fluentci/sdk/common/errors/ExecError.ts new file mode 100644 index 0000000..ede655b --- /dev/null +++ b/example/.fluentci/sdk/common/errors/ExecError.ts @@ -0,0 +1,54 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +interface ExecErrorOptions extends DaggerSDKErrorOptions { + cmd: string[]; + exitCode: number; + stdout: string; + stderr: string; +} + +/** + * API error from an exec operation in a pipeline. + */ +export class ExecError extends DaggerSDKError { + name = ERROR_NAMES.ExecError; + code = ERROR_CODES.ExecError; + + /** + * The command that caused the error. + */ + cmd: string[]; + + /** + * The exit code of the command. + */ + exitCode: number; + + /** + * The stdout of the command. + */ + stdout: string; + + /** + * The stderr of the command. + */ + stderr: string; + + /** + * @hidden + */ + constructor(message: string, options: ExecErrorOptions) { + super(message, options); + this.cmd = options.cmd; + this.exitCode = options.exitCode; + this.stdout = options.stdout; + this.stderr = options.stderr; + } + + toString(): string { + return `${super.toString()}\nStdout:\n${this.stdout}\nStderr:\n${ + this.stderr + }`; + } +} diff --git a/example/.fluentci/sdk/common/errors/GraphQLRequestError.ts b/example/.fluentci/sdk/common/errors/GraphQLRequestError.ts new file mode 100644 index 0000000..59584f8 --- /dev/null +++ b/example/.fluentci/sdk/common/errors/GraphQLRequestError.ts @@ -0,0 +1,36 @@ +import { GraphQLRequestContext, GraphQLResponse } from "./types.ts"; + +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +interface GraphQLRequestErrorOptions extends DaggerSDKErrorOptions { + response: GraphQLResponse; + request: GraphQLRequestContext; +} + +/** + * This error originates from the dagger engine. It means that some error was thrown and sent back via GraphQL. + */ +export class GraphQLRequestError extends DaggerSDKError { + name = ERROR_NAMES.GraphQLRequestError; + code = ERROR_CODES.GraphQLRequestError; + + /** + * The query and variables, which caused the error. + */ + requestContext: GraphQLRequestContext; + + /** + * the GraphQL response containing the error. + */ + response: GraphQLResponse; + + /** + * @hidden + */ + constructor(message: string, options: GraphQLRequestErrorOptions) { + super(message, options); + this.requestContext = options.request; + this.response = options.response; + } +} diff --git a/example/.fluentci/sdk/common/errors/InitEngineSessionBinaryError.ts b/example/.fluentci/sdk/common/errors/InitEngineSessionBinaryError.ts new file mode 100644 index 0000000..879c1ce --- /dev/null +++ b/example/.fluentci/sdk/common/errors/InitEngineSessionBinaryError.ts @@ -0,0 +1,17 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +/** + * This error is thrown if the dagger binary cannot be copied from the dagger docker image and copied to the local host. + */ +export class InitEngineSessionBinaryError extends DaggerSDKError { + name = ERROR_NAMES.InitEngineSessionBinaryError; + code = ERROR_CODES.InitEngineSessionBinaryError; + + /** + * @hidden + */ + constructor(message: string, options?: DaggerSDKErrorOptions) { + super(message, options); + } +} diff --git a/example/.fluentci/sdk/common/errors/NotAwaitedRequestError.ts b/example/.fluentci/sdk/common/errors/NotAwaitedRequestError.ts new file mode 100644 index 0000000..291b924 --- /dev/null +++ b/example/.fluentci/sdk/common/errors/NotAwaitedRequestError.ts @@ -0,0 +1,17 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +/** + * This error is thrown when the compute function isn't awaited. + */ +export class NotAwaitedRequestError extends DaggerSDKError { + name = ERROR_NAMES.NotAwaitedRequestError; + code = ERROR_CODES.NotAwaitedRequestError; + + /** + * @hidden + */ + constructor(message: string, options?: DaggerSDKErrorOptions) { + super(message, options); + } +} diff --git a/example/.fluentci/sdk/common/errors/TooManyNestedObjectsError.ts b/example/.fluentci/sdk/common/errors/TooManyNestedObjectsError.ts new file mode 100644 index 0000000..7b8b907 --- /dev/null +++ b/example/.fluentci/sdk/common/errors/TooManyNestedObjectsError.ts @@ -0,0 +1,27 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +interface TooManyNestedObjectsErrorOptions extends DaggerSDKErrorOptions { + response: unknown; +} + +/** + * Dagger only expects one response value from the engine. If the engine returns more than one value this error is thrown. + */ +export class TooManyNestedObjectsError extends DaggerSDKError { + name = ERROR_NAMES.TooManyNestedObjectsError; + code = ERROR_CODES.TooManyNestedObjectsError; + + /** + * the response containing more than one value. + */ + response: unknown; + + /** + * @hidden + */ + constructor(message: string, options: TooManyNestedObjectsErrorOptions) { + super(message, options); + this.response = options.response; + } +} diff --git a/example/.fluentci/sdk/common/errors/UnknownDaggerError.ts b/example/.fluentci/sdk/common/errors/UnknownDaggerError.ts new file mode 100644 index 0000000..fe29169 --- /dev/null +++ b/example/.fluentci/sdk/common/errors/UnknownDaggerError.ts @@ -0,0 +1,17 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +/** + * This error is thrown if the dagger SDK does not identify the error and just wraps the cause. + */ +export class UnknownDaggerError extends DaggerSDKError { + name = ERROR_NAMES.UnknownDaggerError; + code = ERROR_CODES.UnknownDaggerError; + + /** + * @hidden + */ + constructor(message: string, options: DaggerSDKErrorOptions) { + super(message, options); + } +} diff --git a/example/.fluentci/sdk/common/errors/errors-codes.ts b/example/.fluentci/sdk/common/errors/errors-codes.ts new file mode 100644 index 0000000..a6e4d48 --- /dev/null +++ b/example/.fluentci/sdk/common/errors/errors-codes.ts @@ -0,0 +1,63 @@ +export const ERROR_CODES = { + /** + * {@link GraphQLRequestError} + */ + GraphQLRequestError: "D100", + + /** + * {@link UnknownDaggerError} + */ + UnknownDaggerError: "D101", + + /** + * {@link TooManyNestedObjectsError} + */ + TooManyNestedObjectsError: "D102", + + /** + * {@link EngineSessionConnectParamsParseError} + */ + EngineSessionConnectParamsParseError: "D103", + + /** + * {@link EngineSessionConnectionTimeoutError} + */ + EngineSessionConnectionTimeoutError: "D104", + + /** + * {@link EngineSessionError} + */ + EngineSessionError: "D105", + + /** + * {@link InitEngineSessionBinaryError} + */ + InitEngineSessionBinaryError: "D106", + + /** + * {@link DockerImageRefValidationError} + */ + DockerImageRefValidationError: "D107", + + /** + * {@link NotAwaitedRequestError} + */ + NotAwaitedRequestError: "D108", + + /** + * (@link ExecError} + */ + ExecError: "D109", +} as const + +type ErrorCodesType = typeof ERROR_CODES +export type ErrorNames = keyof ErrorCodesType +export type ErrorCodes = ErrorCodesType[ErrorNames] + +type ErrorNamesMap = { readonly [Key in ErrorNames]: Key } +export const ERROR_NAMES: ErrorNamesMap = ( + Object.keys(ERROR_CODES) as Array +).reduce( + (obj, item) => ({ ...obj, [item]: item }), + {} as ErrorNamesMap +) diff --git a/example/.fluentci/sdk/common/errors/index.ts b/example/.fluentci/sdk/common/errors/index.ts new file mode 100644 index 0000000..61faf70 --- /dev/null +++ b/example/.fluentci/sdk/common/errors/index.ts @@ -0,0 +1,12 @@ +export { DaggerSDKError } from "./DaggerSDKError.ts"; +export { UnknownDaggerError } from "./UnknownDaggerError.ts"; +export { DockerImageRefValidationError } from "./DockerImageRefValidationError.ts"; +export { EngineSessionConnectParamsParseError } from "./EngineSessionConnectParamsParseError.ts"; +export { ExecError } from "./ExecError.ts"; +export { GraphQLRequestError } from "./GraphQLRequestError.ts"; +export { InitEngineSessionBinaryError } from "./InitEngineSessionBinaryError.ts"; +export { TooManyNestedObjectsError } from "./TooManyNestedObjectsError.ts"; +export { EngineSessionError } from "./EngineSessionErrorOptions.ts"; +export { EngineSessionConnectionTimeoutError } from "./EngineSessionConnectionTimeoutError.ts"; +export { NotAwaitedRequestError } from "./NotAwaitedRequestError.ts"; +export { ERROR_CODES } from "./errors-codes.ts"; diff --git a/example/.fluentci/sdk/common/errors/types.ts b/example/.fluentci/sdk/common/errors/types.ts new file mode 100644 index 0000000..f5b1582 --- /dev/null +++ b/example/.fluentci/sdk/common/errors/types.ts @@ -0,0 +1,16 @@ +import { GraphQLError } from "npm:graphql@16.8.1"; + +export interface GraphQLResponse { + data?: T; + errors?: GraphQLError[]; + extensions?: unknown; + status: number; + [key: string]: unknown; +} + +export type Variables = Record; + +export interface GraphQLRequestContext { + query: string | string[]; + variables?: V; +} diff --git a/example/.fluentci/sdk/common/utils.ts b/example/.fluentci/sdk/common/utils.ts new file mode 100644 index 0000000..5853601 --- /dev/null +++ b/example/.fluentci/sdk/common/utils.ts @@ -0,0 +1,4 @@ +import logger from "npm:node-color-log@11.0.2"; + +export const log = (stack?: string) => + logger.bgColor("red").color("black").log(stack); diff --git a/example/.fluentci/src/dagger/jobs.ts b/example/.fluentci/src/dagger/jobs.ts index 52f9757..a379094 100644 --- a/example/.fluentci/src/dagger/jobs.ts +++ b/example/.fluentci/src/dagger/jobs.ts @@ -3,7 +3,7 @@ * @description Module for running Terraform commands */ -import { Directory, dag } from "../../deps.ts"; +import { Directory, dag, env } from "../../deps.ts"; import { CacheSharingMode } from "../../sdk/client.gen.ts"; import { filterObjectByPrefix, withEnvs, getDirectory } from "./lib.ts"; @@ -16,11 +16,7 @@ export enum Job { export const exclude = [".terraform", ".git", ".fluentci", "plan"]; -const envs = filterObjectByPrefix(Deno.env.toObject(), [ - "TF_", - "AWS_", - "GOOGLE_", -]); +const envs = filterObjectByPrefix(env.toObject(), ["TF_", "AWS_", "GOOGLE_"]); /** * @function @@ -36,7 +32,7 @@ export async function init( googleApplicationCredentials?: string ): Promise { const context = await getDirectory(src); - const TF_VERSION = tfVersion || Deno.env.get("TF_VERSION") || "latest"; + const TF_VERSION = tfVersion || env.get("TF_VERSION") || "latest"; if (googleApplicationCredentials) { envs.GOOGLE_APPLICATION_CREDENTIALS = googleApplicationCredentials; @@ -78,7 +74,7 @@ export async function validate( tfVersion?: string ): Promise { const context = await getDirectory(src); - const TF_VERSION = tfVersion || Deno.env.get("TF_VERSION") || "latest"; + const TF_VERSION = tfVersion || env.get("TF_VERSION") || "latest"; const baseCtr = withEnvs( dag @@ -137,7 +133,7 @@ export async function plan( googleApplicationCredentials?: string ): Promise { const context = await getDirectory(src); - const TF_VERSION = tfVersion || Deno.env.get("TF_VERSION") || "latest"; + const TF_VERSION = tfVersion || env.get("TF_VERSION") || "latest"; if (googleApplicationCredentials) { envs.GOOGLE_APPLICATION_CREDENTIALS = googleApplicationCredentials; @@ -155,7 +151,7 @@ export async function plan( .withMountedCache("/app/.terraform", dag.cacheVolume("terraform-example"), { sharing: CacheSharingMode.Shared, }) - .withMountedCache("/app/plan", dag.cacheVolume("tfplan-example")) + .withMountedCache("/app/plan", dag.cacheVolume("tfplan")) .withDirectory("/app", context, { exclude, }) @@ -201,7 +197,7 @@ export async function apply( googleApplicationCredentials?: string ): Promise { const context = await getDirectory(src); - const TF_VERSION = tfVersion || Deno.env.get("TF_VERSION") || "latest"; + const TF_VERSION = tfVersion || env.get("TF_VERSION") || "latest"; if (googleApplicationCredentials) { envs.GOOGLE_APPLICATION_CREDENTIALS = googleApplicationCredentials; @@ -219,7 +215,7 @@ export async function apply( .withMountedCache("/app/.terraform", dag.cacheVolume("terraform-example"), { sharing: CacheSharingMode.Shared, }) - .withMountedCache("/app/plan", dag.cacheVolume("tfplan-example"), { + .withMountedCache("/app/plan", dag.cacheVolume("tfplan"), { sharing: CacheSharingMode.Shared, }) .withDirectory("/app", context, { exclude }) @@ -253,7 +249,7 @@ export async function apply( .pipeline("clear_plan") .container() .from("alpine") - .withMountedCache("/app/plan", dag.cacheVolume("tfplan-example")) + .withMountedCache("/app/plan", dag.cacheVolume("tfplan")) .withExec(["sh", "-c", "rm -rf /app/plan/*"]) .stdout(); diff --git a/example/.fluentci/src/dagger/lib.ts b/example/.fluentci/src/dagger/lib.ts index 13cb86e..4475f97 100644 --- a/example/.fluentci/src/dagger/lib.ts +++ b/example/.fluentci/src/dagger/lib.ts @@ -1,5 +1,4 @@ -import { Directory, DirectoryID, Container } from "../../deps.ts"; -import { dag } from "../../sdk/client.gen.ts"; +import { dag, Directory, DirectoryID, Container } from "../../deps.ts"; export const getDirectory = async ( src: string | Directory | undefined = "." diff --git a/example/.fluentci/src/dagger/pipeline.ts b/example/.fluentci/src/dagger/pipeline.ts index 9f80b97..1a0dee8 100644 --- a/example/.fluentci/src/dagger/pipeline.ts +++ b/example/.fluentci/src/dagger/pipeline.ts @@ -1,13 +1,8 @@ -import { uploadContext } from "../../deps.ts"; import * as jobs from "./jobs.ts"; -const { init, validate, plan, runnableJobs, exclude } = jobs; +const { init, validate, plan, runnableJobs } = jobs; export default async function pipeline(src = ".", args: string[] = []) { - if (Deno.env.has("FLUENTCI_SESSION_ID")) { - await uploadContext(src, exclude); - } - if (args.length > 0) { await runSpecificJobs(args as jobs.Job[]); return; diff --git a/example/apply.gql b/example/apply.gql deleted file mode 100644 index 0cc18a4..0000000 --- a/example/apply.gql +++ /dev/null @@ -1,9 +0,0 @@ -{ - terraform { - apply( - src: "." - tfVersion: "1.5.7" - googleApplicationCredentials: "fluentci-086b644d4c53.json" - ) - } -} diff --git a/example/init.gql b/example/init.gql deleted file mode 100644 index f441086..0000000 --- a/example/init.gql +++ /dev/null @@ -1,9 +0,0 @@ -{ - terraform { - init( - src: "." - tfVersion: "1.5.7" - googleApplicationCredentials: "./fluentci-086b644d4c53.json" - ) - } -} diff --git a/example/plan.gql b/example/plan.gql deleted file mode 100644 index d90617b..0000000 --- a/example/plan.gql +++ /dev/null @@ -1,9 +0,0 @@ -{ - terraform { - plan( - src: "." - tfVersion: "1.5.7" - googleApplicationCredentials: "./fluentci-086b644d4c53.json" - ) - } -} diff --git a/example/validate.gql b/example/validate.gql deleted file mode 100644 index 7ec67b6..0000000 --- a/example/validate.gql +++ /dev/null @@ -1,5 +0,0 @@ -{ - terraform { - validate(src: ".", tfVersion: "1.5.7") - } -} diff --git a/sdk/builder.ts b/sdk/builder.ts index f06951a..10182d6 100644 --- a/sdk/builder.ts +++ b/sdk/builder.ts @@ -1,5 +1,6 @@ import { createGQLClient } from "./client.ts"; import { Context } from "./context.ts"; +import { env } from "../deps.ts"; /** * @hidden @@ -10,9 +11,9 @@ export function initDefaultContext(): Context { let ctx = new Context(); // Prefer DAGGER_SESSION_PORT if set - const daggerSessionPort = Deno.env.get("DAGGER_SESSION_PORT"); + const daggerSessionPort = env.get("DAGGER_SESSION_PORT"); if (daggerSessionPort) { - const sessionToken = Deno.env.get("DAGGER_SESSION_TOKEN"); + const sessionToken = env.get("DAGGER_SESSION_TOKEN"); if (!sessionToken) { throw new Error( "DAGGER_SESSION_TOKEN must be set when using DAGGER_SESSION_PORT" diff --git a/sdk/client.gen.ts b/sdk/client.gen.ts index ae06cef..5e20f82 100644 --- a/sdk/client.gen.ts +++ b/sdk/client.gen.ts @@ -127,7 +127,7 @@ export type ContainerBuildOpts = { * * They will be mounted at /run/secrets/[secret-name] in the build container * - * They can be accessed in the Dockerfile using the "secret" mount type and mount path /run/secrets/[secret-name], e.g. RUN --mount=type=secret,id=my-secret curl http://example.com?token=$(cat /run/secrets/my-secret) + * They can be accessed in the Dockerfile using the "secret" mount type and mount path /run/secrets/[secret-name], e.g. RUN --mount=type=secret,id=my-secret curl [http://example.com?token=$(cat /run/secrets/my-secret)](http://example.com?token=$(cat /run/secrets/my-secret)) */ secrets?: Secret[]; }; @@ -306,6 +306,22 @@ export type ContainerWithFileOpts = { owner?: string; }; +export type ContainerWithFilesOpts = { + /** + * Permission given to the copied files (e.g., 0600). + */ + permissions?: number; + + /** + * A user:group to set for the files. + * + * The user and group can either be an ID (1000:1000) or a name (foo:bar). + * + * If the group is omitted, it defaults to the same as the user. + */ + owner?: string; +}; + export type ContainerWithMountedCacheOpts = { /** * Identifier of the directory to use as the cache volume's root. @@ -439,13 +455,13 @@ export type CurrentModuleID = string & { __CurrentModuleID: never }; export type DirectoryAsModuleOpts = { /** - * An optional subpath of the directory which contains the module's source code. + * An optional subpath of the directory which contains the module's configuration file. * * This is needed when the module code is in a subdirectory but requires parent directories to be loaded in order to execute. For example, the module source code may need a go.mod, project.toml, package.json, etc. file from a parent directory. * * If not set, the module source code is loaded from the root of the directory. */ - sourceSubpath?: string; + sourceRootPath?: string; }; export type DirectoryDockerBuildOpts = { @@ -515,6 +531,13 @@ export type DirectoryWithFileOpts = { permissions?: number; }; +export type DirectoryWithFilesOpts = { + /** + * Permission given to the copied files (e.g., 0600). + */ + permissions?: number; +}; + export type DirectoryWithNewDirectoryOpts = { /** * Permission granted to the created directory (e.g., 0777). @@ -852,11 +875,6 @@ export type ClientModuleDependencyOpts = { }; export type ClientModuleSourceOpts = { - /** - * An explicitly set root directory for the module source. This is required to load local sources as modules; other source types implicitly encode the root directory and do not require this. - */ - rootDirectory?: Directory; - /** * If true, enforce that the source is a stable version for source kinds that support versioning. */ @@ -875,6 +893,10 @@ export type ClientPipelineOpts = { labels?: PipelineLabel[]; }; +export type ClientSecretOpts = { + accessor?: string; +}; + /** * The `SecretID` scalar type represents an identifier for an object of type Secret. */ @@ -1184,7 +1206,7 @@ export class Container extends BaseClient { * * They will be mounted at /run/secrets/[secret-name] in the build container * - * They can be accessed in the Dockerfile using the "secret" mount type and mount path /run/secrets/[secret-name], e.g. RUN --mount=type=secret,id=my-secret curl http://example.com?token=$(cat /run/secrets/my-secret) + * They can be accessed in the Dockerfile using the "secret" mount type and mount path /run/secrets/[secret-name], e.g. RUN --mount=type=secret,id=my-secret curl [http://example.com?token=$(cat /run/secrets/my-secret)](http://example.com?token=$(cat /run/secrets/my-secret)) */ build = (context: Directory, opts?: ContainerBuildOpts): Container => { return new Container({ @@ -1993,6 +2015,34 @@ export class Container extends BaseClient { }); }; + /** + * Retrieves this container plus the contents of the given files copied to the given path. + * @param path Location where copied files should be placed (e.g., "/src"). + * @param sources Identifiers of the files to copy. + * @param opts.permissions Permission given to the copied files (e.g., 0600). + * @param opts.owner A user:group to set for the files. + * + * The user and group can either be an ID (1000:1000) or a name (foo:bar). + * + * If the group is omitted, it defaults to the same as the user. + */ + withFiles = ( + path: string, + sources: File[], + opts?: ContainerWithFilesOpts + ): Container => { + return new Container({ + queryTree: [ + ...this._queryTree, + { + operation: "withFiles", + args: { path, sources, ...opts }, + }, + ], + ctx: this._ctx, + }); + }; + /** * Indicate that subsequent operations should be featured more prominently in the UI. */ @@ -2719,7 +2769,7 @@ export class Directory extends BaseClient { /** * Load the directory as a Dagger module - * @param opts.sourceSubpath An optional subpath of the directory which contains the module's source code. + * @param opts.sourceRootPath An optional subpath of the directory which contains the module's configuration file. * * This is needed when the module code is in a subdirectory but requires parent directories to be loaded in order to execute. For example, the module source code may need a go.mod, project.toml, package.json, etc. file from a parent directory. * @@ -2956,6 +3006,29 @@ export class Directory extends BaseClient { }); }; + /** + * Retrieves this directory plus the contents of the given files copied to the given path. + * @param path Location where copied files should be placed (e.g., "/src"). + * @param sources Identifiers of the files to copy. + * @param opts.permissions Permission given to the copied files (e.g., 0600). + */ + withFiles = ( + path: string, + sources: File[], + opts?: DirectoryWithFilesOpts + ): Directory => { + return new Directory({ + queryTree: [ + ...this._queryTree, + { + operation: "withFiles", + args: { path, sources, ...opts }, + }, + ], + ctx: this._ctx, + }); + }; + /** * Retrieves this directory plus a new directory created at the given path. * @param path Location of the directory created (e.g., "/logs"). @@ -4167,7 +4240,7 @@ export class GitModuleSource extends BaseClient { private readonly _cloneURL?: string = undefined; private readonly _commit?: string = undefined; private readonly _htmlURL?: string = undefined; - private readonly _sourceSubpath?: string = undefined; + private readonly _rootSubpath?: string = undefined; private readonly _version?: string = undefined; /** @@ -4179,7 +4252,7 @@ export class GitModuleSource extends BaseClient { _cloneURL?: string, _commit?: string, _htmlURL?: string, - _sourceSubpath?: string, + _rootSubpath?: string, _version?: string ) { super(parent); @@ -4188,7 +4261,7 @@ export class GitModuleSource extends BaseClient { this._cloneURL = _cloneURL; this._commit = _commit; this._htmlURL = _htmlURL; - this._sourceSubpath = _sourceSubpath; + this._rootSubpath = _rootSubpath; this._version = _version; } @@ -4255,6 +4328,21 @@ export class GitModuleSource extends BaseClient { return response; }; + /** + * The directory containing everything needed to load load and use the module. + */ + contextDirectory = (): Directory => { + return new Directory({ + queryTree: [ + ...this._queryTree, + { + operation: "contextDirectory", + }, + ], + ctx: this._ctx, + }); + }; + /** * The URL to the source's git repo in a web browser */ @@ -4277,18 +4365,18 @@ export class GitModuleSource extends BaseClient { }; /** - * The path to the module source code dir specified by this source relative to the source's root directory. + * The path to the root of the module source under the context directory. This directory contains its configuration file. It also contains its source code (possibly as a subdirectory). */ - sourceSubpath = async (): Promise => { - if (this._sourceSubpath) { - return this._sourceSubpath; + rootSubpath = async (): Promise => { + if (this._rootSubpath) { + return this._rootSubpath; } const response: Awaited = await computeQuery( [ ...this._queryTree, { - operation: "sourceSubpath", + operation: "rootSubpath", }, ], await this._ctx.connection() @@ -5074,7 +5162,7 @@ export class ListTypeDef extends BaseClient { */ export class LocalModuleSource extends BaseClient { private readonly _id?: LocalModuleSourceID = undefined; - private readonly _sourceSubpath?: string = undefined; + private readonly _rootSubpath?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. @@ -5082,12 +5170,12 @@ export class LocalModuleSource extends BaseClient { constructor( parent?: { queryTree?: QueryTree[]; ctx: Context }, _id?: LocalModuleSourceID, - _sourceSubpath?: string + _rootSubpath?: string ) { super(parent); this._id = _id; - this._sourceSubpath = _sourceSubpath; + this._rootSubpath = _rootSubpath; } /** @@ -5112,18 +5200,33 @@ export class LocalModuleSource extends BaseClient { }; /** - * The path to the module source code dir specified by this source. + * The directory containing everything needed to load load and use the module. */ - sourceSubpath = async (): Promise => { - if (this._sourceSubpath) { - return this._sourceSubpath; + contextDirectory = (): Directory => { + return new Directory({ + queryTree: [ + ...this._queryTree, + { + operation: "contextDirectory", + }, + ], + ctx: this._ctx, + }); + }; + + /** + * The path to the root of the module source under the context directory. This directory contains its configuration file. It also contains its source code (possibly as a subdirectory). + */ + rootSubpath = async (): Promise => { + if (this._rootSubpath) { + return this._rootSubpath; } const response: Awaited = await computeQuery( [ ...this._queryTree, { - operation: "sourceSubpath", + operation: "rootSubpath", }, ], await this._ctx.connection() @@ -5282,14 +5385,29 @@ export class Module_ extends BaseClient { }; /** - * The module's root directory containing the config file for it and its source (possibly as a subdir). It includes any generated code or updated config files created after initial load, but not any files/directories that were unchanged after sdk codegen was run. + * The generated files and directories made on top of the module source's context directory. + */ + generatedContextDiff = (): Directory => { + return new Directory({ + queryTree: [ + ...this._queryTree, + { + operation: "generatedContextDiff", + }, + ], + ctx: this._ctx, + }); + }; + + /** + * The module source's context plus any configuration and source files created by codegen. */ - generatedSourceRootDirectory = (): Directory => { + generatedContextDirectory = (): Directory => { return new Directory({ queryTree: [ ...this._queryTree, { - operation: "generatedSourceRootDirectory", + operation: "generatedContextDirectory", }, ], ctx: this._ctx, @@ -5482,23 +5600,6 @@ export class Module_ extends BaseClient { }); }; - /** - * Update the module configuration to use the given dependencies. - * @param dependencies The dependency modules to install. - */ - withDependencies = (dependencies: ModuleDependency[]): Module_ => { - return new Module_({ - queryTree: [ - ...this._queryTree, - { - operation: "withDependencies", - args: { dependencies }, - }, - ], - ctx: this._ctx, - }); - }; - /** * Retrieves the module with the given description * @param description The description to set @@ -5532,23 +5633,6 @@ export class Module_ extends BaseClient { }); }; - /** - * Update the module configuration to use the given name. - * @param name The name to use. - */ - withName = (name: string): Module_ => { - return new Module_({ - queryTree: [ - ...this._queryTree, - { - operation: "withName", - args: { name }, - }, - ], - ctx: this._ctx, - }); - }; - /** * This module plus the given Object type and associated functions. */ @@ -5565,23 +5649,6 @@ export class Module_ extends BaseClient { }); }; - /** - * Update the module configuration to use the given SDK. - * @param sdk The SDK to use. - */ - withSDK = (sdk: string): Module_ => { - return new Module_({ - queryTree: [ - ...this._queryTree, - { - operation: "withSDK", - args: { sdk }, - }, - ], - ctx: this._ctx, - }); - }; - /** * Retrieves the module with basic configuration loaded if present. * @param source The module source to initialize from. @@ -5694,9 +5761,13 @@ export class ModuleDependency extends BaseClient { export class ModuleSource extends BaseClient { private readonly _id?: ModuleSourceID = undefined; private readonly _asString?: string = undefined; + private readonly _configExists?: boolean = undefined; private readonly _kind?: ModuleSourceKind = undefined; private readonly _moduleName?: string = undefined; - private readonly _subpath?: string = undefined; + private readonly _moduleOriginalName?: string = undefined; + private readonly _resolveContextPathFromCaller?: string = undefined; + private readonly _sourceRootSubpath?: string = undefined; + private readonly _sourceSubpath?: string = undefined; /** * Constructor is used for internal usage only, do not create object from it. @@ -5705,17 +5776,25 @@ export class ModuleSource extends BaseClient { parent?: { queryTree?: QueryTree[]; ctx: Context }, _id?: ModuleSourceID, _asString?: string, + _configExists?: boolean, _kind?: ModuleSourceKind, _moduleName?: string, - _subpath?: string + _moduleOriginalName?: string, + _resolveContextPathFromCaller?: string, + _sourceRootSubpath?: string, + _sourceSubpath?: string ) { super(parent); this._id = _id; this._asString = _asString; + this._configExists = _configExists; this._kind = _kind; this._moduleName = _moduleName; - this._subpath = _subpath; + this._moduleOriginalName = _moduleOriginalName; + this._resolveContextPathFromCaller = _resolveContextPathFromCaller; + this._sourceRootSubpath = _sourceRootSubpath; + this._sourceSubpath = _sourceSubpath; } /** @@ -5806,7 +5885,81 @@ export class ModuleSource extends BaseClient { }; /** - * The directory containing the actual module's source code, as determined from the root directory and subpath. + * Returns whether the module source has a configuration file. + */ + configExists = async (): Promise => { + if (this._configExists) { + return this._configExists; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "configExists", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + + /** + * The directory containing everything needed to load load and use the module. + */ + contextDirectory = (): Directory => { + return new Directory({ + queryTree: [ + ...this._queryTree, + { + operation: "contextDirectory", + }, + ], + ctx: this._ctx, + }); + }; + + /** + * The dependencies of the module source. Includes dependencies from the configuration and any extras from withDependencies calls. + */ + dependencies = async (): Promise => { + type dependencies = { + id: ModuleDependencyID; + }; + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "dependencies", + }, + { + operation: "id", + }, + ], + await this._ctx.connection() + ); + + return response.map( + (r) => + new ModuleDependency( + { + queryTree: [ + { + operation: "loadModuleDependencyFromID", + args: { id: r.id }, + }, + ], + ctx: this._ctx, + }, + r.id + ) + ); + }; + + /** + * The directory containing the module configuration and source code (source code may be in a subdir). * @param path The path from the source directory to select. */ directory = (path: string): Directory => { @@ -5844,7 +5997,7 @@ export class ModuleSource extends BaseClient { }; /** - * If set, the name of the module this source references + * If set, the name of the module this source references, including any overrides at runtime by callers. */ moduleName = async (): Promise => { if (this._moduleName) { @@ -5864,6 +6017,48 @@ export class ModuleSource extends BaseClient { return response; }; + /** + * The original name of the module this source references, as defined in the module configuration. + */ + moduleOriginalName = async (): Promise => { + if (this._moduleOriginalName) { + return this._moduleOriginalName; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "moduleOriginalName", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + + /** + * The path to the module source's context directory on the caller's filesystem. Only valid for local sources. + */ + resolveContextPathFromCaller = async (): Promise => { + if (this._resolveContextPathFromCaller) { + return this._resolveContextPathFromCaller; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "resolveContextPathFromCaller", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + /** * Resolve the provided module source arg as a dependency relative to this module source. * @param dep The dependency module source to resolve. @@ -5882,14 +6077,14 @@ export class ModuleSource extends BaseClient { }; /** - * The root directory of the module source that contains its configuration and source code (which may be in a subdirectory of this root). + * Load the source from its path on the caller's filesystem, including only needed+configured files and directories. Only valid for local sources. */ - rootDirectory = (): Directory => { - return new Directory({ + resolveFromCaller = (): ModuleSource => { + return new ModuleSource({ queryTree: [ ...this._queryTree, { - operation: "rootDirectory", + operation: "resolveFromCaller", }, ], ctx: this._ctx, @@ -5897,18 +6092,39 @@ export class ModuleSource extends BaseClient { }; /** - * The path to the module subdirectory containing the actual module's source code. + * The path relative to context of the root of the module source, which contains dagger.json. It also contains the module implementation source code, but that may or may not being a subdir of this root. + */ + sourceRootSubpath = async (): Promise => { + if (this._sourceRootSubpath) { + return this._sourceRootSubpath; + } + + const response: Awaited = await computeQuery( + [ + ...this._queryTree, + { + operation: "sourceRootSubpath", + }, + ], + await this._ctx.connection() + ); + + return response; + }; + + /** + * The path relative to context of the module implementation source code. */ - subpath = async (): Promise => { - if (this._subpath) { - return this._subpath; + sourceSubpath = async (): Promise => { + if (this._sourceSubpath) { + return this._sourceSubpath; } const response: Awaited = await computeQuery( [ ...this._queryTree, { - operation: "subpath", + operation: "sourceSubpath", }, ], await this._ctx.connection() @@ -5917,6 +6133,91 @@ export class ModuleSource extends BaseClient { return response; }; + /** + * Update the module source with a new context directory. Only valid for local sources. + * @param dir The directory to set as the context directory. + */ + withContextDirectory = (dir: Directory): ModuleSource => { + return new ModuleSource({ + queryTree: [ + ...this._queryTree, + { + operation: "withContextDirectory", + args: { dir }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Append the provided dependencies to the module source's dependency list. + * @param dependencies The dependencies to append. + */ + withDependencies = (dependencies: ModuleDependency[]): ModuleSource => { + return new ModuleSource({ + queryTree: [ + ...this._queryTree, + { + operation: "withDependencies", + args: { dependencies }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Update the module source with a new name. + * @param name The name to set. + */ + withName = (name: string): ModuleSource => { + return new ModuleSource({ + queryTree: [ + ...this._queryTree, + { + operation: "withName", + args: { name }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Update the module source with a new SDK. + * @param sdk The SDK to set. + */ + withSDK = (sdk: string): ModuleSource => { + return new ModuleSource({ + queryTree: [ + ...this._queryTree, + { + operation: "withSDK", + args: { sdk }, + }, + ], + ctx: this._ctx, + }); + }; + + /** + * Update the module source with a new source subpath. + * @param path The path to set as the source subpath. + */ + withSourceSubpath = (path: string): ModuleSource => { + return new ModuleSource({ + queryTree: [ + ...this._queryTree, + { + operation: "withSourceSubpath", + args: { path }, + }, + ], + ctx: this._ctx, + }); + }; + /** * Call the provided function with current ModuleSource. * @@ -6312,6 +6613,23 @@ export class Client extends BaseClient { }); }; + /** + * Retrieves a container builtin to the engine. + * @param digest Digest of the image manifest + */ + builtinContainer = (digest: string): Container => { + return new Container({ + queryTree: [ + ...this._queryTree, + { + operation: "builtinContainer", + args: { digest }, + }, + ], + ctx: this._ctx, + }); + }; + /** * Constructs a cache volume for a given cache key. * @param key A string identifier to target this cache volume (e.g., "modules-cache"). @@ -7119,7 +7437,6 @@ export class Client extends BaseClient { /** * Create a new module source instance from a source ref string. * @param refString The string ref representation of the module source - * @param opts.rootDirectory An explicitly set root directory for the module source. This is required to load local sources as modules; other source types implicitly encode the root directory and do not require this. * @param opts.stable If true, enforce that the source is a stable version for source kinds that support versioning. */ moduleSource = ( @@ -7160,13 +7477,13 @@ export class Client extends BaseClient { /** * Reference a secret by name. */ - secret = (name: string): Secret => { + secret = (name: string, opts?: ClientSecretOpts): Secret => { return new Secret({ queryTree: [ ...this._queryTree, { operation: "secret", - args: { name }, + args: { name, ...opts }, }, ], ctx: this._ctx, diff --git a/sdk/common/errors/DaggerSDKError.ts b/sdk/common/errors/DaggerSDKError.ts new file mode 100644 index 0000000..f2f009d --- /dev/null +++ b/sdk/common/errors/DaggerSDKError.ts @@ -0,0 +1,46 @@ +import { log } from "../utils.ts"; +import { ErrorCodes, ErrorNames } from "./errors-codes.ts"; + +export interface DaggerSDKErrorOptions { + cause?: Error; +} + +/** + * The base error. Every other error inherits this error. + */ +export abstract class DaggerSDKError extends Error { + /** + * The name of the dagger error. + */ + abstract readonly name: ErrorNames; + + /** + * The dagger specific error code. + * Use this to identify dagger errors programmatically. + */ + abstract readonly code: ErrorCodes; + + /** + * The original error, which caused the DaggerSDKError. + */ + cause?: Error; + + protected constructor(message: string, options?: DaggerSDKErrorOptions) { + super(message); + this.cause = options?.cause; + } + + /** + * @hidden + */ + get [Symbol.toStringTag]() { + return this.name; + } + + /** + * Pretty prints the error + */ + printStackTrace() { + log(this.stack); + } +} diff --git a/sdk/common/errors/DockerImageRefValidationError.ts b/sdk/common/errors/DockerImageRefValidationError.ts new file mode 100644 index 0000000..6f45b46 --- /dev/null +++ b/sdk/common/errors/DockerImageRefValidationError.ts @@ -0,0 +1,28 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts" +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts" + +interface DockerImageRefValidationErrorOptions extends DaggerSDKErrorOptions { + ref: string +} + +/** + * This error is thrown if the passed image reference does not pass validation and is not compliant with the + * DockerImage constructor. + */ +export class DockerImageRefValidationError extends DaggerSDKError { + name = ERROR_NAMES.DockerImageRefValidationError + code = ERROR_CODES.DockerImageRefValidationError + + /** + * The docker image reference, which caused the error. + */ + ref: string + + /** + * @hidden + */ + constructor(message: string, options: DockerImageRefValidationErrorOptions) { + super(message, options) + this.ref = options?.ref + } +} diff --git a/sdk/common/errors/EngineSessionConnectParamsParseError.ts b/sdk/common/errors/EngineSessionConnectParamsParseError.ts new file mode 100644 index 0000000..8acd47a --- /dev/null +++ b/sdk/common/errors/EngineSessionConnectParamsParseError.ts @@ -0,0 +1,31 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +interface EngineSessionConnectParamsParseErrorOptions + extends DaggerSDKErrorOptions { + parsedLine: string; +} + +/** + * This error is thrown if the EngineSession does not manage to parse the required connection parameters from the session binary + */ +export class EngineSessionConnectParamsParseError extends DaggerSDKError { + name = ERROR_NAMES.EngineSessionConnectParamsParseError; + code = ERROR_CODES.EngineSessionConnectParamsParseError; + + /** + * the line, which caused the error during parsing, if the error was caused because of parsing. + */ + parsedLine: string; + + /** + * @hidden + */ + constructor( + message: string, + options: EngineSessionConnectParamsParseErrorOptions + ) { + super(message, options); + this.parsedLine = options.parsedLine; + } +} diff --git a/sdk/common/errors/EngineSessionConnectionTimeoutError.ts b/sdk/common/errors/EngineSessionConnectionTimeoutError.ts new file mode 100644 index 0000000..e2550ac --- /dev/null +++ b/sdk/common/errors/EngineSessionConnectionTimeoutError.ts @@ -0,0 +1,31 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +interface EngineSessionConnectionTimeoutErrorOptions + extends DaggerSDKErrorOptions { + timeOutDuration: number; +} + +/** + * This error is thrown if the EngineSession does not manage to parse the required port successfully because the sessions connection timed out. + */ +export class EngineSessionConnectionTimeoutError extends DaggerSDKError { + name = ERROR_NAMES.EngineSessionConnectionTimeoutError; + code = ERROR_CODES.EngineSessionConnectionTimeoutError; + + /** + * The duration until the timeout occurred in ms. + */ + timeOutDuration: number; + + /** + * @hidden + */ + constructor( + message: string, + options: EngineSessionConnectionTimeoutErrorOptions + ) { + super(message, options); + this.timeOutDuration = options.timeOutDuration; + } +} diff --git a/sdk/common/errors/EngineSessionErrorOptions.ts b/sdk/common/errors/EngineSessionErrorOptions.ts new file mode 100644 index 0000000..ba0ec90 --- /dev/null +++ b/sdk/common/errors/EngineSessionErrorOptions.ts @@ -0,0 +1,20 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +type EngineSessionErrorOptions = DaggerSDKErrorOptions; + +/** + * This error is thrown if the EngineSession does not manage to parse the required port successfully because a EOF is read before any valid port. + * This usually happens if no connection can be established. + */ +export class EngineSessionError extends DaggerSDKError { + name = ERROR_NAMES.EngineSessionError; + code = ERROR_CODES.EngineSessionError; + + /** + * @hidden + */ + constructor(message: string, options?: EngineSessionErrorOptions) { + super(message, options); + } +} diff --git a/sdk/common/errors/ExecError.ts b/sdk/common/errors/ExecError.ts new file mode 100644 index 0000000..ede655b --- /dev/null +++ b/sdk/common/errors/ExecError.ts @@ -0,0 +1,54 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +interface ExecErrorOptions extends DaggerSDKErrorOptions { + cmd: string[]; + exitCode: number; + stdout: string; + stderr: string; +} + +/** + * API error from an exec operation in a pipeline. + */ +export class ExecError extends DaggerSDKError { + name = ERROR_NAMES.ExecError; + code = ERROR_CODES.ExecError; + + /** + * The command that caused the error. + */ + cmd: string[]; + + /** + * The exit code of the command. + */ + exitCode: number; + + /** + * The stdout of the command. + */ + stdout: string; + + /** + * The stderr of the command. + */ + stderr: string; + + /** + * @hidden + */ + constructor(message: string, options: ExecErrorOptions) { + super(message, options); + this.cmd = options.cmd; + this.exitCode = options.exitCode; + this.stdout = options.stdout; + this.stderr = options.stderr; + } + + toString(): string { + return `${super.toString()}\nStdout:\n${this.stdout}\nStderr:\n${ + this.stderr + }`; + } +} diff --git a/sdk/common/errors/GraphQLRequestError.ts b/sdk/common/errors/GraphQLRequestError.ts new file mode 100644 index 0000000..59584f8 --- /dev/null +++ b/sdk/common/errors/GraphQLRequestError.ts @@ -0,0 +1,36 @@ +import { GraphQLRequestContext, GraphQLResponse } from "./types.ts"; + +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +interface GraphQLRequestErrorOptions extends DaggerSDKErrorOptions { + response: GraphQLResponse; + request: GraphQLRequestContext; +} + +/** + * This error originates from the dagger engine. It means that some error was thrown and sent back via GraphQL. + */ +export class GraphQLRequestError extends DaggerSDKError { + name = ERROR_NAMES.GraphQLRequestError; + code = ERROR_CODES.GraphQLRequestError; + + /** + * The query and variables, which caused the error. + */ + requestContext: GraphQLRequestContext; + + /** + * the GraphQL response containing the error. + */ + response: GraphQLResponse; + + /** + * @hidden + */ + constructor(message: string, options: GraphQLRequestErrorOptions) { + super(message, options); + this.requestContext = options.request; + this.response = options.response; + } +} diff --git a/sdk/common/errors/InitEngineSessionBinaryError.ts b/sdk/common/errors/InitEngineSessionBinaryError.ts new file mode 100644 index 0000000..879c1ce --- /dev/null +++ b/sdk/common/errors/InitEngineSessionBinaryError.ts @@ -0,0 +1,17 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +/** + * This error is thrown if the dagger binary cannot be copied from the dagger docker image and copied to the local host. + */ +export class InitEngineSessionBinaryError extends DaggerSDKError { + name = ERROR_NAMES.InitEngineSessionBinaryError; + code = ERROR_CODES.InitEngineSessionBinaryError; + + /** + * @hidden + */ + constructor(message: string, options?: DaggerSDKErrorOptions) { + super(message, options); + } +} diff --git a/sdk/common/errors/NotAwaitedRequestError.ts b/sdk/common/errors/NotAwaitedRequestError.ts new file mode 100644 index 0000000..291b924 --- /dev/null +++ b/sdk/common/errors/NotAwaitedRequestError.ts @@ -0,0 +1,17 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +/** + * This error is thrown when the compute function isn't awaited. + */ +export class NotAwaitedRequestError extends DaggerSDKError { + name = ERROR_NAMES.NotAwaitedRequestError; + code = ERROR_CODES.NotAwaitedRequestError; + + /** + * @hidden + */ + constructor(message: string, options?: DaggerSDKErrorOptions) { + super(message, options); + } +} diff --git a/sdk/common/errors/TooManyNestedObjectsError.ts b/sdk/common/errors/TooManyNestedObjectsError.ts new file mode 100644 index 0000000..7b8b907 --- /dev/null +++ b/sdk/common/errors/TooManyNestedObjectsError.ts @@ -0,0 +1,27 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +interface TooManyNestedObjectsErrorOptions extends DaggerSDKErrorOptions { + response: unknown; +} + +/** + * Dagger only expects one response value from the engine. If the engine returns more than one value this error is thrown. + */ +export class TooManyNestedObjectsError extends DaggerSDKError { + name = ERROR_NAMES.TooManyNestedObjectsError; + code = ERROR_CODES.TooManyNestedObjectsError; + + /** + * the response containing more than one value. + */ + response: unknown; + + /** + * @hidden + */ + constructor(message: string, options: TooManyNestedObjectsErrorOptions) { + super(message, options); + this.response = options.response; + } +} diff --git a/sdk/common/errors/UnknownDaggerError.ts b/sdk/common/errors/UnknownDaggerError.ts new file mode 100644 index 0000000..fe29169 --- /dev/null +++ b/sdk/common/errors/UnknownDaggerError.ts @@ -0,0 +1,17 @@ +import { DaggerSDKError, DaggerSDKErrorOptions } from "./DaggerSDKError.ts"; +import { ERROR_CODES, ERROR_NAMES } from "./errors-codes.ts"; + +/** + * This error is thrown if the dagger SDK does not identify the error and just wraps the cause. + */ +export class UnknownDaggerError extends DaggerSDKError { + name = ERROR_NAMES.UnknownDaggerError; + code = ERROR_CODES.UnknownDaggerError; + + /** + * @hidden + */ + constructor(message: string, options: DaggerSDKErrorOptions) { + super(message, options); + } +} diff --git a/sdk/common/errors/errors-codes.ts b/sdk/common/errors/errors-codes.ts new file mode 100644 index 0000000..a6e4d48 --- /dev/null +++ b/sdk/common/errors/errors-codes.ts @@ -0,0 +1,63 @@ +export const ERROR_CODES = { + /** + * {@link GraphQLRequestError} + */ + GraphQLRequestError: "D100", + + /** + * {@link UnknownDaggerError} + */ + UnknownDaggerError: "D101", + + /** + * {@link TooManyNestedObjectsError} + */ + TooManyNestedObjectsError: "D102", + + /** + * {@link EngineSessionConnectParamsParseError} + */ + EngineSessionConnectParamsParseError: "D103", + + /** + * {@link EngineSessionConnectionTimeoutError} + */ + EngineSessionConnectionTimeoutError: "D104", + + /** + * {@link EngineSessionError} + */ + EngineSessionError: "D105", + + /** + * {@link InitEngineSessionBinaryError} + */ + InitEngineSessionBinaryError: "D106", + + /** + * {@link DockerImageRefValidationError} + */ + DockerImageRefValidationError: "D107", + + /** + * {@link NotAwaitedRequestError} + */ + NotAwaitedRequestError: "D108", + + /** + * (@link ExecError} + */ + ExecError: "D109", +} as const + +type ErrorCodesType = typeof ERROR_CODES +export type ErrorNames = keyof ErrorCodesType +export type ErrorCodes = ErrorCodesType[ErrorNames] + +type ErrorNamesMap = { readonly [Key in ErrorNames]: Key } +export const ERROR_NAMES: ErrorNamesMap = ( + Object.keys(ERROR_CODES) as Array +).reduce( + (obj, item) => ({ ...obj, [item]: item }), + {} as ErrorNamesMap +) diff --git a/sdk/common/errors/index.ts b/sdk/common/errors/index.ts new file mode 100644 index 0000000..61faf70 --- /dev/null +++ b/sdk/common/errors/index.ts @@ -0,0 +1,12 @@ +export { DaggerSDKError } from "./DaggerSDKError.ts"; +export { UnknownDaggerError } from "./UnknownDaggerError.ts"; +export { DockerImageRefValidationError } from "./DockerImageRefValidationError.ts"; +export { EngineSessionConnectParamsParseError } from "./EngineSessionConnectParamsParseError.ts"; +export { ExecError } from "./ExecError.ts"; +export { GraphQLRequestError } from "./GraphQLRequestError.ts"; +export { InitEngineSessionBinaryError } from "./InitEngineSessionBinaryError.ts"; +export { TooManyNestedObjectsError } from "./TooManyNestedObjectsError.ts"; +export { EngineSessionError } from "./EngineSessionErrorOptions.ts"; +export { EngineSessionConnectionTimeoutError } from "./EngineSessionConnectionTimeoutError.ts"; +export { NotAwaitedRequestError } from "./NotAwaitedRequestError.ts"; +export { ERROR_CODES } from "./errors-codes.ts"; diff --git a/sdk/common/errors/types.ts b/sdk/common/errors/types.ts new file mode 100644 index 0000000..f5b1582 --- /dev/null +++ b/sdk/common/errors/types.ts @@ -0,0 +1,16 @@ +import { GraphQLError } from "npm:graphql@16.8.1"; + +export interface GraphQLResponse { + data?: T; + errors?: GraphQLError[]; + extensions?: unknown; + status: number; + [key: string]: unknown; +} + +export type Variables = Record; + +export interface GraphQLRequestContext { + query: string | string[]; + variables?: V; +} diff --git a/sdk/common/utils.ts b/sdk/common/utils.ts new file mode 100644 index 0000000..5853601 --- /dev/null +++ b/sdk/common/utils.ts @@ -0,0 +1,4 @@ +import logger from "npm:node-color-log@11.0.2"; + +export const log = (stack?: string) => + logger.bgColor("red").color("black").log(stack); diff --git a/src/dagger/jobs.ts b/src/dagger/jobs.ts index 7918808..743caee 100644 --- a/src/dagger/jobs.ts +++ b/src/dagger/jobs.ts @@ -3,7 +3,7 @@ * @description Module for running Terraform commands */ -import { Directory, dag } from "../../deps.ts"; +import { Directory, dag, env } from "../../deps.ts"; import { CacheSharingMode } from "../../sdk/client.gen.ts"; import { filterObjectByPrefix, withEnvs, getDirectory } from "./lib.ts"; @@ -16,11 +16,7 @@ export enum Job { export const exclude = [".terraform", ".git", ".fluentci", "plan"]; -const envs = filterObjectByPrefix(Deno.env.toObject(), [ - "TF_", - "AWS_", - "GOOGLE_", -]); +const envs = filterObjectByPrefix(env.toObject(), ["TF_", "AWS_", "GOOGLE_"]); /** * @function @@ -36,7 +32,7 @@ export async function init( googleApplicationCredentials?: string ): Promise { const context = await getDirectory(src); - const TF_VERSION = tfVersion || Deno.env.get("TF_VERSION") || "latest"; + const TF_VERSION = tfVersion || env.get("TF_VERSION") || "latest"; if (googleApplicationCredentials) { envs.GOOGLE_APPLICATION_CREDENTIALS = googleApplicationCredentials; @@ -78,7 +74,7 @@ export async function validate( tfVersion?: string ): Promise { const context = await getDirectory(src); - const TF_VERSION = tfVersion || Deno.env.get("TF_VERSION") || "latest"; + const TF_VERSION = tfVersion || env.get("TF_VERSION") || "latest"; const baseCtr = withEnvs( dag @@ -137,7 +133,7 @@ export async function plan( googleApplicationCredentials?: string ): Promise { const context = await getDirectory(src); - const TF_VERSION = tfVersion || Deno.env.get("TF_VERSION") || "latest"; + const TF_VERSION = tfVersion || env.get("TF_VERSION") || "latest"; if (googleApplicationCredentials) { envs.GOOGLE_APPLICATION_CREDENTIALS = googleApplicationCredentials; @@ -201,7 +197,7 @@ export async function apply( googleApplicationCredentials?: string ): Promise { const context = await getDirectory(src); - const TF_VERSION = tfVersion || Deno.env.get("TF_VERSION") || "latest"; + const TF_VERSION = tfVersion || env.get("TF_VERSION") || "latest"; if (googleApplicationCredentials) { envs.GOOGLE_APPLICATION_CREDENTIALS = googleApplicationCredentials; diff --git a/src/dagger/lib.ts b/src/dagger/lib.ts index 13cb86e..4475f97 100644 --- a/src/dagger/lib.ts +++ b/src/dagger/lib.ts @@ -1,5 +1,4 @@ -import { Directory, DirectoryID, Container } from "../../deps.ts"; -import { dag } from "../../sdk/client.gen.ts"; +import { dag, Directory, DirectoryID, Container } from "../../deps.ts"; export const getDirectory = async ( src: string | Directory | undefined = "." diff --git a/src/dagger/pipeline.ts b/src/dagger/pipeline.ts index 9f80b97..1a0dee8 100644 --- a/src/dagger/pipeline.ts +++ b/src/dagger/pipeline.ts @@ -1,13 +1,8 @@ -import { uploadContext } from "../../deps.ts"; import * as jobs from "./jobs.ts"; -const { init, validate, plan, runnableJobs, exclude } = jobs; +const { init, validate, plan, runnableJobs } = jobs; export default async function pipeline(src = ".", args: string[] = []) { - if (Deno.env.has("FLUENTCI_SESSION_ID")) { - await uploadContext(src, exclude); - } - if (args.length > 0) { await runSpecificJobs(args as jobs.Job[]); return;