Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Changelog

All notable changes to this project will be documented in this file.

## [Unreleased]

### Added

- Added `bin/deploy temporary` for disposable public Azure Container Apps environments from pull requests, branches, or immutable git hashes, including readiness checks, persisted cleanup state, and non-production resource guardrails.

### Changed

- Renamed temporary deployment environment variables to the `TEMPORARY_DEPLOYMENT_*` namespace to make the public configuration contract explicit.
9 changes: 8 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,15 @@ RUN npm clean-install

COPY web ./

# Switching to production mode for build environment.
ARG VITE_TEMPORARY_HOST_SUFFIX
ARG VITE_TEMPORARY_AUTH0_DOMAIN
ARG VITE_TEMPORARY_AUTH0_AUDIENCE
ARG VITE_TEMPORARY_AUTH0_CLIENT_ID
ENV NODE_ENV=production
ENV VITE_TEMPORARY_HOST_SUFFIX=${VITE_TEMPORARY_HOST_SUFFIX}
ENV VITE_TEMPORARY_AUTH0_DOMAIN=${VITE_TEMPORARY_AUTH0_DOMAIN}
ENV VITE_TEMPORARY_AUTH0_AUDIENCE=${VITE_TEMPORARY_AUTH0_AUDIENCE}
ENV VITE_TEMPORARY_AUTH0_CLIENT_ID=${VITE_TEMPORARY_AUTH0_CLIENT_ID}
RUN npm run build

# Stage 3 - production setup
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
source "https://rubygems.org"

gem "local-development-gateway", "~> 0.1"
gem "local-development-gateway", "~> 0.1.2"
gem "json", ">= 2.7.2"
gem "rdoc"

Expand Down
6 changes: 3 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ GEM
erb (6.0.6)
json (2.21.1)
language_server-protocol (3.17.0.6)
local-development-gateway (0.1.0)
local-development-gateway (0.1.2)
logger (1.7.0)
prettier_print (1.2.1)
prism (1.9.0)
Expand All @@ -31,7 +31,7 @@ PLATFORMS

DEPENDENCIES
json (>= 2.7.2)
local-development-gateway (~> 0.1)
local-development-gateway (~> 0.1.2)
prettier_print (= 1.2.1)
rdoc
ruby-lsp (= 0.26.9)
Expand All @@ -41,7 +41,7 @@ CHECKSUMS
erb (6.0.6) sha256=a9b24986700f5bf127c4f297c5403c3ca41b83b0a316c0cd09a096b56e644ae5
json (2.21.1) sha256=13a43df75d95641443f5702dff350f237164a9d811ff0f2c2800d4d980220583
language_server-protocol (3.17.0.6) sha256=5ef2c0c138f8267e1bc631d3328347d354f96724b0af22f2c79516120443b7f0
local-development-gateway (0.1.0) sha256=0f443837bbc4900ae0f3ea383c2055b27f741e4c81a57d03d0e5a8e9bdc6bff7
local-development-gateway (0.1.2) sha256=51e94cb3c614d4c5a310e43d7bb27115efa0873090df8f31cf0e9b497f340082
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
prettier_print (1.2.1) sha256=a72838b5f23facff21f90a5423cdcdda19e4271092b41f4ea7f50b83929e6ff9
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
Expand Down
3 changes: 1 addition & 2 deletions api/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,11 @@ export const RUN_SCHEDULER = process.env.RUN_SCHEDULER || "false"
// ====================
// Authentication & Authorization
// ====================

// Auth0 Configuration
export const AUTH0_DOMAIN = stripTrailingSlash(process.env.VITE_AUTH0_DOMAIN || "")
export const AUTH0_AUDIENCE = process.env.VITE_AUTH0_AUDIENCE
export const AUTH0_REDIRECT = process.env.VITE_AUTH0_REDIRECT || process.env.FRONTEND_URL || ""

export const QA_ENVIRONMENT = process.env.QA_ENVIRONMENT === "true"
// ====================
// Database & Cache Configuration
// ====================
Expand Down
96 changes: 96 additions & 0 deletions bin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,99 @@ dev sqlcmd -i ./data/funding_submission_lines.sql
assuming the file is located at `/db/data/funding_submission_lines.sql`

Note that the `dev` command uses the `db` service, and so only has access to folders under the top-level `db` directory.

## Temporary deployments

`bin/deploy temporary` builds the selected immutable commit and provisions a
disposable public Azure Container Apps environment.

```bash
bin/deploy temporary --pr 51 --ttl-hours 4
bin/deploy temporary --branch feature/example --ttl-hours 4
bin/deploy temporary --git-hash 0123456789abcdef0123456789abcdef01234567
bin/deploy temporary status --pr 51
bin/deploy temporary logs --pr 51 --follow
bin/deploy temporary down --pr 51
bin/deploy temporary down --all --expired --yes
```

`bin/deploy ephemeral` is an alias for `bin/deploy temporary`. The environment
URL is `https://tk-temporary-<source>.<TEMPORARY_DEPLOYMENT_DOMAIN_SUFFIX>`. Each
deployment has isolated SQL Server, Redis, MailDev, and blob storage.

State is stored in `TEMPORARY_DEPLOYMENT_STATE_DIRECTORY` (default:
`~/.traditional-knowledge-temporary`) so failed cleanup can be retried. TTL is
recorded; there is no background scheduler.

Before use, configure these local-only `TEMPORARY_DEPLOYMENT_*` variables:

- `TEMPORARY_DEPLOYMENT_RESOURCE_GROUP`, `TEMPORARY_DEPLOYMENT_CONTAINER_APPS_ENVIRONMENT`,
`TEMPORARY_DEPLOYMENT_CONTAINER_REGISTRY_SERVER`, `TEMPORARY_DEPLOYMENT_AZURE_SUBSCRIPTION_ID`
- `TEMPORARY_DEPLOYMENT_DOMAIN_SUFFIX`, with an ACA custom-domain suffix and wildcard
certificate
- `TEMPORARY_DEPLOYMENT_STORAGE_ACCOUNT`, `TEMPORARY_DEPLOYMENT_BLOB_CONNECTION_STRING`,
`TEMPORARY_DEPLOYMENT_BLOB_CONTAINER`
- `TEMPORARY_DEPLOYMENT_AUTH0_MANAGEMENT_TOKEN`,
`TEMPORARY_DEPLOYMENT_AUTH0_ALLOWED_HOST_SUFFIX`

The command defaults to the shared UAT Auth0 domain, audience, and client ID.
Set the `TEMPORARY_DEPLOYMENT_AUTH0_*` overrides only when using another compatible
Auth0 application.

Use the `artzzpr-sub` subscription (or its ID), not `wrpzzpr-sub`. The command
resolves the configured subscription before Azure REST calls. A developer with
an eligible Azure role can use PIM self-activation; CI should use an
OIDC/service-principal identity with scoped write access.

Configure the Auth0 application with these wildcard values, replacing
`<suffix>` with `TEMPORARY_DEPLOYMENT_DOMAIN_SUFFIX`:

```text
Allowed Callback URLs: https://*.<suffix>/callback
Allowed Logout URLs: https://*.<suffix>
Allowed Web Origins: https://*.<suffix>
```

The resource group, ACA environment, storage account, and ACR must all carry
`traditional-knowledge-temporary=true`. Do not use production credentials or
resources.

### GitHub Actions

The CLI is workflow-safe without a repository-specific action. Authenticate
Azure with OIDC and grant the workflow identity scoped access to the temporary
resource group; do not rely on interactive PIM in CI:

```yaml
permissions:
contents: read
id-token: write

env:
TEMPORARY_DEPLOYMENT_RESOURCE_GROUP: ${{ vars.TEMPORARY_DEPLOYMENT_RESOURCE_GROUP }}
TEMPORARY_DEPLOYMENT_CONTAINER_APPS_ENVIRONMENT: ${{ vars.TEMPORARY_DEPLOYMENT_CONTAINER_APPS_ENVIRONMENT }}
TEMPORARY_DEPLOYMENT_CONTAINER_REGISTRY_SERVER: ${{ vars.TEMPORARY_DEPLOYMENT_CONTAINER_REGISTRY_SERVER }}
TEMPORARY_DEPLOYMENT_AZURE_SUBSCRIPTION_ID: ${{ vars.TEMPORARY_DEPLOYMENT_AZURE_SUBSCRIPTION_ID }}
TEMPORARY_DEPLOYMENT_DOMAIN_SUFFIX: ${{ vars.TEMPORARY_DEPLOYMENT_DOMAIN_SUFFIX }}
TEMPORARY_DEPLOYMENT_STORAGE_ACCOUNT: ${{ vars.TEMPORARY_DEPLOYMENT_STORAGE_ACCOUNT }}
TEMPORARY_DEPLOYMENT_BLOB_CONTAINER: ${{ vars.TEMPORARY_DEPLOYMENT_BLOB_CONTAINER }}
TEMPORARY_DEPLOYMENT_AUTH0_ALLOWED_HOST_SUFFIX: ${{ vars.TEMPORARY_DEPLOYMENT_AUTH0_ALLOWED_HOST_SUFFIX }}
TEMPORARY_DEPLOYMENT_BLOB_CONNECTION_STRING: ${{ secrets.TEMPORARY_DEPLOYMENT_BLOB_CONNECTION_STRING }}
TEMPORARY_DEPLOYMENT_AUTH0_MANAGEMENT_TOKEN: ${{ secrets.TEMPORARY_DEPLOYMENT_AUTH0_MANAGEMENT_TOKEN }}
TEMPORARY_DEPLOYMENT_STATE_DIRECTORY: ${{ runner.temp }}/traditional-knowledge-temporary
GH_TOKEN: ${{ github.token }}

steps:
- uses: actions/checkout@v4
- uses: azure/login@v2
with:
client-id: ${{ secrets.TEMPORARY_DEPLOYMENT_AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.TEMPORARY_DEPLOYMENT_AZURE_TENANT_ID }}
subscription-id: ${{ vars.TEMPORARY_DEPLOYMENT_AZURE_SUBSCRIPTION_ID }}
- run: bin/deploy temporary --pr "${{ github.event.pull_request.number }}"
- if: ${{ always() }}
run: bin/deploy temporary down --all --yes
```

Use `workflow_dispatch` or a trusted same-repository pull request workflow.
Never expose Azure or Auth0 secrets to untrusted fork code.
12 changes: 12 additions & 0 deletions bin/deploy
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env ruby

require_relative "lib/deploy/all"

if $PROGRAM_NAME == __FILE__
begin
TraditionalKnowledgeTemporaryDeployment::Command.call(ARGV)
rescue ArgumentError => error
warn error.message
exit 1
end
end
Loading