Archive: post-init work (19 commits)#10
Conversation
functions testing harness
Dev/testing strategy using a matrix
There was a problem hiding this comment.
Pull request overview
Archives a large set of post-init commits adding a Kubernetes-based function testing harness, multiple function prototypes, and supporting CI/CD + K8s manifests for local/dev workflows.
Changes:
- Adds centralized KubernetesJS test runner + Makefile targets and CI matrix to run function tests in-cluster.
- Introduces multiple new example/prototype functions (Node, Bash, Rust, Python) and corresponding K8s/Knative manifests.
- Updates TypeScript/Jest tooling and function packaging to support builds/tests/publishing.
Reviewed changes
Copilot reviewed 123 out of 129 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.json | Adjusts root TS compiler settings to support the new scripts/tests layout. |
| scripts/test-runner.ts | Adds centralized Kubernetes Job-based Jest runner for function tests. |
| scripts/run-function-test.sh | Adds helper script to invoke centralized test runner per-function. |
| pnpm-workspace.yaml | Includes scripts/ in workspace discovery. |
| package.json | Adds Jest/dotenv/kubernetesjs/ts-node tooling for test runner & tests. |
| k8s/scripts/setup/01-install-operators.sh | Improves pod-ready waiting logic during operator install. |
| k8s/scripts/scaffold-function.sh | Adds scaffolding script for new function + manifest creation. |
| k8s/overlays/local/kustomization.yaml | Includes hello-world/runtime-script resources in local overlay. |
| k8s/overlays/local/constructive/knative-job-service.yaml | Extends supported job routing map to additional functions. |
| k8s/base/functions/stripe-function.yaml | Adds Knative Service manifest for stripe-function. |
| k8s/base/functions/simple-bash.yaml | Adds a simple batch Job manifest for bash example. |
| k8s/base/functions/rust-hello-world.yaml | Adds Knative Service manifest for rust hello-world image. |
| k8s/base/functions/runtime-script.yaml | Adds Knative Service manifest for runtime-script function. |
| k8s/base/functions/pytorch-gpu.yaml | Adds Knative Service manifest for pytorch-gpu example. |
| k8s/base/functions/opencode-headless.yaml | Adds Knative Service manifest for opencode-headless function. |
| k8s/base/functions/llm-internal-calvin.yaml | Adds Knative Service manifest for internal Calvin LLM function. |
| k8s/base/functions/llm-external.yaml | Adds Knative Service manifest for external LLM function. |
| k8s/base/functions/hello-world.yaml | Adds Knative Service manifest for hello-world function. |
| k8s/base/functions/github-repo-creator.yaml | Adds Knative Service manifest for GitHub repo creator function. |
| k8s/base/functions/crypto-login.yaml | Adds Knative Service manifest for crypto-login function. |
| k8s/Makefile | Adds spin-up/down helpers, scaffold target, and safer delete/pull-secret steps. |
| jest.config.js | Adds root Jest config using ts-jest. |
| functions/twilio-sms/tsconfig.json | Adds per-function TS config for build/test outputs. |
| functions/twilio-sms/src/index.ts | Adds Twilio SMS function implementation. |
| functions/twilio-sms/package.json | Adds build/test scripts and deps for twilio-sms package. |
| functions/twilio-sms/tests/index.test.ts | Adds K8s integration test for twilio-sms. |
| functions/test-utils.ts | Adds shared K8s job teardown helper for tests. |
| functions/stripe-function/tsconfig.json | Adds per-function TS config for stripe-function. |
| functions/stripe-function/src/index.ts | Adds Stripe function prototype. |
| functions/stripe-function/package.json | Adds build/test scripts and deps for stripe-function. |
| functions/stripe-function/tests/index.test.ts | Adds K8s integration test for stripe-function. |
| functions/simple-email/tsconfig.json | Reworks TS config (no longer extends root) for build/test. |
| functions/simple-email/src/index.ts | Refactors simple-email to default handler function (runner-driven). |
| functions/simple-email/package.json | Makes package publishable and adds test/build scripts + deps. |
| functions/simple-email/node_modules_bad/typescript | Adds local node_modules artifact placeholder (should not be committed). |
| functions/simple-email/node_modules_bad/ts-jest | Adds local node_modules artifact placeholder (should not be committed). |
| functions/simple-email/node_modules_bad/rimraf | Adds local node_modules artifact placeholder (should not be committed). |
| functions/simple-email/node_modules_bad/pgsql-test | Adds local node_modules artifact placeholder (should not be committed). |
| functions/simple-email/node_modules_bad/kubernetesjs | Adds local node_modules artifact placeholder (should not be committed). |
| functions/simple-email/node_modules_bad/jest | Adds local node_modules artifact placeholder (should not be committed). |
| functions/simple-email/node_modules_bad/@types/node | Adds local node_modules artifact placeholder (should not be committed). |
| functions/simple-email/node_modules_bad/@types/jest | Adds local node_modules artifact placeholder (should not be committed). |
| functions/simple-email/node_modules_bad/@pgpmjs/env | Adds local node_modules artifact placeholder (should not be committed). |
| functions/simple-email/node_modules_bad/@launchql/postmaster | Adds local node_modules artifact placeholder (should not be committed). |
| functions/simple-email/node_modules_bad/@constructive-io/knative-job-fn | Adds local node_modules artifact placeholder (should not be committed). |
| functions/simple-email/node_modules_bad/.pnpm-workspace-state-v1.json | Adds local pnpm workspace state artifact (should not be committed). |
| functions/simple-email/node_modules_bad/.bin/tsserver | Adds local binary with absolute paths (should not be committed). |
| functions/simple-email/node_modules_bad/.bin/tsc | Adds local binary with absolute paths (should not be committed). |
| functions/simple-email/node_modules_bad/.bin/ts-jest | Adds local binary with absolute paths (should not be committed). |
| functions/simple-email/node_modules_bad/.bin/rimraf | Adds local binary with absolute paths (should not be committed). |
| functions/simple-email/node_modules_bad/.bin/jest | Adds local binary with absolute paths (should not be committed). |
| functions/simple-email/node_modules_bad/.bin/browserslist | Adds local binary with absolute paths (should not be committed). |
| functions/simple-email/tests/index.test.ts | Adds K8s integration test for simple-email. |
| functions/simple-bash/tsconfig.json | Adds TS config for simple-bash test harness. |
| functions/simple-bash/src/index.sh | Adds bash function body. |
| functions/simple-bash/package.json | Adds test harness package config for simple-bash. |
| functions/simple-bash/jest.config.js | Adds per-package Jest config for simple-bash. |
| functions/simple-bash/tests/index.test.ts | Adds K8s integration test for simple-bash. |
| functions/simple-bash/Makefile | Adds make targets for running tests locally/in-k8s. |
| functions/simple-bash/Dockerfile.test | Adds test-image Dockerfile for simple-bash. |
| functions/simple-bash/Dockerfile | Adds minimal runtime image for bash example. |
| functions/send-email-link/tsconfig.json | Reworks TS config for send-email-link. |
| functions/send-email-link/src/index.ts | Refactors to default handler (runner-driven) + header extraction. |
| functions/send-email-link/package.json | Makes package publishable and adds test/build tooling + deps. |
| functions/send-email-link/jest.config.js | Adds per-package Jest config for send-email-link. |
| functions/send-email-link/tests/index.test.ts | Adds K8s integration test for send-email-link. |
| functions/rust-hello-world/src/main.rs | Adds Rust Hello World HTTP server. |
| functions/rust-hello-world/tests/index.test.ts | Adds K8s integration test for rust hello-world job. |
| functions/rust-hello-world/Dockerfile | Adds multi-stage Rust build Dockerfile. |
| functions/rust-hello-world/Cargo.toml | Adds Rust crate definition for rust-hello-world. |
| functions/runtime-script/tsconfig.json | Adds TS build config for runtime-script. |
| functions/runtime-script/src/index.ts | Adds runtime SQL execution function using pg Pool. |
| functions/runtime-script/package.json | Adds build/test scripts and deps for runtime-script. |
| functions/runtime-script/jest.config.js | Adds per-package Jest config for runtime-script. |
| functions/runtime-script/tests/index.test.ts | Adds K8s integration test for runtime-script. |
| functions/runtime-script/tests/app_jobs_schema.sql | Adds SQL schema fixture for runtime-script tests. |
| functions/runtime-script/Makefile | Adds make targets for runtime-script tests in k8s. |
| functions/pytorch-gpu/src/main.py | Adds Flask+Torch endpoint for GPU detection. |
| functions/pytorch-gpu/tests/index.test.ts | Adds K8s integration test for pytorch-gpu job. |
| functions/pytorch-gpu/Dockerfile | Adds Python Dockerfile for pytorch-gpu example. |
| functions/pgpm-dump/tsconfig.json | Adds TS config for pgpm-dump. |
| functions/pgpm-dump/src/index.ts | Adds pgpm dump wrapper function. |
| functions/pgpm-dump/package.json | Adds build/test scripts and deps for pgpm-dump. |
| functions/pgpm-dump/tests/run-k8s.sh | Adds helper script to run centralized test runner. |
| functions/pgpm-dump/tests/index.test.ts | Adds K8s integration test invoking pgpm dump within pod. |
| functions/pgpm-dump/Makefile | Adds make targets to run centralized test runner. |
| functions/opencode-headless/tsconfig.json | Adds TS config for opencode-headless. |
| functions/opencode-headless/src/index.ts | Adds headless opencode server spawn wrapper. |
| functions/opencode-headless/scripts/build-calvin.sh | Adds script to build opencode binary from calvincode repo. |
| functions/opencode-headless/package.json | Adds build/test scripts (incl. prebuild binary) and deps. |
| functions/opencode-headless/tests/run-k8s.sh | Adds helper script to run centralized test runner. |
| functions/opencode-headless/tests/index.test.ts | Adds K8s integration test for opencode-headless. |
| functions/llm-internal-calvin/tsconfig.json | Adds TS config for llm-internal-calvin. |
| functions/llm-internal-calvin/src/index.ts | Adds Calvin LLM API call function. |
| functions/llm-internal-calvin/package.json | Adds build/test scripts and deps for llm-internal-calvin. |
| functions/llm-internal-calvin/tests/run-k8s.sh | Adds helper script to run centralized test runner. |
| functions/llm-internal-calvin/tests/index.test.ts | Adds K8s integration test for llm-internal-calvin. |
| functions/llm-external/tsconfig.json | Adds TS config for llm-external. |
| functions/llm-external/src/index.ts | Adds external LLM provider dispatcher (OpenAI/test). |
| functions/llm-external/package.json | Adds build/test scripts and deps for llm-external. |
| functions/llm-external/tests/index.test.ts | Adds K8s integration test for llm-external. |
| functions/hello-world/tsconfig.json | Adds TS config for hello-world. |
| functions/hello-world/src/index.ts | Adds hello-world handler prototype. |
| functions/hello-world/package.json | Adds build/test scripts and deps for hello-world. |
| functions/hello-world/tests/run-k8s.sh | Adds helper script to run centralized test runner. |
| functions/hello-world/tests/index.test.ts | Adds K8s integration test for hello-world. |
| functions/hello-world/Makefile | Adds make targets for hello-world tests (incl. k8s). |
| functions/github-repo-creator/tsconfig.json | Adds TS config for github-repo-creator. |
| functions/github-repo-creator/src/index.ts | Adds function to create GitHub repo and pgpm dump. |
| functions/github-repo-creator/package.json | Adds build/test scripts and deps for github-repo-creator. |
| functions/github-repo-creator/tests/index.test.ts | Adds K8s integration test for github-repo-creator. |
| functions/crypto-login/tsconfig.json | Adds TS config for crypto-login. |
| functions/crypto-login/src/index.ts | Adds multi-chain signature verification handler. |
| functions/crypto-login/package.json | Adds build/test scripts and deps for crypto-login. |
| functions/crypto-login/tests/index.test.ts | Adds K8s integration test (startup) for crypto-login. |
| functions/_runtimes/rust/Dockerfile | Adds generic Rust runtime Dockerfile template. |
| functions/_runtimes/python/Dockerfile | Adds placeholder python runtime Dockerfile. |
| functions/_runtimes/node/runner.js | Adds runtime server shim that loads a function handler and serves it. |
| functions/_runtimes/node/Dockerfile.test | Adds shared test runner image Dockerfile for K8s-based tests. |
| functions/_runtimes/node/Dockerfile | Adds production node runtime Dockerfile for function packaging. |
| functions/_runtimes/agentic/Dockerfile.agentic | Adds large “agentic” runtime Dockerfile for local-model workflows. |
| Makefile | Expands root make targets for build/test + K8s test runner operations. |
| .gitignore | Ignores opencode build output and binary directory. |
| .github/workflows/test-k8s-deployment.yaml | Adds matrix strategy + installs node/pnpm + runs K8s test runner per function. |
| .dockerignore | Adds root dockerignore to reduce build context / avoid secrets. |
Files not reviewed (1)
- functions/simple-bash/pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (19)
scripts/test-runner.ts:1
- Kubernetes
env[].valuemust be a string; several entries are assigned fromprocess.env.*which can beundefined. This can cause the Job creation call to fail validation. Filter out undefined entries (or provide explicit default strings) before sending the manifest to the API.
scripts/test-runner.ts:1 - Setting
NODE_TLS_REJECT_UNAUTHORIZED=0disables TLS certificate verification for all HTTPS calls in the test container, which is a high-risk default (it can hide real TLS issues and enables MITM in less controlled environments). Prefer removing this entirely, or gating it behind an explicit local-only flag (e.g.,ALLOW_INSECURE_TLS=true) and keeping the secure default.
scripts/test-runner.ts:1 - Running Jest with
-uupdates snapshots, which is not appropriate for CI and makes test results non-deterministic (it may “fix” failures by rewriting expected outputs). Consider removing-u(and optionally use--ci) so the runner strictly validates current snapshots.
k8s/scripts/scaffold-function.sh:1 TARGET_FILEis used but never defined in this script, so the existence check andcp/sedsteps will fail (or operate on an empty path). DefineTARGET_FILEexplicitly (e.g., the destination manifest path underk8s/base/functions/${FUNCTION_NAME}.yaml) before it’s referenced.
k8s/scripts/scaffold-function.sh:1TARGET_FILEis used but never defined in this script, so the existence check andcp/sedsteps will fail (or operate on an empty path). DefineTARGET_FILEexplicitly (e.g., the destination manifest path underk8s/base/functions/${FUNCTION_NAME}.yaml) before it’s referenced.
functions/simple-email/node_modules_bad/.bin/tsc:1functions/simple-email/node_modules_bad/**appears to be committed localnode_modules/pnpm artifacts, including absolute filesystem paths. This is both sensitive (leaks developer machine paths) and will break portability. Remove this directory from the repo and add an ignore rule to prevent reintroduction (e.g.,functions/**/node_modules*, and specificallyfunctions/simple-email/node_modules_bad/).
package.json:1jest@30paired withts-jest@29is very likely incompatible (ts-jest major versions typically track Jest majors). This can cause runtime failures in test transforms and confusing CI breakage. Align versions (either upgradets-jestto a version compatible with Jest 30, or keep Jest on the matching major).
package.json:1jest@30paired withts-jest@29is very likely incompatible (ts-jest major versions typically track Jest majors). This can cause runtime failures in test transforms and confusing CI breakage. Align versions (either upgradets-jestto a version compatible with Jest 30, or keep Jest on the matching major).
functions/simple-email/src/index.ts:1getRequiredFieldthrows on missing fields, but the refactor removed the surrounding Expresstry/catch/next(err)flow and there’s no localtry/catcharound these calls now. That means missingto/subjectwill bubble to the runner and likely become a 500 rather than a proper “bad request” response. Wrap the payload processing in atry/catchand return a structured{ error: ... }(or changegetRequiredFieldto not throw in this runtime-invoked handler style).
functions/simple-email/tests/index.test.ts:1- The generated database name string includes a trailing space, which can create an invalid/unexpected database name and cause connection or creation failures. Remove the extra space so the database name is stable and valid. (Same pattern appears in other tests like
send-email-link.)
k8s/scripts/setup/01-install-operators.sh:1 - The function spends up to
$timeoutseconds waiting for “any pod to exist” and then can spend another full$timeoutinsidekubectl wait, so overall wait time can exceed the intended timeout. Consider subtractingelapsedfrom the second wait and using the remaining time (or using a single loop that enforces a hard upper bound).
k8s/scripts/setup/01-install-operators.sh:1 - The function spends up to
$timeoutseconds waiting for “any pod to exist” and then can spend another full$timeoutinsidekubectl wait, so overall wait time can exceed the intended timeout. Consider subtractingelapsedfrom the second wait and using the remaining time (or using a single loop that enforces a hard upper bound).
k8s/scripts/setup/01-install-operators.sh:1 - The function spends up to
$timeoutseconds waiting for “any pod to exist” and then can spend another full$timeoutinsidekubectl wait, so overall wait time can exceed the intended timeout. Consider subtractingelapsedfrom the second wait and using the remaining time (or using a single loop that enforces a hard upper bound).
functions/simple-bash/Makefile:1 - The recipe contains
pnpm build:test-k8s:(note the trailing colon), which is not a valid shell command and will cause thetest-k8starget to fail immediately. Remove the colon and use a real pnpm script invocation (or delete this line if it’s accidental).
functions/runtime-script/src/index.ts:1 - This function executes an arbitrary SQL string from the request payload directly against Postgres. That is a critical escalation vector if the function can be invoked by non-admin callers (data exfiltration/destruction). If this is meant to be an admin-only tool, add explicit authorization checks (e.g., require a shared secret header/token), and consider restricting the allowed operations (e.g., allowlist of commands, or parameterized execution only).
functions/runtime-script/src/index.ts:1 - This function executes an arbitrary SQL string from the request payload directly against Postgres. That is a critical escalation vector if the function can be invoked by non-admin callers (data exfiltration/destruction). If this is meant to be an admin-only tool, add explicit authorization checks (e.g., require a shared secret header/token), and consider restricting the allowed operations (e.g., allowlist of commands, or parameterized execution only).
functions/send-email-link/src/index.ts:1 - This handler requires
GRAPHQL_URLbut still usescontext.clientfor the primaryclientwhile constructing onlymetafrom env. That’s inconsistent and makes behavior depend on the runner’sGRAPHQL_ENDPOINTdefault rather than the function’s own config. Prefer constructing the primaryclientfromgraphqlUrl(using the samecreateGraphQLClienthelper) so the function’s explicit env config actually controls its GraphQL connectivity.
functions/send-email-link/src/index.ts:1 - This handler requires
GRAPHQL_URLbut still usescontext.clientfor the primaryclientwhile constructing onlymetafrom env. That’s inconsistent and makes behavior depend on the runner’sGRAPHQL_ENDPOINTdefault rather than the function’s own config. Prefer constructing the primaryclientfromgraphqlUrl(using the samecreateGraphQLClienthelper) so the function’s explicit env config actually controls its GraphQL connectivity.
functions/send-email-link/src/index.ts:1 - This handler requires
GRAPHQL_URLbut still usescontext.clientfor the primaryclientwhile constructing onlymetafrom env. That’s inconsistent and makes behavior depend on the runner’sGRAPHQL_ENDPOINTdefault rather than the function’s own config. Prefer constructing the primaryclientfromgraphqlUrl(using the samecreateGraphQLClienthelper) so the function’s explicit env config actually controls its GraphQL connectivity.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const express = resolveDep('express'); | ||
| const bodyParser = resolveDep('body-parser'); | ||
| const { GraphQLClient } = resolveDep('graphql-request'); |
There was a problem hiding this comment.
runner.js unconditionally resolves express and body-parser from the function’s node_modules and exits if they aren’t installed. Many of the function packages in this PR don’t declare express/body-parser, so the runtime can fail before it ever attempts to use @constructive-io/knative-job-fn. A concrete fix is to only resolve express/body-parser inside the fallback path (when @constructive-io/knative-job-fn is not available), or alternatively ensure the runtime image (or every function package) includes these deps consistently.
| - pytorch-gpu | ||
| - runtime-script | ||
| - rust-hello-world |
There was a problem hiding this comment.
The CI matrix includes functions whose tests reference images that are set to imagePullPolicy: "Never" (e.g., pytorch-gpu, rust-hello-world). In GitHub Actions, these images won’t exist in the kind node unless you explicitly build and kind load them during the workflow, so those matrix jobs should fail deterministically. Either (1) build/load those specific images in CI before running tests, or (2) change the tests/manifests to use pullable images (and set IfNotPresent / Always as appropriate).
| - pytorch-gpu | |
| - runtime-script | |
| - rust-hello-world | |
| - runtime-script |
| pnpm -r lint | ||
|
|
||
| test: | ||
| pnpm -r test |
There was a problem hiding this comment.
pnpm -r test can run workspace tests concurrently (depending on pnpm settings), but many integration tests in this PR start kubectl proxy on fixed ports (commonly 8001). This creates a deterministic port-collision race when tests run in parallel. Solutions: run tests serially (e.g., set workspace concurrency to 1 for this target) and/or update the tests to choose an available port dynamically per test run.
| pnpm -r test | |
| pnpm -r --workspace-concurrency=1 test |
2c6fe8f to
22aa874
Compare
|
Heads-up: repository history was rewritten on 2026-05-12 to scrub leaked secrets (Postgres/pgAdmin default passwords, an AWS access key ID, generated This PR shows "DIRTY" / merge-conflict status because git fetch --all --prune
git checkout <this-branch>
git reset --hard origin/<this-branch> # your local branch tip moved too — pick up the rewritten version
git rebase origin/main # rebase onto rewritten main
# resolve conflicts (usually trivial — mostly secret-placeholder + the 4 deleted interweb-*.yaml files)
git push --force-with-leaseOr merge instead of rebase if the branch is shared with others: git merge origin/main
git pushNotes:
|
Summary
Archived commits from after the initial repo setup (
ff08ccc). These commits added various functions, CI/CD, testing infrastructure, and other changes that need further work before merging.Cherry-pick from this branch as needed.
Commits preserved