An opinionated deployment orchestrator that lets you describe a “component” in a single YAML file and deploy it with different underlying provider technologies (AWS CDK, Serverless Framework v1, hard‑coded outputs, or a Dynamic Environment provisioning lambda) using one unified CLI: deployer.
Status: Experimental / Early Internal Use. Expect breaking changes.
- Deployer
The Deployer abstracts over multiple infrastructure/application deployment mechanisms. You provide a YAML “component template” that names the component, its target environment, provider selection & configuration, and arbitrary input properties. The CLI then:
- Parses the YAML (including JSON references via
json-refsif used in the future). - Instantiates the appropriate provider implementation.
- Runs the provider deployment.
- Collects any outputs returned by the provider and persists them to a centralized environment output service (
https://environments.daysmart.net/output).
- Unified CLI:
deployer deploy <component.yml>. - Multiple providers:
- AWS CDK (single stack synthesis & deployment).
- Serverless Framework v1 (writes ephemeral config & runs
sls deploy). - Hardcoded (inject static key/value outputs without actually deploying anything).
- Dynamic Environment provisioning (invokes a predefined Lambda, subscribes to CodeBuild logs until completion).
- Automatic output publishing per component/environment.
- Simple YAML schema; minimal required fields.
- Extensible provider model via a switch in
lib/deployer.ts.
| Concern | Minimum | Recommended |
|---|---|---|
| Node.js runtime | 18.x LTS | 22.x (current active release) |
| NPM | 8.x+ | 10.x+ |
| AWS Credentials | Standard CLI / env vars | AssumeRole with MFA (org policy) |
Why Node 22: Modern dependencies increasingly rely on stable node: specifiers, updated crypto APIs, and performance improvements only available in >=18; choosing 22 future‑proofs the tool and aligns with deprecation of older runtimes. Running under Node <16 can yield Cannot find module 'node:crypto' for packages expecting the newer resolution behavior.
If you see errors like:
Error: Cannot find module 'node:crypto'
Update your buildspec to use a newer runtime (e.g. runtime-versions: nodejs: 22). Also correct any YAML typos (e.g. upload-artificats should be upload-artifacts). See example below.
Example buildspec.yml (Node 22)
version: 0.2
env:
variables:
COMPONENT_FILE: components/orders.yaml
phases:
install:
runtime-versions:
nodejs: 22
commands:
- npm install -g git+https://github.com/DaySmart/deployer.git#master
pre_build:
commands:
- echo "Using Node $(node -v)" && deployer deploy $COMPONENT_FILE
build:
commands:
- echo "Build phase complete" # (Optional – deployment already done in pre_build)
artifacts:
files:
- '**/*'Place deploy in pre_build if deployment is the goal; use build for subsequent packaging or tests.
Below is a consolidated schema (informal). Fields may vary slightly per provider.
name: orders-api # Logical component name
env: dev # Target environment/stage name (used in stack naming, outputs key prefix)
provider:
name: serverless-framework # One of: serverless-framework | hardcoded | dsicollection-dynamic-environment | cdk
# (For provider 'cdk' only) config:
# constructPath: infra/orders-stack.js # Path (relative to repo root) to module exporting one or more CDK constructs
# constructName: OrdersStack # Optional; if omitted first exported symbol is used
# env: # Standard CDK Environment
# account: '123456789012'
# region: 'us-east-1'
region: us-east-1 # (Serverless only) AWS region override; optional
input: # Arbitrary provider-specific properties
SOME_VAR: some-value # Serverless: becomes .deployer/serverless.config.yaml
# Hardcoded provider: each key/value becomes an output
# Dynamic environment provider example:
# branch: feature/my-branch
# baseEnvironment: dev
# includeApps:
# - app1
# excludeApps:
# - legacyAppAt least: name, env, and provider.name (plus provider.config for cdk).
- The file is parsed by
parseYaml(lib/utils/parseYaml.ts) usingjs-yaml. - JSON references (
$ref) could be supported sincejson-refsis included (not currently invoked explicitly).
| Name | File | Purpose | Outputs Behavior |
|---|---|---|---|
serverless-framework |
lib/providers/serverless.ts |
Executes a Serverless Framework v1 deployment using runtime-built args. | Extracts CloudFormation stack outputs and publishes them. |
hardcoded |
lib/providers/hardcoded.ts |
Returns each input key/value directly as an output (no cloud action). |
Publishes every pair exactly. |
dsicollection-dynamic-environment |
lib/providers/dsicollectionDynamicEnvironment.ts |
Invokes a provisioning Lambda, tails CodeBuild logs, returns no outputs. | Publishes nothing (empty array). |
cdk |
lib/providers/cdk.ts |
Synths & deploys a single CDK stack from a construct. | Converts deploy result outputs to key/value pairs. |
Implement a class with an async deploy() returning { outputs: Array<{key,value}> }. Then extend the switch(providerType) in lib/deployer.ts.
Basic syntax:
deployer deploy ./path/to/component.yaml
deployer destroy ./path/to/component.yaml # (Not implemented yet – will log error)The entrypoint (bin/index.ts) parses positional args. Ensure your YAML path is the fourth element after Node + script – normal usage with the global binary handles this automatically.
npm install -g deployernpm install
npm run build
node ./bin/index.js deploy ./examples/orders.yaml- Install globally or clone the repo and build.
- Create a component YAML (see examples above).
- Run
deployer deploy your-component.yaml. - Inspect logs for provider‑specific output.
- Query the environment output service to see persisted outputs (internal tooling).
Providers return outputs as an array: [{ key: string, value: string }]. After deployment, lib/deployer.ts iterates outputs and calls environmentService.putComponentOutput(env, name, key, value).
Component output names are namespaced as: <env>.<component> on the remote service.
Defined in lib/service/environmentService.ts. It POSTs JSON:
{
"componentName": "dev.orders-api",
"outputName": "RestApiUrl",
"value": "https://abc123.execute-api.us-east-1.amazonaws.com/dev"
}Endpoint: https://environments.daysmart.net/output.
You must have network access and any required auth (currently unauthenticated request code – ensure this is safe or add authentication later).
You can instantiate and run a deployment directly in Node:
const Deployer = require("deployer/lib/deployer");
const deployer = new Deployer("deploy", "./components/orders.yaml");
await deployer.run();- Constructor args:
(command: string, filePath: string). command: currentlydeployordestroy(destroy not yet implemented).run(): dispatches todeploy()or logs an error.- Errors: Throws if provider name unsupported or underlying provider fails.
component.yaml ──▶ parseYaml ──▶ Deployer ──▶ Provider (strategy) ──▶ Deploy
│
└──▶ outputs array ──▶ environmentService POST
Key modules:
lib/deployer.ts: Orchestrator & provider factory.lib/providers/*: Provider implementations.lib/utils/parseYaml.ts: YAML loader.lib/service/environmentService.ts: Output publishing.
Scripts (package.json):
npm run build– compile TypeScript.npm run watch– incremental compilation.npm test– placeholder (Jest not yet added as a dependency; future enhancement).
Dependencies of note:
@aws-cdk/core,aws-cdkfor CDK deployments.serverlessfor Serverless Framework integration.aws-sdkfor Lambda, CloudWatch Logs, CodeBuild interactions.js-yamlfor YAML parsing.json-refsincluded (future: YAML$refexpansion).minimistfor CLI arg parsing.
npm install
npm run build- CDK: ensure
constructPathpoints at a built JS file (aftertsc). - Serverless: inputs are written to
.deployer/serverless.config.yaml; merge logic could be extended. - Dynamic Environment: requires the provisioning Lambda ARN hardcoded in
dsicollectionDynamicEnvironment.ts. Update if ARN changes. - Hardcoded: ideal for wiring outputs without deployment (e.g., referencing pre-existing resources).
| Issue | Cause | Mitigation |
|---|---|---|
The provider X is not implemented! |
Misspelled provider name in YAML | Use one of the supported names. |
| No outputs published | Provider returned empty array (e.g., dynamic environment) | Confirm provider should emit outputs. |
| CDK construct not found | constructName missing or mismatch |
Set provider.config.constructName explicitly. |
| Serverless deploy picks wrong stage | env value incorrect |
Verify env in YAML; maps to -s flag. |
| AWS auth errors | Missing credentials | Export AWS_PROFILE or env vars before running. |
| Hanging dynamic environment | Long CodeBuild duration | Watch logs; process polls every 60s. |
| Jest tests fail to run | Jest not installed | Add jest & config or remove script. |
- Implement
destroylogic for all providers. - Add Jest + sample tests.
- Support
$refexpansion for large templated YAMLs. - Add authentication / headers for environment output service.
- Structured logging & log levels.
- TypeScript types for component schema and provider responses.
- Fork repository.
- Create feature branch:
git checkout -b feature/awesome. - Implement changes + add/update docs.
- Run build & (future) tests.
- Open PR describing provider or feature additions.
Please maintain backward compatibility when possible and document breaking changes clearly.
Apache License 2.0. See LICENSE file.
Internal tooling created by DaySmart. Use responsibly; review code before production usage.
If you have questions or suggestions, open an issue at the repository’s GitHub issues page.