Skip to content
Closed
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
82 changes: 0 additions & 82 deletions .github/dependabot.yml

This file was deleted.

61 changes: 61 additions & 0 deletions .github/workflows/renovate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Renovate

# Self-hosted Renovate via renovatebot/github-action. Phase 6 of the
# scenario-regression smoke-pack tech-spec. Replaces .github/dependabot.yml
# (deleted in this PR per ADR-2) with the unified bot.
#
# Cadence: twice daily. The cold-start cost is non-trivial (~2-3 min full
# scan + per-package resolution) so 4×/day would burn CI minutes without
# proportional value. workflow_dispatch lets a maintainer trigger ad-hoc.
#
# Action pin: digest, not tag. The spec's pinning strategy is "every pin
# must carry a Renovate-trackable tag alongside the digest." The digest
# below tracks v46.1.14 of renovatebot/github-action. Renovate's
# github-actions packageRule (in renovate.json) pinDigests=true keeps
# this current.

on:
schedule:
- cron: '0 6,18 * * *' # 06:00 and 18:00 UTC daily
workflow_dispatch:
inputs:
logLevel:
description: 'Log level (debug for verbose)'
required: false
default: 'info'
type: choice
options:
- info
- debug

permissions:
contents: read
# Renovate writes via the PAT (RENOVATE_TOKEN), NOT GITHUB_TOKEN. Keeping
# GITHUB_TOKEN's permissions tight prevents accidental scope creep.

concurrency:
group: renovate
cancel-in-progress: false

jobs:
renovate:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v6

- name: Run Renovate
uses: renovatebot/github-action@693b9ef15eec82123529a37c782242f091365961 # v46.1.14
with:
# Fine-grained PAT scoped repo:read+write on co-cddo/ndx_try_aws_scenarios only.
# Minted by the operator per docs/smoke-test-account-setup.md →
# Operational Notes → RENOVATE_TOKEN rotation.
token: ${{ secrets.RENOVATE_TOKEN }}
configurationFile: renovate.json
env:
LOG_LEVEL: ${{ inputs.logLevel || 'info' }}
RENOVATE_PLATFORM: github
RENOVATE_REPOSITORIES: '["co-cddo/ndx_try_aws_scenarios"]'
# Keep Renovate's onboarding off; renovate.json is the committed config.
RENOVATE_ONBOARDING: 'false'
RENOVATE_REQUIRE_CONFIG: 'required'
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
# cp scripts/seed_sample_data.rb bops-src/scripts/
# cp scripts/seed-entrypoint.sh bops-src/scripts/
# cp entrypoint.sh bops-src/
# docker build -f bops-src/Dockerfile.production -t bops:latest bops-src/
# docker build -f bops-src/Dockerfile.production -t bops-local bops-src/
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export class DigitalPlanningRegisterStack extends cdk.Stack {
// CloudFormation parameter for Docker image URI
const imageUriParam = new cdk.CfnParameter(this, 'ImageUri', {
type: 'String',
default: 'ghcr.io/co-cddo/ndx_try_aws_scenarios-dpr:latest',
default: 'ghcr.io/co-cddo/ndx_try_aws_scenarios-dpr:sha-33e9e9f@sha256:775db3c01e2cb01302078b1e2e9129423016ec8c4dc2000f3c35066e2912de35',
description: 'Docker image URI for the Digital Planning Register container',
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export class ComputeConstruct extends Construct {

// Main FixMyStreet container (Perl/Catalyst app on port 9000)
const fmsContainer = this.taskDefinition.addContainer('fixmystreet', {
image: ecs.ContainerImage.fromRegistry('ghcr.io/co-cddo/ndx_try_aws_scenarios-fixmystreet:latest'),
image: ecs.ContainerImage.fromRegistry('ghcr.io/co-cddo/ndx_try_aws_scenarios-fixmystreet:sha-be035a6@sha256:863c3e7dded6d2132663b9e46725bc4f46e934c8ce86b3977a13ade45d986e94'),
logging: ecs.LogDrivers.awsLogs({
logGroup: this.logGroup,
streamPrefix: 'fms',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ export class ComputeConstruct extends Construct {

// Add container - pull from GitHub Container Registry
const container = taskDefinition.addContainer('drupal', {
image: ecs.ContainerImage.fromRegistry('ghcr.io/co-cddo/ndx_try_aws_scenarios-localgov_drupal:latest'),
image: ecs.ContainerImage.fromRegistry('ghcr.io/co-cddo/ndx_try_aws_scenarios-localgov_drupal:sha-5801fb7@sha256:e91947e3eebc50d408921367069d6e4046a6e61f94521e19c6b0b55a5773e5d0'),
logging: ecs.LogDrivers.awsLogs({
logGroup: this.logGroup,
streamPrefix: 'drupal',
Expand Down
2 changes: 1 addition & 1 deletion cloudformation/scenarios/localgov-drupal/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,7 @@ Resources:
Retries: 5
StartPeriod: 300
Timeout: 10
Image: ghcr.io/co-cddo/ndx_try_aws_scenarios-localgov_drupal:latest
Image: ghcr.io/co-cddo/ndx_try_aws_scenarios-localgov_drupal:sha-5801fb7@sha256:e91947e3eebc50d408921367069d6e4046a6e61f94521e19c6b0b55a5773e5d0
LogConfiguration:
LogDriver: awslogs
Options:
Expand Down
10 changes: 6 additions & 4 deletions cloudformation/scenarios/minute/cdk/lib/constructs/compute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import * as servicediscovery from 'aws-cdk-lib/aws-servicediscovery';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import { Construct } from 'constructs';

// GHCR public images (built by .github/workflows/docker-build-minute.yml)
const FRONTEND_IMAGE = 'ghcr.io/co-cddo/ndx_try_aws_scenarios-minute_frontend:latest';
const BACKEND_IMAGE = 'ghcr.io/co-cddo/ndx_try_aws_scenarios-minute_backend:latest';
const WORKER_IMAGE = 'ghcr.io/co-cddo/ndx_try_aws_scenarios-minute_worker:latest';
// GHCR public images (built by .github/workflows/docker-build-minute.yml).
// Pins follow the spec's "own GHCR" pattern: <repo>:sha-<7chars>@sha256:<digest>.
// Renovate tracks both via the regex in renovate.json.
const FRONTEND_IMAGE = 'ghcr.io/co-cddo/ndx_try_aws_scenarios-minute_frontend:sha-5d3d423@sha256:0cfbf3bca86f2360935765dc5ae33e9cbcc88d96ad2d58fd5c9d0a5b99862abf';
const BACKEND_IMAGE = 'ghcr.io/co-cddo/ndx_try_aws_scenarios-minute_backend:sha-5d3d423@sha256:0830ab1fe636764380c0eb2ea56530abfff6658a694f3550f9dda2eddb48517b';
const WORKER_IMAGE = 'ghcr.io/co-cddo/ndx_try_aws_scenarios-minute_worker:sha-5d3d423@sha256:13d7800495c7268cd75170649025e6a7f98bf12cdd2e87cbdab5ddbef5d76a65';

export interface ComputeConstructProps {
readonly vpc: ec2.IVpc;
Expand Down
1 change: 0 additions & 1 deletion cloudformation/scenarios/minute/template.json

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export class ComputeConstruct extends Construct {
);

const tikaContainer = this.taskDefinition.addContainer('tika', {
image: ecs.ContainerImage.fromRegistry('docker.io/apache/tika:latest'),
image: ecs.ContainerImage.fromRegistry('docker.io/apache/tika:3.3.0.0-full@sha256:ecdd37e204308266b1f8e28569f8516ebd5b96d7a4518a71d3904710b20c03b3'),
essential: true,
logging: ecs.LogDrivers.awsLogs({ logGroup: this.logGroup, streamPrefix: 'tika' }),
portMappings: [{ containerPort: 9998, protocol: ecs.Protocol.TCP }],
Expand All @@ -188,7 +188,7 @@ export class ComputeConstruct extends Construct {
const dbPass = props.databaseSecret.secretValueFromJson('password').unsafeUnwrap();

const paperlessContainer = this.taskDefinition.addContainer('paperless', {
image: ecs.ContainerImage.fromRegistry('ghcr.io/paperless-ngx/paperless-ngx:latest'),
image: ecs.ContainerImage.fromRegistry('ghcr.io/paperless-ngx/paperless-ngx:2.9@sha256:948dc7297df8259bffac23e564a7ca688bfc8f04fed9113e7fb14f6030da63dd'),
essential: true,
logging: ecs.LogDrivers.awsLogs({ logGroup: this.logGroup, streamPrefix: 'paperless' }),
portMappings: [{ containerPort: 8000, protocol: ecs.Protocol.TCP }],
Expand Down
8 changes: 4 additions & 4 deletions cloudformation/scenarios/planx/cdk/lib/constructs/compute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export class ComputeConstruct extends Construct {
// 3. Pre-creates extensions (postgis, pgcrypto, fuzzystrmatch, pg_cron, etc.)
// 4. Then runs the standard Hasura cli-migrations entrypoint
hasuraTaskDef.addContainer('hasura-engine', {
image: ecs.ContainerImage.fromRegistry(`${ghcrPrefix}-hasura:latest`),
image: ecs.ContainerImage.fromRegistry('ghcr.io/co-cddo/ndx_try_aws_scenarios-planx-hasura:sha-e748ef5@sha256:0d81caa04dccbbc890a589e709eb0d98c727b64768f34c95185137a05d768c8b'),
logging: ecs.LogDrivers.awsLogs({ logGroup, streamPrefix: 'hasura' }),
environment: {
HASURA_GRAPHQL_DATABASE_URL: databaseUrl,
Expand Down Expand Up @@ -209,7 +209,7 @@ export class ComputeConstruct extends Construct {
].join(' && ');

apiTaskDef.addContainer('api', {
image: ecs.ContainerImage.fromRegistry(`${ghcrPrefix}-api:latest`),
image: ecs.ContainerImage.fromRegistry('ghcr.io/co-cddo/ndx_try_aws_scenarios-planx-api:sha-e748ef5@sha256:9f765c0130675218066d11178b2dc7275cd8c1f8916af5583c25ddbb9e03bd79'),
logging: ecs.LogDrivers.awsLogs({ logGroup, streamPrefix: 'api' }),
environment: {
...sharedEnv,
Expand Down Expand Up @@ -301,7 +301,7 @@ export class ComputeConstruct extends Construct {
});

sharedbTaskDef.addContainer('sharedb', {
image: ecs.ContainerImage.fromRegistry(`${ghcrPrefix}-sharedb:latest`),
image: ecs.ContainerImage.fromRegistry('ghcr.io/co-cddo/ndx_try_aws_scenarios-planx-sharedb:sha-e748ef5@sha256:e998deeb6246e92568a2993e4e3dd5579edad77ef26bcc9e7c131606211b4c03'),
logging: ecs.LogDrivers.awsLogs({ logGroup, streamPrefix: 'sharedb' }),
environment: {
...sharedEnv,
Expand Down Expand Up @@ -350,7 +350,7 @@ export class ComputeConstruct extends Construct {
});

editorTaskDef.addContainer('editor', {
image: ecs.ContainerImage.fromRegistry(`${ghcrPrefix}-editor:latest`),
image: ecs.ContainerImage.fromRegistry('ghcr.io/co-cddo/ndx_try_aws_scenarios-planx-editor:sha-e748ef5@sha256:99212cef72aa68c8119e387409e3ae8f37087a36d47128487c8e1b02cd5d8d8b'),
logging: ecs.LogDrivers.awsLogs({ logGroup, streamPrefix: 'editor' }),
environment: {
// Editor SPA uses relative paths for API/Hasura and window.location.host for WebSockets
Expand Down
113 changes: 113 additions & 0 deletions renovate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended",
":dependencyDashboard",
":semanticCommits"
],
"timezone": "Europe/London",
"platform": "github",
"labels": ["renovate"],
"osvVulnerabilityAlerts": true,
"vulnerabilityAlerts": {
"labels": ["security", "security-priority"],
"groupName": "security-priority",
"schedule": ["at any time"],
"minimumReleaseAge": null
},
"rangeStrategy": "bump",
"configMigration": true,
"ignorePaths": [
"**/node_modules/**",
"**/cdk.out/**",
"**/.aws-sam/**",
"**/dist/**",
"**/.upstream/**"
],
"customManagers": [
{
"customType": "regex",
"description": "Pin GHCR + docker.io image references in CDK TypeScript and raw CFN templates. Renovate's built-in docker manager does not cover ecs.ContainerImage.fromRegistry() string literals; this manager does.",
"fileMatch": [
"^cloudformation/scenarios/.*\\.(ts|yaml|yml|json)$"
],
"matchStrings": [
"(?<depName>(?:ghcr\\.io|docker\\.io)/[a-z0-9._/-]+):(?<currentValue>[a-z0-9.\\-]+)@(?<currentDigest>sha256:[a-f0-9]+)"
],
"datasourceTemplate": "docker",
"versioningTemplate": "docker"
}
],
"packageRules": [
{
"description": "Pin discipline: NEVER replace a digest with a bare tag; updates must carry both.",
"matchCustomManagers": ["custom.regex"],
"pinDigests": true
},
{
"description": "Own GHCR images — one PR per scenario; immediate when an image bumps. Smoke runs scoped to that scenario give fast feedback.",
"groupName": "scenario-{{packageName}}",
"matchCustomManagers": ["custom.regex"],
"matchPackagePatterns": [
"^ghcr\\.io/co-cddo/ndx_try_aws_scenarios-"
],
"schedule": ["at any time"]
},
{
"description": "Upstream container deps (tika, paperless-ngx, gotenberg). Weekly grouped per image to keep blast radius small.",
"groupName": "upstream-{{packageName}}",
"matchCustomManagers": ["custom.regex"],
"matchPackagePatterns": [
"^docker\\.io/apache/tika",
"^docker\\.io/gotenberg/gotenberg",
"^ghcr\\.io/paperless-ngx/paperless-ngx"
],
"schedule": ["before 09:00 on monday"]
},
{
"description": "npm dev deps — weekly batched. Low-risk; noise control.",
"matchManagers": ["npm"],
"matchDepTypes": ["devDependencies"],
"groupName": "npm-dev",
"schedule": ["before 09:00 on monday"]
},
{
"description": "npm prod deps — weekly batched. Higher risk; smoke gates the merge.",
"matchManagers": ["npm"],
"matchDepTypes": ["dependencies"],
"groupName": "npm-prod",
"schedule": ["before 09:00 on monday"]
},
{
"description": "Drupal composer deps. Same cadence as npm-prod.",
"matchManagers": ["composer"],
"groupName": "composer",
"schedule": ["before 09:00 on monday"]
},
{
"description": "GitHub Actions — workflow action references. Weekly batched; action bumps rarely break. pinDigests scoped to OUR workflows; third-party actions in docker-build scripts (renovatebot/github-action etc.) keep their explicit digest pins because the workflow author already chose them.",
"matchManagers": ["github-actions"],
"matchFileNames": [".github/workflows/*"],
"groupName": "github-actions",
"schedule": ["before 09:00 on monday"]
},
{
"description": "Pin official actions/* and aws-actions/* references in workflows to digest. Other action sources (community / vendor-specific) keep their existing pin shape — pinning everything caused a firehose in past adoption.",
"matchManagers": ["github-actions"],
"matchPackagePatterns": [
"^actions/",
"^aws-actions/"
],
"pinDigests": true
},
{
"description": "Python pip Lambda layer deps — batched weekly with npm-dev cadence.",
"matchManagers": ["pip_requirements", "pip-compile"],
"groupName": "pip",
"schedule": ["before 09:00 on monday"]
}
],
"prConcurrentLimit": 6,
"prHourlyLimit": 4,
"branchConcurrentLimit": 12
}
Loading