> ## Documentation Index
> Fetch the complete documentation index at: https://playbook.smedleygroup.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deployment and Environments

> How the three GKL Platform repositories reach production: branch based environments, the pipelines, and the order things have to be deployed in.

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.

> [!WARNING]
>
> 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.

| Repository | Dev branch | Prod branch |
| - | - | - |
| GklPlatform-API | `dev` | `prod` |
| GklPlatform-OperatorWebApp | `dev` | `prod` |
| GklPlatform-WebApp | `dev-v2` | `prod-v2` |

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:

```bash theme={null}
git push origin dev:prod
```

> [!NOTE]
>
> 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

| Setting | Value |
| - | - |
| AWS account | `338232497876` |
| Region | `eu-west-2`, except ACM certificates in `us-east-1` |
| Source | AWS CodeCommit |
| IaC | TypeScript AWS CDK, one `CdkBuild` project per repository |
| Approval gates | None |

## GKL API

Deployed by two pipelines defined in one bootstrap stack.

| Resource | Name |
| - | - |
| Bootstrap stack | `GklPlatform` |
| Pipelines | `GklPlatformApiPipeline-dev`, `GklPlatformApiPipeline-prod` |
| Artifact bucket | `gkl-platform-api-pipeline-bucket` |
| Deployed stack | `GklPlatformApiStack-dev`, `GklPlatformApiStack-prod` |

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}`.

> [!NOTE]
>
> 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

| Resource | Name |
| - | - |
| Certificate stack (`us-east-1`) | `GklPlatformOperatorWebAppCertificateStack` |
| Deployment stack (`eu-west-2`) | `GklPlatformOperatorWebApp` |
| Pipelines | `GklPlatformOperatorWebAppPipeline-dev`, `GklPlatformOperatorWebAppPipeline-prod` |
| Artifact bucket | `gkl-platform-operator-web-app-pipeline-bucket` |
| Deployment buckets | `gkl-platform-operator-web-app-deployment-bucket-{stage}-uk` |

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

## Booking Website

| Resource | Name |
| - | - |
| Stages | `GklPlatformNewWebAppDeploymentStage-dev-v2`, `-prod-v2` |
| Certificate stack (`us-east-1`) | `GklPlatformSingleInstanceWebAppCertificateStack-{stage}` |
| Deployment stack (`eu-west-2`) | `GklPlatformSingleInstanceWebApp-{stage}` |
| Pipelines | `GklPlatformSingleInstanceWebAppPipeline-{stage}` |
| Deployment buckets | `gkl-platform-single-instance-web-app-deployment-bucket-{stage}` |

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:

```
unzip the built Angular bundle
aws s3 rm s3://<deployment bucket> --recursive
aws s3 sync build-webapps/dist/<app>/browser/ s3://<deployment bucket>
aws cloudfront create-invalidation --paths "/*"
npm install && npx cdk synth
```

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.

> [!WARNING]
>
> 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:

```bash theme={null}
npx cdk deploy GklPlatform
```

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:

```bash theme={null}
npx cdk deploy GklPlatformNewWebAppDeploymentStage-prod-v2/*
```

These are needed the first time a pipeline definition changes rather than application code.

## Related Documentation

| Page | Relevance |
| - | - |
| [GKL API](/software/developer/estate/systems/gkl/gkl-api) | What the API does |
| [Infrastructure BAU](/software/developer/operations/index) | The weekly pipeline and drift check |
| [TalentIdPipeline-Infra-CDK](/software/developer/estate/infra/talentidpipeline-infra-cdk) | The VPC and database these stacks depend on |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.