Skip to main content
All three GKL Platform repositories deploy the same way in principle and differ in the details. This page covers what is shared, then what is specific to each.
There is no approval gate on any GKL pipeline. Pushing to a production branch deploys to production. This is the single most surprising thing about the setup and the one most likely to catch someone out.

The Branch Is The Environment

There is no deploy button and no release process. A pipeline watches a branch, and pushing to that branch is the deployment. The Booking Website is the odd one out. It was rebuilt, and the v2 suffix in both its branch names and its stack names is a leftover from that rebuild rather than anything meaningful today. Promotion is a branch push:
All three repositories are in AWS CodeCommit. CodeCommit is closed to new customers and cannot be recreated, so migrating to the SG GitHub organisation is outstanding work that affects every one of them.

Key Facts

GKL API

Deployed by two pipelines defined in one bootstrap stack. The pipeline runs three builds in parallel before synthesising, one per deployable artifact:
1

The API Lambda

Pins .NET 8, installs Amazon.Lambda.Tools, and runs dotnet lambda package to produce the API Gateway Lambda zip.
2

The notification Lambda

Installs the Python requirements into the function directory and zips it.
3

The HubSpot Lambda

The same pattern as the notification Lambda.
4

Synth and deploy

The synth step deletes the stale zips committed in the repository, copies the freshly built ones in, then runs cdk synth. The stage that follows deploys GklPlatformApiStack-{stage}.
The zips in CdkBuild/build_assets/ are committed placeholders. They exist so cdk synth works on a laptop, and the pipeline deletes and replaces them on every run. They are not live artifacts, despite being binaries in source control.
This pipeline self mutates. Changing the CDK is safe: the pipeline updates itself first, then deploys. The two web app pipelines do not, so a structural CDK change there needs a manual cdk deploy.

Operator Dashboard

Both environments live in one stack, which also defines both pipelines.

Booking Website

Here each environment gets its own stack, which is the better pattern of the two. The Operator Dashboard was never migrated to it, so the asymmetry is unfinished convergence rather than a deliberate difference.

How The Web Apps Actually Deploy

Neither web app pipeline has a deploy stage. The deployment happens inside the synth step:
The reasoning is that a static site needs files in a bucket and a cache flush, and routing that through a CDK stage means a second CodeBuild plus a CloudFormation deployment that changes nothing. Because the deploy is in the synth step, the CodeBuild role needs S3 and CloudFront permissions granted explicitly through codeBuildDefaults.rolePolicy rather than inherited from a deploy action.

How The Front Ends Learn The API URL

This is the contract between the repositories, and the reason deployment order matters.
1

The API publishes where it lives

On deploy, the API stack writes its public gateway URL to the SSM parameter /GklPlatform/configuration/{stage}/UK.
2

The web app reads it at synth time

Each web app’s CDK looks that parameter up while synthesising.
3

The build writes it into the bundle

The build step generates environment.ts line by line with echo, interpolating the URL. The Booking Website also pulls its external API key straight from Secrets Manager during the build.
Because the lookup happens at synth time, the resolved value is cached into cdk.context.json and committed. If the API gateway is ever recreated with a new ID, the web apps keep building against the stale cached URL until someone deletes that file.

Bootstrapping

The pipelines are themselves CDK stacks that were deployed by hand once. For the API:
That creates both API pipelines, which then manage themselves. The Booking Website’s stages are instantiated directly into the CDK app, so they are addressed by path:
These are needed the first time a pipeline definition changes rather than application code.
Last modified on September 10, 2026