API


express-rest-api

A REST resource API built on the Express web framework and deployed with Gantry.

View on GitHub

Added in 3.8.0

Changelog
  • 9.0.0: Point Docker base images to AWS ECR Public and remove constant --platform arguments (#1684)

  • 8.2.1: Remove JSON schema definitions from Buildkite pipeline files (#1624)

    This reverts #1611 due to incompatibility with pipeline signing.

  • 8.2.1: docker-compose v5.3.0 (#1620)

  • 8.2.0: Add JSON schema definitions to Buildkite pipeline files (#1611)

  • 8.1.0: Add extension recommendations to .vscode/extensions.json (#1556)

  • 8.1.0: Make all configuration values explicit (#1560)

    Previously, src/config.ts included optional configuration values and inheritance between environments in the spirit of DRY. While the templated file was wired up in a “safe” way—the production environment never inherited from other environments and explicitly specified all its configuration values—its pattern was misappropriated elsewhere and led to local configuration values affecting production environments.

    Instead, we now list all configuration values explicitly against each environment.

  • 8.1.0: Remove deprecated docker-compose.yml version (#1570)

    Docker has ignored this for a while, and now generates a warning on every build: https://github.com/compose-spec/compose-spec/blob/master/04-version-and-name.md

  • 8.1.0: Clean up templated environment variables (#1562)

    • AWS_NODEJS_CONNECTION_REUSE_ENABLED is no longer required with AWS SDK V3.
    • The env boilerplate in Gantry values files was largely unnecessary and confusing.

      Our templates prefer to declare configuration values directly in src/config.ts.

  • 8.0.1: Install specific pnpm version via Corepack (#1515)

    Previously, our Dockerfiles ran corepack enable pnpm without installing a specific version. This does not guarantee installation of the pnpm version specified in package.json, which could cause a subsequent pnpm install --offline to run Corepack online or otherwise hang on stdin:

    FROM --platform=arm64 node:20-alpine
    
    RUN corepack enable pnpm
    
    {
      "packageManager": "pnpm@8.15.4",
      "engines": {
        "node": ">=20"
      }
    }
    
    Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-8.15.4.tgz.
    
    Do you want to continue? [Y/n]
    

    To avoid this issue, modify (1) Buildkite pipelines to cache on the packageManager property in package.json, and (2) Dockerfiles to mount package.json and run corepack install:

    - seek-oss/docker-ecr-cache#v2.1.0:
    + seek-oss/docker-ecr-cache#v2.2.0:
        cache-on:
         - .npmrc
    +    - package.json#.packageManager
         - pnpm-lock.yaml
    
    FROM --platform=arm64 node:20-alpine
    
    - RUN corepack enable pnpm
    + RUN --mount=type=bind,source=package.json,target=package.json \
    + corepack enable pnpm && corepack install
    
  • 8.0.1: Fix lint failure (#1514)

    This resolves the following failure on a newly-initialised project due to a regression in the @types/express dependency chain:

    error TS2688: Cannot find type definition file for 'mime'.
      The file is in the program because:
        Entry point for implicit type library 'mime'
    

    A temporary workaround is to install mime as a dev dependency.

  • 8.0.0: Remove BUILDPLATFORM from Dockerfiles (#1350)

    Previously, the built-in templates made use of BUILDPLATFORM and a fallback value:

    FROM --platform=${BUILDPLATFORM:-arm64} gcr.io/distroless/nodejs20-debian11
    
    1. Choose the platform of the host machine running the Docker build. An AWS Graviton Buildkite agent or Apple Silicon laptop will build under arm64, while an Intel laptop will build under amd64.
    2. Fall back to arm64 if the build platform is not available. This maintains compatibility with toolchains like Gantry that lack support for the BUILDPLATFORM argument.

    This approach allowed you to quickly build images and run containers in a local environment without emulation. For example, you could docker build an arm64 image on an Apple Silicon laptop for local troubleshooting, while your CI/CD solution employed amd64 hardware across its build and runtime environments. The catch is that your local arm64 image may exhibit different behaviour, and is unsuitable for use in your amd64 runtime environment without cross-compilation.

    The built-in templates now hardcode --platform as we have largely converged on arm64 across local, build and runtime environments:

    FROM --platform=arm64 gcr.io/distroless/nodejs20-debian11
    

    This approach is more explicit and predictable, reducing surprises when working across different environments and toolchains. Building an image on a different platform will be slower and rely on emulation.

  • 8.0.0: Remove account-level tags from resources (#1494)

    This partially reverts #1459 and #1461 to avoid unnecessary duplication of account-level tags in our templates.

  • 7.5.1: Comply with latest AWS tagging guidance (#1459)

    This includes an upgrade to Gantry v3.

  • 7.4.0: Set readonlyRootFilesystem as a security best practice (#1394)

  • 7.4.0: Use propagate-environment for Docker Compose Buildkite plugin (#1392)

    This simplifies the Docker Compose environment variable configuration required for Buildkite and GitHub integrations.

    In your docker-compose.yml:

    services:
      app:
    -   environment:
    -     # Enable Buildkite + GitHub integrations.
    -     - BUILDKITE
    -     - BUILDKITE_AGENT_ACCESS_TOKEN
    -     - BUILDKITE_BRANCH
    -     - BUILDKITE_BUILD_NUMBER
    -     - BUILDKITE_JOB_ID
    -     - BUILDKITE_PIPELINE_DEFAULT_BRANCH
    -     - BUILDKITE_STEP_ID
    -     - GITHUB_API_TOKEN
        image: ${BUILDKITE_PLUGIN_DOCKER_IMAGE:-''}
        init: true
        volumes:
          - ./:/workdir
          # Mount agent for Buildkite annotations.
          - /usr/bin/buildkite-agent:/usr/bin/buildkite-agent
          # Mount cached dependencies.
          - /workdir/node_modules
    

    In your .buildkite/pipeline.yml:

    steps:
      - commands:
          - pnpm lint
          - pnpm test
        env:
          # At SEEK, this instructs the build agent to populate the GITHUB_API_TOKEN environment variable for this step.
          GET_GITHUB_TOKEN: 'please'
        plugins:
          - *aws-sm
          - *private-npm
          - *docker-ecr-cache
          - docker-compose#v4.16.0:
    +         environment:
    +           - GITHUB_API_TOKEN
    +         propagate-environment: true
              run: app
    
  • 7.4.0: Disable dev CloudWatch dashboards for cost savings (#1395)

  • 7.3.1: Update to Node 20 (#1317)

    Consider upgrading the Node.js version for your project across:

    • .nvmrc
    • package.json#/engines/node
    • serverless.yml
    • @types/node package version
    • CI/CD configuration (.buildkite/pipeline.yml, Dockerfile, etc.)

    If you are updating your AWS Lambda runtime to nodejs20.x, consider reading the release announcement as there are some breaking changes with this upgrade.

  • 7.3.0: seek-oss/docker-ecr-cache 2.1 (#1266)

    This update brings a new skip-pull-from-cache option which is useful on Warm/Build Cache steps.

    At SEEK, our build agents no longer persist their Docker build cache from previous steps. This option allows a preparatory step to proceed on a cache hit without pulling the image from ECR, which can save on average ~1 minute per build for a 2GB Docker image.

  • 7.3.0: Mount npm build secret to a separate directory (#1278)

    Our templated Buildkite pipelines currently retrieve a temporary .npmrc. This file contains an npm read token that allows us to fetch private @seek-scoped packages.

    New projects now write this file to /tmp/ on the Buildkite agent and mount it as a secret to /root/ in Docker. This separation allows you to commit a non-sensitive .npmrc to your GitHub repository while avoiding accidental exposure of the npm read token. This is especially important if you are migrating a project to pnpm, which houses some of its configuration options in .npmrc.

    Existing projects are generally advised to wait until we’ve paved a cleaner migration path for pnpm.

  • 7.1.0: Switch distroless image from nodejs:18 to nodejs18-debian11 (#1224)

  • 7.0.0: Require Node.js 18.12+ (#1206)

  • 6.2.0: Include manifest files in CODEOWNERS (#1162)

    Our templates previously excluded package.json and yarn.lock from CODEOWNERS. This was intended to support advanced workflows such as auto-merging PRs and augmenting GitHub push notifications with custom tooling. However, we are reverting this configuration as it is more common for SEEKers to prefer a simpler CODEOWNERS-based workflow.

    This will not affect existing projects. If you create a new project and wish to restore the previous behaviour, you can manually extend .github/CODEOWNERS:

    * @<%- ownerName %>
    
    + # Configured by Renovate
    + package.json
    + yarn.lock
    
  • 6.2.0: Remove Gantry ignoreAlarms override (#1160)

    This issue has been resolved in Gantry v2.2.0; see its release notes for more information.

    deployment:
    - # SEEK-Jobs/gantry#488
    - ignoreAlarms: true
    
  • 5.1.0: Prompt for target platform (amd64 or arm64) (#1041)

  • 5.1.0: Replace '' with a custom environment Gantry value. (#1065)

  • 5.0.0: Bump greeter and API templates to Node.js 18 (#1011)

    Node.js 18 is now in active LTS. The Lambda templates are stuck on Node.js 16 until the new AWS Lambda runtime is released.

  • 5.0.0: Support AMD64 Docker builds via BUILDPLATFORM (#1021)

    See the Docker documentation for more information. Note that this does not allow you to build on AMD64 hardware then deploy to ARM64 hardware and vice versa. It is provided for convenience if you need to revert to an AMD64 workflow and/or build and run an image on local AMD64 hardware.

  • 4.3.1: seek-jobs/gantry v2.0.0 (#935)

  • 4.3.1: Fix README link to ARM64 guide (#913)

  • 4.3.1: Fix Gantry documentation links (#931)

  • 4.3.0: seek-jobs/gantry v1.8.1 (#887)

  • 4.3.0: Remove .me files (#902)

    SEEK is moving away from Codex to off-the-shelf software powered by Backstage catalog-info.yaml files.

    At the moment we’re only asking teams to document their systems, which typically span across multiple repositories. We may add catalog-info.yaml files back to the templates if there’s a need for teams to document their components at a repository level.

  • 4.3.0: Use ARM64 architecture (#873)

    We now recommend building and running projects on ARM64 hardware for greater cost efficiency. This requires a Graviton-based Buildkite cluster; see our ARM64 guide for more information.

  • 4.2.1: Time out Buildkite test steps after 10 minutes (#842)

    Successful testing and linting should complete within this window. This timeout prevents commands from hanging and indefinitely preoccupying your Buildkite agents.

    steps:
      - label: 🧪 Test & Lint
    +   timeout_in_minutes: 10
    
  • 4.2.0: Propagate Buildkite environment variables for lint autofixing (#800)

  • 4.2.0: Exclude DOM type definitions by default (#822)

    TypeScript will now raise compiler errors when DOM globals like document and window are referenced in new projects. This catches unsafe usage of Web APIs that will throw exceptions in a Node.js context.

    If you are developing a new npm package for browser use or require specific Node.js-compatible Web APIs like the Encoding API, you can opt in to DOM type definitions in your tsconfig.json:

    {
      "compilerOptions": {
    -   "lib": ["ES2020"]
    +   "lib": ["DOM", "ES2020"]
      }
    }
    

    If you have an existing backend project, you can opt out of DOM type definitions in your tsconfig.json.

    For Node.js 14:

    {
      "compilerOptions": {
    +   "lib": ["ES2020"],
        "target": "ES2020"
      }
    }
    

    For Node.js 16:

    {
      "compilerOptions": {
    +   "lib": ["ES2021"],
        "target": "ES2021"
      }
    }
    
  • 4.2.0: Avoid alternative syntax for ENV instructions (#823)

    Omitting the = symbol in ENV instructions is discouraged and may be disallowed in future.

    - ENV NODE_ENV production
    + ENV NODE_ENV=production
    
  • 4.2.0: seek-jobs/gantry v1.7.0 (#824)

  • 4.1.1: Disable type checking in tests (#787)

    Newly initialised projects will skip TypeScript type checking on skuba test as it’s already covered by skuba lint. You can now iterate on your tests without running into annoying compilation errors like TS6133 (unused declarations).

    This will be defaulted for existing projects in a future major version. You can opt in early by setting the globals configuration option in your jest.config.ts:

    export default Jest.mergePreset({
      globals: {
        'ts-jest': {
          // seek-oss/skuba#626
          isolatedModules: true,
        },
      },
      // Rest of config
    });
    
  • 4.1.1: Specify default Buildkite agent (#775)

  • 4.1.1: seek-jobs/gantry v1.6.2 (#778)

  • 4.1.0: skuba-dive ^2.0.0 (#766)

  • 4.1.0: Ignore deployment alarms and ECR scanning (#773)

  • 4.0.0: Use --enable-source-maps (#761)

    Stable source map support has landed in Node.js 14.18+ via the built-in --enable-source-maps option.

    We recommend migrating off of custom source map implementations in favour of this option. Upgrading to skuba-dive v2 will remove source-map-support from the skuba-dive/register hook.

    For a containerised application, update your Dockerfile:

    - FROM gcr.io/distroless/nodejs:12 AS runtime
    + FROM gcr.io/distroless/nodejs:16 AS runtime
    
    + # https://nodejs.org/api/cli.html#cli_node_options_options
    + ENV NODE_OPTIONS=--enable-source-maps
    

    For a Serverless Lambda application, update your serverless.yml:

    provider:
    - runtime: nodejs12.x
    + runtime: nodejs14.x
    
    functions:
      Worker:
        environment:
    +     # https://nodejs.org/api/cli.html#cli_node_options_options
    +     NODE_OPTIONS: --enable-source-maps
    

    For a CDK Lambda application, update your stack:

    new aws_lambda.Function(this, 'worker', {
    - runtime: aws_lambda.Runtime.NODEJS_12_X,
    + runtime: aws_lambda.Runtime.NODEJS_14_X,
      environment: {
    +   // https://nodejs.org/api/cli.html#cli_node_options_options
    +   NODE_OPTIONS: '--enable-source-maps',
      },
    });
    
  • 4.0.0: seek-jobs/gantry v1.6.1 (#759)

  • 3.17.0: Retrieve GitHub token on Test & Lint (#667)

  • 3.17.0: serverless-prune-plugin ^2.0.0 (#719)

  • 3.16.0: Use correct environment key in docker-compose.yml (#654)

  • 3.16.0: Bump non-Lambda templates to Node.js 16 (#633)

    Node.js 16 is now in active LTS. The Lambda templates are stuck on Node.js 14 until the new AWS Lambda runtime is released.

  • 3.16.0: seek-jobs/gantry v1.5.2 (#634)

  • 3.16.0: hot-shots ^9.0.0 (#639)

  • 3.16.0: @seek/logger ^5.0.0 (#621)

  • 3.16.0: Ignore .gantry YAML paths via .prettierignore (#636)

    Gantry resource and value files often live in the .gantry subdirectory and may use non-standard template syntax.

  • 3.16.0: Propagate environment variables for GitHub annotations (#642)

    This enables GitHub annotations for newly-initialised projects with the appropriate Buildkite configuration.

  • 3.15.2: Remove README tables of contents (#596)

    GitHub’s Markdown renderer now generates its own table of contents.

  • 3.15.2: seek-jobs/gantry v1.5.1 (#604)

  • 3.15.2: pino-pretty ^6.0.0 (#594)

    pino-pretty@7 requires pino@7, which has not been released on its stable channel yet.

  • 3.15.1: Remove unknown specifier in catch clauses (#580)

    Strict TypeScript 4.4 now defaults to typing catch clause variables as unknown.

  • 3.15.0: pino-pretty ^7.0.0 (#506)

  • 3.15.0: Configure environment variables and volume mounts for Buildkite annotations (#558)

  • 3.15.0: serverless-plugin-canary-deployments ^0.7.0 (#508)

  • 3.15.0: seek-jobs/gantry v1.4.1 (#504)

  • 3.15.0: Remove @types/node resolution override (#498)

    Jest 27.1 is compatible with newer versions of @types/node.

  • 3.15.0: Suggest using a secure header middleware (#579)

  • 3.15.0: Remove Yarn cache from worker Docker images (#499)

    This shrinks the cached Docker images that our worker templates generate.

  • 3.14.4: @types/node ^14.17.19 (#490)

  • 3.14.4: seek-jobs/gantry v1.4.0 (#483)

  • 3.14.4: Parameterise AWS region (#488)

  • 3.14.3: seek-oss/docker-ecr-cache v1.11.0 (#467)

  • 3.14.3: Add test:ci script (#473)

  • 3.14.3: Force @jest/types resolution to fix clean installs (#468)

  • 3.14.3: Group Buildkite pipeline anchors (#474)

    This provides a bit more structure to our pipeline.ymls and allows anchored plugins to be recognised by Renovate.

  • 3.14.3: Use Docker Build secrets (#471)

  • 3.14.3: Reduce app boilerplate (#478)

  • 3.14.3: Default Docker Compose image to empty string (#469)

    This suppresses Docker Compose CLI warnings and errors when running outside of Buildkite.

  • 3.14.3: Use BUILDKITE_PIPELINE_DEFAULT_BRANCH in pipeline.yml (#475)

  • 3.14.3: Add placeholder test coverage configuration (#472)

  • 3.14.2: Use seek-oss/docker-ecr-cache Buildkite plugin (#453)

  • 3.14.2: Reuse ECR cache in Docker Compose (#453)

  • 3.14.1: pino-pretty ^5.0.0 (#441)

  • 3.14.1: seek-jobs/gantry v1.3.0 (#452)

  • 3.14.0: Banish typeof undefined syntax (#429)

  • 3.14.0: Prune devDependencies instead of installing twice in Docker (#435)

    The template-bundled Dockerfiles would previously run yarn install twice to build a separate stage for production dependencies only. These have been updated to correctly share the Yarn cache across stages and to use yarn install --production to perform offline pruning.

  • 3.13.1: @types/node ^15.0.0 (#422)

  • 3.13.0: Upgrade to Node 14 (#347)

    Node.js 14 is now supported on AWS Lambda. This lets us upgrade the Node.js requirement for skuba’s templates.

    This should only impact newly created projects. You can use the template changes in this PR as an example of how to upgrade an existing project. A future version of skuba may include a fixup command to automatically upgrade your project to the most recent LTS release.

  • 3.13.0: runtypes-filter ^0.6.0 (#408)

  • 3.13.0: Drop region parameterisation (#363)

  • 3.13.0: Fail Gantry build if ECR scanning reports vulnerabilities (#373)

  • 3.13.0: runtypes ^6.0.0 (#404)

  • 3.13.0: Move Gantry region config to plugin options (#374)

  • 3.13.0: Add GitHub repository settings and Renovate to init checklist (#388)

  • 3.12.1: seek-jobs/gantry v1.2.11 (#336)

  • 3.12.0: Use jest.config.ts (#303)

  • 3.12.0: Enable retry of successful deployment steps (#311)

    This should be used with caution, but may be necessary if you need to rapidly roll back a broken deployment.

  • 3.12.0: Supply custom autoscaling policy (#322)

  • 3.12.0: Explicitly register listen.ts (#332)

  • 3.12.0: Clarify health checks and smoke tests (#332)

  • 3.12.0: Bump caret ranges (#331)

  • 3.12.0: Use Distroless runtime images (#316)

  • 3.12.0: Uplift READMEs (#334)

  • 3.11.0: Check coverage on default test script (#290)

  • 3.11.0: Include test:watch script (#290)

  • 3.11.0: Fix server listener and port (#289)

  • 3.11.0: Lock .nvmrcs to Node.js 12 (#281)

  • 3.10.2: Add .me files (#248)

  • 3.10.2: seek-jobs/gantry v1.2.9 (#249)

  • 3.10.2: supertest ^6.0.0 (#243)

  • 3.10.2: runtypes-filter ^0.4.0 (#257)

  • 3.10.2: @koa/router ^10.0.0 (#249)

  • 3.10.2: Mount working directory in Docker Compose (#247)

  • 3.10.2: seek-datadog-custom-metrics ^4.0.0 (#261)

  • 3.10.1: seek-jobs/gantry v1.2.8 (#238)

  • 3.10.0: supertest ^5.0.0 (#220)

  • 3.10.0: Recommend @seek/logger (#225)

    This provides logging structure, trimming and redaction over plain Pino.

  • 3.10.0: docker-compose v3.7.0 (#224)

  • 3.10.0: Unset initial skuba version (#216)

  • 3.10.0: Skip pre-build in Docker Compose service (#222)

  • 3.10.0: Add start:debug scripts (#230)

  • 3.9.2: docker-compose v3.6.0 (#210)

  • 3.9.2: seek-jobs/gantry v1.2.6 (#211)

  • 3.9.2: Bump dep ranges (#212)

  • 3.9.0: Use unknown catch clause variables (#189)


koa-rest-api

A REST resource API built on the Koa web framework and deployed with Gantry.

View on GitHub

Added in 3.4.1

Changelog
  • 9.0.0: Switch from koa-bodyparser to @koa/bodyparser (#1605)

  • 9.0.0: Enable secure headers middleware by default (#1601)

    See the Koala documentation for more information.

  • 9.0.0: Point Docker base images to AWS ECR Public and remove constant --platform arguments (#1684)

  • 8.2.1: Remove JSON schema definitions from Buildkite pipeline files (#1624)

    This reverts #1611 due to incompatibility with pipeline signing.

  • 8.2.1: docker-compose v5.3.0 (#1620)

  • 8.2.0: Clean up src/app.test.ts (#1606)

  • 8.2.0: Add JSON schema definitions to Buildkite pipeline files (#1611)

  • 8.1.0: Add extension recommendations to .vscode/extensions.json (#1556)

  • 8.1.0: Make all configuration values explicit (#1560)

    Previously, src/config.ts included optional configuration values and inheritance between environments in the spirit of DRY. While the templated file was wired up in a “safe” way—the production environment never inherited from other environments and explicitly specified all its configuration values—its pattern was misappropriated elsewhere and led to local configuration values affecting production environments.

    Instead, we now list all configuration values explicitly against each environment.

  • 8.1.0: Remove deprecated docker-compose.yml version (#1570)

    Docker has ignored this for a while, and now generates a warning on every build: https://github.com/compose-spec/compose-spec/blob/master/04-version-and-name.md

  • 8.1.0: Clean up templated environment variables (#1562)

    • AWS_NODEJS_CONNECTION_REUSE_ENABLED is no longer required with AWS SDK V3.
    • The env boilerplate in Gantry values files was largely unnecessary and confusing.

      Our templates prefer to declare configuration values directly in src/config.ts.

  • 8.0.1: Install specific pnpm version via Corepack (#1515)

    Previously, our Dockerfiles ran corepack enable pnpm without installing a specific version. This does not guarantee installation of the pnpm version specified in package.json, which could cause a subsequent pnpm install --offline to run Corepack online or otherwise hang on stdin:

    FROM --platform=arm64 node:20-alpine
    
    RUN corepack enable pnpm
    
    {
      "packageManager": "pnpm@8.15.4",
      "engines": {
        "node": ">=20"
      }
    }
    
    Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-8.15.4.tgz.
    
    Do you want to continue? [Y/n]
    

    To avoid this issue, modify (1) Buildkite pipelines to cache on the packageManager property in package.json, and (2) Dockerfiles to mount package.json and run corepack install:

    - seek-oss/docker-ecr-cache#v2.1.0:
    + seek-oss/docker-ecr-cache#v2.2.0:
        cache-on:
         - .npmrc
    +    - package.json#.packageManager
         - pnpm-lock.yaml
    
    FROM --platform=arm64 node:20-alpine
    
    - RUN corepack enable pnpm
    + RUN --mount=type=bind,source=package.json,target=package.json \
    + corepack enable pnpm && corepack install
    
  • 8.0.1: Fix lint failure (#1514)

    This resolves the following failure on a newly-initialised project due to a regression in the @types/express dependency chain:

    error TS2688: Cannot find type definition file for 'mime'.
      The file is in the program because:
        Entry point for implicit type library 'mime'
    

    A temporary workaround is to install mime as a dev dependency.

  • 8.0.0: Remove BUILDPLATFORM from Dockerfiles (#1350)

    Previously, the built-in templates made use of BUILDPLATFORM and a fallback value:

    FROM --platform=${BUILDPLATFORM:-arm64} gcr.io/distroless/nodejs20-debian11
    
    1. Choose the platform of the host machine running the Docker build. An AWS Graviton Buildkite agent or Apple Silicon laptop will build under arm64, while an Intel laptop will build under amd64.
    2. Fall back to arm64 if the build platform is not available. This maintains compatibility with toolchains like Gantry that lack support for the BUILDPLATFORM argument.

    This approach allowed you to quickly build images and run containers in a local environment without emulation. For example, you could docker build an arm64 image on an Apple Silicon laptop for local troubleshooting, while your CI/CD solution employed amd64 hardware across its build and runtime environments. The catch is that your local arm64 image may exhibit different behaviour, and is unsuitable for use in your amd64 runtime environment without cross-compilation.

    The built-in templates now hardcode --platform as we have largely converged on arm64 across local, build and runtime environments:

    FROM --platform=arm64 gcr.io/distroless/nodejs20-debian11
    

    This approach is more explicit and predictable, reducing surprises when working across different environments and toolchains. Building an image on a different platform will be slower and rely on emulation.

  • 8.0.0: Remove account-level tags from resources (#1494)

    This partially reverts #1459 and #1461 to avoid unnecessary duplication of account-level tags in our templates.

  • 7.5.1: Comply with latest AWS tagging guidance (#1459)

    This includes an upgrade to Gantry v3.

  • 7.4.0: Set readonlyRootFilesystem as a security best practice (#1394)

  • 7.4.0: Use propagate-environment for Docker Compose Buildkite plugin (#1392)

    This simplifies the Docker Compose environment variable configuration required for Buildkite and GitHub integrations.

    In your docker-compose.yml:

    services:
      app:
    -   environment:
    -     # Enable Buildkite + GitHub integrations.
    -     - BUILDKITE
    -     - BUILDKITE_AGENT_ACCESS_TOKEN
    -     - BUILDKITE_BRANCH
    -     - BUILDKITE_BUILD_NUMBER
    -     - BUILDKITE_JOB_ID
    -     - BUILDKITE_PIPELINE_DEFAULT_BRANCH
    -     - BUILDKITE_STEP_ID
    -     - GITHUB_API_TOKEN
        image: ${BUILDKITE_PLUGIN_DOCKER_IMAGE:-''}
        init: true
        volumes:
          - ./:/workdir
          # Mount agent for Buildkite annotations.
          - /usr/bin/buildkite-agent:/usr/bin/buildkite-agent
          # Mount cached dependencies.
          - /workdir/node_modules
    

    In your .buildkite/pipeline.yml:

    steps:
      - commands:
          - pnpm lint
          - pnpm test
        env:
          # At SEEK, this instructs the build agent to populate the GITHUB_API_TOKEN environment variable for this step.
          GET_GITHUB_TOKEN: 'please'
        plugins:
          - *aws-sm
          - *private-npm
          - *docker-ecr-cache
          - docker-compose#v4.16.0:
    +         environment:
    +           - GITHUB_API_TOKEN
    +         propagate-environment: true
              run: app
    
  • 7.4.0: Disable dev CloudWatch dashboards for cost savings (#1395)

  • 7.4.0: Improve input validation error response for Zod unions (#1339)

  • 7.3.1: Update to Node 20 (#1317)

    Consider upgrading the Node.js version for your project across:

    • .nvmrc
    • package.json#/engines/node
    • serverless.yml
    • @types/node package version
    • CI/CD configuration (.buildkite/pipeline.yml, Dockerfile, etc.)

    If you are updating your AWS Lambda runtime to nodejs20.x, consider reading the release announcement as there are some breaking changes with this upgrade.

  • 7.3.0: Fix app.test.ts assertions (#1282)

    Previously, custom .expect((res) => {}) assertions were incorrectly defined to return false rather than throw an error. The template has been updated to avoid this syntax, but the most straightforward diff to demonstrate the fix is as follows:

    - await agent.get('/').expect(({ status }) => status !== 404);
    + await agent.get('/').expect(({ status }) => expect(status).not.toBe(404));
    
  • 7.3.0: seek-oss/docker-ecr-cache 2.1 (#1266)

    This update brings a new skip-pull-from-cache option which is useful on Warm/Build Cache steps.

    At SEEK, our build agents no longer persist their Docker build cache from previous steps. This option allows a preparatory step to proceed on a cache hit without pulling the image from ECR, which can save on average ~1 minute per build for a 2GB Docker image.

  • 7.3.0: Mount npm build secret to a separate directory (#1278)

    Our templated Buildkite pipelines currently retrieve a temporary .npmrc. This file contains an npm read token that allows us to fetch private @seek-scoped packages.

    New projects now write this file to /tmp/ on the Buildkite agent and mount it as a secret to /root/ in Docker. This separation allows you to commit a non-sensitive .npmrc to your GitHub repository while avoiding accidental exposure of the npm read token. This is especially important if you are migrating a project to pnpm, which houses some of its configuration options in .npmrc.

    Existing projects are generally advised to wait until we’ve paved a cleaner migration path for pnpm.

  • 7.1.0: Switch distroless image from nodejs:18 to nodejs18-debian11 (#1224)

  • 7.0.0: Require Node.js 18.12+ (#1206)

  • 6.2.0: Include manifest files in CODEOWNERS (#1162)

    Our templates previously excluded package.json and yarn.lock from CODEOWNERS. This was intended to support advanced workflows such as auto-merging PRs and augmenting GitHub push notifications with custom tooling. However, we are reverting this configuration as it is more common for SEEKers to prefer a simpler CODEOWNERS-based workflow.

    This will not affect existing projects. If you create a new project and wish to restore the previous behaviour, you can manually extend .github/CODEOWNERS:

    * @<%- ownerName %>
    
    + # Configured by Renovate
    + package.json
    + yarn.lock
    
  • 6.2.0: Remove Gantry ignoreAlarms override (#1160)

    This issue has been resolved in Gantry v2.2.0; see its release notes for more information.

    deployment:
    - # SEEK-Jobs/gantry#488
    - ignoreAlarms: true
    
  • 5.1.0: Prompt for target platform (amd64 or arm64) (#1041)

  • 5.1.0: Replace '' with a custom environment Gantry value. (#1065)

  • 5.0.0: Bump greeter and API templates to Node.js 18 (#1011)

    Node.js 18 is now in active LTS. The Lambda templates are stuck on Node.js 16 until the new AWS Lambda runtime is released.

  • 5.0.0: Support AMD64 Docker builds via BUILDPLATFORM (#1021)

    See the Docker documentation for more information. Note that this does not allow you to build on AMD64 hardware then deploy to ARM64 hardware and vice versa. It is provided for convenience if you need to revert to an AMD64 workflow and/or build and run an image on local AMD64 hardware.

  • 5.0.0: Replace Runtypes with Zod as default schema validator (#984)

  • 4.4.1: Drop uuid (#964)

    V4 UUIDs can be generated using the built-in crypto.randomUUID() function starting from Node.js 14.17. This is analogous to the Crypto.randomUUID() Web API.

    - import { v4 as randomUUID } from 'uuid';
    + import { randomUUID } from 'crypto';
    
  • 4.3.1: seek-jobs/gantry v2.0.0 (#935)

  • 4.3.1: Fix README link to ARM64 guide (#913)

  • 4.3.1: Fix Gantry documentation links (#931)

  • 4.3.0: seek-jobs/gantry v1.8.1 (#887)

  • 4.3.0: Remove .me files (#902)

    SEEK is moving away from Codex to off-the-shelf software powered by Backstage catalog-info.yaml files.

    At the moment we’re only asking teams to document their systems, which typically span across multiple repositories. We may add catalog-info.yaml files back to the templates if there’s a need for teams to document their components at a repository level.

  • 4.3.0: Use ARM64 architecture (#873)

    We now recommend building and running projects on ARM64 hardware for greater cost efficiency. This requires a Graviton-based Buildkite cluster; see our ARM64 guide for more information.

  • 4.2.1: Time out Buildkite test steps after 10 minutes (#842)

    Successful testing and linting should complete within this window. This timeout prevents commands from hanging and indefinitely preoccupying your Buildkite agents.

    steps:
      - label: 🧪 Test & Lint
    +   timeout_in_minutes: 10
    
  • 4.2.1: Use AsyncLocalStorage to track logger context (#864)

    We now employ RequestLogging.createContextStorage to thread logging context through the middleware stack of your Koa application. This enables use of a singleton logger instance instead of manually propagating Koa context and juggling rootLoggers and contextLoggers.

    Before:

    import createLogger from '@seek/logger';
    import Koa, { Context } from 'koa';
    import { RequestLogging } from 'seek-koala';
    
    const rootLogger = createLogger();
    
    const contextLogger = (ctx: Context) =>
      rootLogger.child(RequestLogging.contextFields(ctx));
    
    const app = new Koa().use((ctx) => {
      rootLogger.info('Has no context');
    
      contextLogger(ctx).info('Has context');
    });
    

    After:

    import createLogger from '@seek/logger';
    import Koa from 'koa';
    import { RequestLogging } from 'seek-koala';
    
    const { createContextMiddleware, mixin } =
      RequestLogging.createContextStorage();
    
    const contextMiddleware = createContextMiddleware();
    
    const logger = createLogger({ mixin });
    
    const app = new Koa().use(contextMiddleware).use((ctx) => {
      logger.info('Has context');
    });
    
  • 4.2.0: Propagate Buildkite environment variables for lint autofixing (#800)

  • 4.2.0: Exclude DOM type definitions by default (#822)

    TypeScript will now raise compiler errors when DOM globals like document and window are referenced in new projects. This catches unsafe usage of Web APIs that will throw exceptions in a Node.js context.

    If you are developing a new npm package for browser use or require specific Node.js-compatible Web APIs like the Encoding API, you can opt in to DOM type definitions in your tsconfig.json:

    {
      "compilerOptions": {
    -   "lib": ["ES2020"]
    +   "lib": ["DOM", "ES2020"]
      }
    }
    

    If you have an existing backend project, you can opt out of DOM type definitions in your tsconfig.json.

    For Node.js 14:

    {
      "compilerOptions": {
    +   "lib": ["ES2020"],
        "target": "ES2020"
      }
    }
    

    For Node.js 16:

    {
      "compilerOptions": {
    +   "lib": ["ES2021"],
        "target": "ES2021"
      }
    }
    
  • 4.2.0: Avoid alternative syntax for ENV instructions (#823)

    Omitting the = symbol in ENV instructions is discouraged and may be disallowed in future.

    - ENV NODE_ENV production
    + ENV NODE_ENV=production
    
  • 4.2.0: seek-jobs/gantry v1.7.0 (#824)

  • 4.1.1: Disable type checking in tests (#787)

    Newly initialised projects will skip TypeScript type checking on skuba test as it’s already covered by skuba lint. You can now iterate on your tests without running into annoying compilation errors like TS6133 (unused declarations).

    This will be defaulted for existing projects in a future major version. You can opt in early by setting the globals configuration option in your jest.config.ts:

    export default Jest.mergePreset({
      globals: {
        'ts-jest': {
          // seek-oss/skuba#626
          isolatedModules: true,
        },
      },
      // Rest of config
    });
    
  • 4.1.1: Specify default Buildkite agent (#775)

  • 4.1.1: seek-jobs/gantry v1.6.2 (#778)

  • 4.1.0: skuba-dive ^2.0.0 (#766)

  • 4.1.0: Ignore deployment alarms and ECR scanning (#773)

  • 4.0.0: Use --enable-source-maps (#761)

    Stable source map support has landed in Node.js 14.18+ via the built-in --enable-source-maps option.

    We recommend migrating off of custom source map implementations in favour of this option. Upgrading to skuba-dive v2 will remove source-map-support from the skuba-dive/register hook.

    For a containerised application, update your Dockerfile:

    - FROM gcr.io/distroless/nodejs:12 AS runtime
    + FROM gcr.io/distroless/nodejs:16 AS runtime
    
    + # https://nodejs.org/api/cli.html#cli_node_options_options
    + ENV NODE_OPTIONS=--enable-source-maps
    

    For a Serverless Lambda application, update your serverless.yml:

    provider:
    - runtime: nodejs12.x
    + runtime: nodejs14.x
    
    functions:
      Worker:
        environment:
    +     # https://nodejs.org/api/cli.html#cli_node_options_options
    +     NODE_OPTIONS: --enable-source-maps
    

    For a CDK Lambda application, update your stack:

    new aws_lambda.Function(this, 'worker', {
    - runtime: aws_lambda.Runtime.NODEJS_12_X,
    + runtime: aws_lambda.Runtime.NODEJS_14_X,
      environment: {
    +   // https://nodejs.org/api/cli.html#cli_node_options_options
    +   NODE_OPTIONS: '--enable-source-maps',
      },
    });
    
  • 4.0.0: seek-jobs/gantry v1.6.1 (#759)

  • 3.17.0: Add opt-in OpenTelemetry support (#706)

  • 3.17.0: Retrieve GitHub token on Test & Lint (#667)

  • 3.17.0: serverless-prune-plugin ^2.0.0 (#719)

  • 3.16.0: Use correct environment key in docker-compose.yml (#654)

  • 3.16.0: Bump non-Lambda templates to Node.js 16 (#633)

    Node.js 16 is now in active LTS. The Lambda templates are stuck on Node.js 14 until the new AWS Lambda runtime is released.

  • 3.16.0: seek-jobs/gantry v1.5.2 (#634)

  • 3.16.0: hot-shots ^9.0.0 (#639)

  • 3.16.0: @seek/logger ^5.0.0 (#621)

  • 3.16.0: Ignore .gantry YAML paths via .prettierignore (#636)

    Gantry resource and value files often live in the .gantry subdirectory and may use non-standard template syntax.

  • 3.16.0: Propagate environment variables for GitHub annotations (#642)

    This enables GitHub annotations for newly-initialised projects with the appropriate Buildkite configuration.

  • 3.15.2: Remove README tables of contents (#596)

    GitHub’s Markdown renderer now generates its own table of contents.

  • 3.15.2: seek-jobs/gantry v1.5.1 (#604)

  • 3.15.2: pino-pretty ^6.0.0 (#594)

    pino-pretty@7 requires pino@7, which has not been released on its stable channel yet.

  • 3.15.1: Remove unknown specifier in catch clauses (#580)

    Strict TypeScript 4.4 now defaults to typing catch clause variables as unknown.

  • 3.15.0: pino-pretty ^7.0.0 (#506)

  • 3.15.0: Configure environment variables and volume mounts for Buildkite annotations (#558)

  • 3.15.0: serverless-plugin-canary-deployments ^0.7.0 (#508)

  • 3.15.0: seek-jobs/gantry v1.4.1 (#504)

  • 3.15.0: Remove @types/node resolution override (#498)

    Jest 27.1 is compatible with newer versions of @types/node.

  • 3.15.0: Suggest using a secure header middleware (#579)

  • 3.15.0: Remove Yarn cache from worker Docker images (#499)

    This shrinks the cached Docker images that our worker templates generate.

  • 3.14.4: @types/node ^14.17.19 (#490)

  • 3.14.4: seek-jobs/gantry v1.4.0 (#483)

  • 3.14.4: Parameterise AWS region (#488)

  • 3.14.3: seek-oss/docker-ecr-cache v1.11.0 (#467)

  • 3.14.3: Add test:ci script (#473)

  • 3.14.3: Force @jest/types resolution to fix clean installs (#468)

  • 3.14.3: Group Buildkite pipeline anchors (#474)

    This provides a bit more structure to our pipeline.ymls and allows anchored plugins to be recognised by Renovate.

  • 3.14.3: Reduce app boilerplate (#478)

  • 3.14.3: Default Docker Compose image to empty string (#469)

    This suppresses Docker Compose CLI warnings and errors when running outside of Buildkite.

  • 3.14.3: Use BUILDKITE_PIPELINE_DEFAULT_BRANCH in pipeline.yml (#475)

  • 3.14.3: Add placeholder test coverage configuration (#472)

  • 3.14.3: Use Docker Build secrets (#471)

  • 3.14.2: Include success message in smoke test body (#459)

  • 3.14.2: Use seek-oss/docker-ecr-cache Buildkite plugin (#453)

  • 3.14.2: Reuse ECR cache in Docker Compose (#453)

  • 3.14.1: pino-pretty ^5.0.0 (#441)

  • 3.14.1: seek-jobs/gantry v1.3.0 (#452)

  • 3.14.0: Banish typeof undefined syntax (#429)

  • 3.14.0: Log returned error responses (#430)

  • 3.14.0: Prune devDependencies instead of installing twice in Docker (#435)

    The template-bundled Dockerfiles would previously run yarn install twice to build a separate stage for production dependencies only. These have been updated to correctly share the Yarn cache across stages and to use yarn install --production to perform offline pruning.

  • 3.13.1: @types/node ^15.0.0 (#422)

  • 3.13.0: Upgrade to Node 14 (#347)

    Node.js 14 is now supported on AWS Lambda. This lets us upgrade the Node.js requirement for skuba’s templates.

    This should only impact newly created projects. You can use the template changes in this PR as an example of how to upgrade an existing project. A future version of skuba may include a fixup command to automatically upgrade your project to the most recent LTS release.

  • 3.13.0: runtypes-filter ^0.6.0 (#408)

  • 3.13.0: Fix ineffectual smoke test (#361)

  • 3.13.0: Drop region parameterisation (#363)

  • 3.13.0: Fail Gantry build if ECR scanning reports vulnerabilities (#373)

  • 3.13.0: runtypes ^6.0.0 (#404)

  • 3.13.0: Remove awkward request body from GET test (#362)

  • 3.13.0: Move Gantry region config to plugin options (#374)

  • 3.13.0: Add GitHub repository settings and Renovate to init checklist (#388)

  • 3.12.1: Tidy custom Koa types (#336)

  • 3.12.1: seek-jobs/gantry v1.2.11 (#336)

  • 3.12.0: Type context (#299)

  • 3.12.0: Use jest.config.ts (#303)

  • 3.12.0: Enable retry of successful deployment steps (#311)

    This should be used with caution, but may be necessary if you need to rapidly roll back a broken deployment.

  • 3.12.0: Supply custom autoscaling policy (#322)

  • 3.12.0: Explicitly register listen.ts (#332)

  • 3.12.0: Limit request logging to errors (#294)

  • 3.12.0: Clarify health checks and smoke tests (#332)

  • 3.12.0: Bump caret ranges (#331)

  • 3.12.0: Use Distroless runtime images (#316)

  • 3.12.0: Uplift READMEs (#334)

  • 3.11.0: Check coverage on default test script (#290)

  • 3.11.0: Include test:watch script (#290)

  • 3.11.0: Lock .nvmrcs to Node.js 12 (#281)

  • 3.10.2: Add .me files (#248)

  • 3.10.2: seek-jobs/gantry v1.2.9 (#249)

  • 3.10.2: seek-koala ^5.0.0 (#260)

  • 3.10.2: supertest ^6.0.0 (#243)

  • 3.10.2: runtypes-filter ^0.4.0 (#257)

  • 3.10.2: @koa/router ^10.0.0 (#249)

  • 3.10.2: Mount working directory in Docker Compose (#247)

  • 3.10.2: seek-datadog-custom-metrics ^4.0.0 (#261)

  • 3.10.1: seek-jobs/gantry v1.2.8 (#238)

  • 3.10.0: supertest ^5.0.0 (#220)

  • 3.10.0: hot-shots ^8.0.0 (#217)

  • 3.10.0: Recommend @seek/logger (#225)

    This provides logging structure, trimming and redaction over plain Pino.

  • 3.10.0: docker-compose v3.7.0 (#224)

  • 3.10.0: Unset initial skuba version (#216)

  • 3.10.0: Avoid export = syntax (#90)

  • 3.10.0: Skip pre-build in Docker Compose service (#222)

  • 3.10.0: Add start:debug scripts (#230)

  • 3.9.2: docker-compose v3.6.0 (#210)

  • 3.9.2: seek-jobs/gantry v1.2.6 (#211)

  • 3.9.2: Remove koa-cluster (#206)

    While Fargate environments with <= 1 vCPU appear to expose multiple threads, clustering does not improve performance and only serves to increase idle memory usage.

    You may add koa-cluster yourself if you have a CPU-bound workload running on multiple vCPUs. Even in such cases, it may be better to run multiple tasks with one vCPU each rather than one task with multiple vCPUs.

  • 3.9.2: Bump dep ranges (#212)

  • 3.9.0: Use unknown catch clause variables (#189)

  • 3.8.0: seek-jobs/gantry v1.2.5 (#174)

  • 3.7.7: Use per-Gantry environment concurrency group in dev (#165)

  • 3.7.7: seek-jobs/gantry v1.2.4 (#170)

  • 3.7.7: Simplify supertest-koa bootstrap (#163)

  • 3.7.7: Remove explicitly set NPM_READ_TOKEN from Dockerfile commands (#168)

  • 3.7.6: runtypes-filter ^0.3.0 (#160)

  • 3.7.6: Keep AWS SDK connections alive (#159)

  • 3.7.6: seek-jobs/gantry v1.2.3 (#161)

  • 3.7.6: docker-compose v3.5.0 (#153)

  • 3.7.6: runtypes ^5.0.0 (#156)

  • 3.7.5: Add intermediate Dockerfile stages (#147)

  • 3.7.5: ecr v2.1.1 (#144)

  • 3.7.5: Switch to Runtypes (#152)

    Yup has overly permissive input coercion (see #151) and weaker type guarantees.

    We already use Runtypes in the Lambda template; other options could be explored in future.

  • 3.7.5: docker-compose v3.4.0 (#144)

  • 3.7.5: Add basic deployment documentation (#148)

  • 3.7.4: Redact err.config.agent path from logs (#140)

  • 3.7.0: Redact Authorization headers in logs (#59)

  • 3.7.0: Ensure lint passes on init (#70)

  • 3.7.0: Redact err.config.sockets from logs (#82)

  • 3.7.0: Support improved Runtypes error messaging (#96)

  • 3.7.0: Drop duplicate team name prompt (#72)

  • 3.7.0: Use Koala’s error handler (#44)

  • 3.6.0: Remove unused function (#35)

  • 3.6.0: Pass through Gantry environment as ENVIRONMENT (#37)

  • 3.5.0: Switch to seek-datadog-custom-metrics (#28)

  • 3.5.0: Switch to seek-koala (#28)

  • 3.5.0: Bump Gantry plugin to v1.2.2 (#8)