Reusable CI/CD workflows for TetraScience repositories.
Reusable workflow that runs actionlint to lint all GitHub Actions workflow files in the repo. Catches syntax errors, type mismatches, deprecated features, and security issues in workflow YAML.
jobs:
actionlint:
uses: tetrascience/ts-ci-cd-lib/.github/workflows/actionlint.yml@main| Input | Description | Required | Default |
|---|---|---|---|
version |
actionlint version to install | No | "latest" |
Reusable workflow that runs knip to detect unused dependencies, exports, types, and files. Handles checkout, Node setup, Corepack, registry auth, install, and caching — callers just wire it up.
jobs:
knip:
uses: tetrascience/ts-ci-cd-lib/.github/workflows/knip.yml@main
secrets:
AUTH_TOKEN: ${{ secrets.JFROG_ARTIFACTORY_READ_NPM_AUTH }}
REGISTRY: ${{ secrets.JFROG_ARTIFACTORY_NPM_VIRTUAL_URL }} knip:
uses: tetrascience/ts-ci-cd-lib/.github/workflows/knip.yml@main
with:
working_directory: packages/my-lib
args: "--include dependencies"
secrets:
AUTH_TOKEN: ${{ secrets.JFROG_ARTIFACTORY_READ_NPM_AUTH }}
REGISTRY: ${{ secrets.JFROG_ARTIFACTORY_NPM_VIRTUAL_URL }}| Input | Description | Required | Default |
|---|---|---|---|
node_version |
Node.js version | No | "20" |
working_directory |
Directory to run knip in | No | "." |
args |
Additional arguments passed to knip | No | "" |
| Secret | Description | Required |
|---|---|---|
AUTH_TOKEN |
JFrog npm auth token (for installing private deps) | No |
REGISTRY |
JFrog virtual registry URL | No |
Same tool, no workflow needed — add directly to .husky/pre-commit:
npx knip --include dependenciesFor most repos, knip works out of the box. If you need to ignore specific patterns, create knip.json:
{
"ignore": ["src/generated/**"],
"ignoreDependencies": ["@types/*"]
}Reusable workflow for publishing npm packages to JFrog Artifactory or the public npm registry.
name: Publish
on:
push:
tags:
- "v*"
jobs:
publish:
uses: tetrascience/ts-ci-cd-lib/.github/workflows/publish-npm-package.yml@main
with:
node_version: "20"
secrets:
AUTH_TOKEN: ${{ secrets.JFROG_AUTH_TOKEN }}
REGISTRY: ${{ secrets.JFROG_NPM_REGISTRY }}
PUBLISH_REGISTRY: ${{ secrets.JFROG_NPM_PUBLISH_REGISTRY }}| Input | Description | Required | Default |
|---|---|---|---|
node_version |
Node.js version | No | "20" |
working_directory |
Directory containing the package to publish | No | "." |
prerelease_tag |
Prerelease tag for version suffix and npm dist-tag (e.g., alpha, beta). Leave empty for non-prerelease versions. | No | "" |
run_tests |
Whether to run tests before publishing | No | true |
publish_to_public_npm |
Set to true to confirm publishing to public npm registry | No | false |
pre_install_command |
Shell command to run after checkout + auth but before install. Runs at repo root (not working_directory) in the same job environment, including any provided secrets/tokens. Use for codegen that produces the working_directory contents, and avoid echoing or logging sensitive values. |
No | "" |
| Secret | Description | Required |
|---|---|---|
AUTH_TOKEN |
Authentication token for JFrog Artifactory | Yes |
REGISTRY |
JFrog Artifactory npm registry URL (for installing dependencies) | Yes |
PUBLISH_REGISTRY |
Registry URL for publishing the package | Yes |
NPM_TOKEN |
npm token (required when publishing to public npm registry) | No |
To publish to the public npm registry (https://registry.npmjs.org):
- Set
publish_to_public_npm: truein the workflow inputs - Provide the
NPM_TOKENsecret - Set
PUBLISH_REGISTRYtohttps://registry.npmjs.org
The workflow will automatically update the package scope from @tetrascience to @tetrascience-npm when publishing to the public registry.
Reusable workflow for checking broken links in markdown files using lychee. The calling repository provides its own lychee.toml configuration file in the repo root.
name: Link Check
on:
push:
branches: [main]
paths: ["**/*.md", "lychee.toml", ".lycheeignore"]
pull_request:
paths: ["**/*.md", "lychee.toml", ".lycheeignore"]
schedule:
- cron: "0 8 * * 1"
workflow_dispatch:
permissions:
contents: read
jobs:
check-links:
uses: tetrascience/ts-ci-cd-lib/.github/workflows/check-links.yml@main| Input | Description | Required | Default |
|---|---|---|---|
lychee_args |
Arguments passed to lychee. The calling repo's lychee.toml handles most configuration. |
No | "--cache --max-cache-age 1d ." |
No secrets required. The workflow uses the automatically available GITHUB_TOKEN for authenticating with the GitHub API (to avoid rate limits when checking GitHub links).
Create a lychee.toml file in your repository root:
max_concurrency = 4
max_retries = 3
timeout = 20
accept = [200, 204, 301, 429]
exclude = [
"^http://localhost",
"^http://127\\.0\\.0\\.1",
"^https?://example\\.com",
]Deploys a service to a predev environment, runs E2E tests via CodeBuild, and streams results back to the PR.
name: E2E Tests
on:
pull_request:
types: [opened, synchronize, reopened, labeled]
push:
branches: [development]
permissions:
id-token: write
contents: read
jobs:
e2e:
uses: tetrascience/ts-ci-cd-lib/.github/workflows/e2e-codebuild.yml@main
with:
environment: predev5
deploy_paths: 'src/** migrations/** package.json yarn.lock Dockerfile'
buildspec: buildspec.e2e.yml
secrets:
JFROG_ARTIFACTORY_NPM_VIRTUAL_URL: ${{ secrets.JFROG_ARTIFACTORY_NPM_VIRTUAL_URL }}
JFROG_ARTIFACTORY_READ_NPM_AUTH: ${{ secrets.JFROG_ARTIFACTORY_READ_NPM_AUTH }}
GITHUB_PAT: ${{ secrets.ARTIFACT_BUILD_GITHUB_TS_DEVOPS_PAT }}Non-secret test configuration (org slugs, app IDs, subdomain bases, etc.) should live in the service repo as a static config file (e.g. test/e2e/environments.ts) keyed by environment name. The workflow passes E2E_ENVIRONMENT so tests can select the right config at runtime. Only actual secrets (auth tokens) belong in SSM.
Each service provides its own buildspec.e2e.yml. The workflow passes the following as CodeBuild environment variables:
| Variable | Description |
|---|---|
E2E_ENVIRONMENT |
Target environment name (e.g. predev3, dev) |
JFROG_ARTIFACTORY_URL |
JFrog npm registry URL |
JFROG_ARTIFACTORY_AUTH |
JFrog npm credentials |
Authentication is handled by each service's test setup (e.g. a globalSetup that reads the TDP admin password from SSM and logs in). The CodeBuild IAM role has access to read SSM parameters under /tetrascience/{environment}/platform/ADMIN_PASSWORD.
Example buildspec:
version: 0.2
phases:
install:
runtime-versions:
nodejs: 20
commands:
- npm install -g corepack
- corepack enable
- YARN_VERSION=$(node -p "require('./package.json').packageManager.split('@')[1]")
- corepack prepare "yarn@$YARN_VERSION" --activate
- |
if [ -n "$JFROG_ARTIFACTORY_URL" ]; then
yarn config set npmRegistryServer "$JFROG_ARTIFACTORY_URL"
yarn config set npmAuthIdent "$JFROG_ARTIFACTORY_AUTH"
yarn config set npmAlwaysAuth true
fi
- yarn install --immutable
build:
commands:
- yarn test:e2e| Input | Required | Default | Description |
|---|---|---|---|
environment |
Yes | Target environment (e.g. predev5, dev) |
|
deploy_paths |
Yes | Globs that trigger deploy. Empty = skip deploy. | |
buildspec |
Yes | Path to buildspec in the caller repo | |
deploy_workflow |
No | ci.yml |
Workflow waited on after pushing to env branch |
image_override |
No | Override CodeBuild image | |
compute_type_override |
No | Override CodeBuild compute (e.g. BUILD_GENERAL1_MEDIUM) |
|
timeout_minutes |
No | 25 |
Max minutes for the E2E job |
| Secret | Description |
|---|---|
JFROG_ARTIFACTORY_NPM_VIRTUAL_URL |
JFrog npm registry URL |
JFROG_ARTIFACTORY_READ_NPM_AUTH |
JFrog npm credentials |
GITHUB_PAT |
PAT for cross-repo access + deploy push |
- check-changes — compares changed files against
deploy_paths. Skipped ifdeploy_pathsis empty. - deploy — pushes to the env branch, waits for the deploy workflow to complete. Skipped if no service code changed.
- e2e — uploads source to S3, triggers CodeBuild, streams logs, writes job summary.
The shared CodeBuild project (tdp-e2e) must be deployed per environment via EnableE2E=true in the TDP service stack. See ts-cloudformation-service/infrastructure/tdp-e2e.yaml.