Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
505850b
Add production deployment configuration and CI/CD
cooper667 Jan 22, 2026
d212819
Update submodules to commits that exist in remotes
cooper667 Jan 22, 2026
ef26689
Update staging domain to dev.adr.fjelltopp.org
cooper667 Jan 26, 2026
e320355
Update staging domain to dev-adr.fjelltopp.org
cooper667 Jan 27, 2026
212cd3d
fix(submodules): update ckanext-unaids with CSRF token fix for file u…
cooper667 Jan 30, 2026
537d89e
docs(config): update CSRF comments now that FileUploader sends token
cooper667 Jan 30, 2026
86c34ec
fix(submodules): update ckanext-blob-storage with datapusher route fix
cooper667 Jan 30, 2026
55d9136
fix(submodules): update ckanext-blob-storage with trailing slash fix
cooper667 Jan 30, 2026
e01ec91
feat: Enable SAML2 Auth0 login on dev.adr.fjelltopp.org
cooper667 Jan 31, 2026
4e1289e
fix(docker): use deploy/production.ini for CKAN config
cooper667 Feb 1, 2026
338f36e
fix(saml): use correct Auth0 client ID for dev.adr.fjelltopp.org
cooper667 Feb 1, 2026
92405e9
fix(saml): use correct Auth0 tenant (dev-udfgla0l)
cooper667 Feb 1, 2026
f0016dc
refactor(config): use base.ini + secrets.ini → production.ini
cooper667 Feb 1, 2026
21d7e3b
refactor(config): split into base.ini + env.ini + secrets.ini
cooper667 Feb 1, 2026
c0ad19a
fix(submodules): revert ckanext-unaids to upstream fjelltopp repo
cooper667 Feb 2, 2026
e67b5be
fix(saml): use correct Auth0 name claim URI
cooper667 Feb 3, 2026
6348fdf
chore: update ckanext-blob-storage submodule
cooper667 Feb 3, 2026
8fe251f
chore: update ckanext-blob-storage submodule to 3335f65
cooper667 Feb 3, 2026
1590bb4
Merge branch 'ckan211-python310-migration-staging-1' into ckan211-pro…
cooper667 Feb 5, 2026
8765d8b
wip: hopefully brings the configs in line
ChasNelson1990 Feb 5, 2026
54802f9
Merge branch 'ckan211-prod-deploy-pr' of github.com:fjelltopp/adx_dev…
cooper667 Feb 6, 2026
d693ca2
correct ckan ini file
cooper667 Feb 6, 2026
1f84515
Fix duplicate ckan.resource_formats in base.ini
cooper667 Feb 6, 2026
2314ced
Remove unavailable officedocs_view plugin from plugins list
cooper667 Feb 6, 2026
b4759f1
Disable email_to to avoid CKAN 2.11 startup crash
cooper667 Feb 6, 2026
f630d95
Prevent Front Door from caching dynamic/error responses
cooper667 Feb 6, 2026
a92f4d7
Bump ckanext-scheming to fix hardcoded resource URLs
cooper667 Feb 7, 2026
b30ef3c
Bump ckanext-validation to fix CKAN 2.11 compatibility
cooper667 Feb 8, 2026
b67a917
Update ckanext-harvest and ckanext-dhis2harvester submodules
A-Souhei Feb 8, 2026
c028c3b
Fix supervisor worker paths for prod virtualenv and config
cooper667 Feb 12, 2026
362d426
Fix supervisor logging to use /dev/stdout instead of /dev/fd/1
cooper667 Feb 13, 2026
fa0c256
Bump ckanext-dhis2harvester with Python 3 compatibility fixes
cooper667 Feb 14, 2026
d2a65b9
Update ckanext-unaids: fix numpy/pandas compatibility for Python 3.10
A-Souhei Feb 19, 2026
16dfd16
Fix ckan-worker crash by running as root user
cooper667 Feb 20, 2026
d5d98b1
Add SMTP config for staging via Azure Communication Services
cooper667 Mar 4, 2026
953b97d
chore: bump submodules, add Solr rebuild script, and minor dev toolin…
A-Souhei Mar 16, 2026
94e1df0
chore: bump ckanext-unaids (Download All fixes + XSS hardening)
A-Souhei Mar 16, 2026
ee4bbc7
fix: Bump ckanext-unaids to fix Download All on staging
A-Souhei Mar 17, 2026
63bd123
chore: bump ckanext-unaids to 78f93c5
A-Souhei Apr 10, 2026
82bc772
ci: add manual workflow to rebuild Solr index
cooper667 Apr 10, 2026
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
10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
groups:
actions:
patterns:
- "*"
132 changes: 132 additions & 0 deletions .github/workflows/build-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: Build and Deploy CKAN

on:
push:
branches: [master, ckan211-prod-deploy-pr]
tags: ["v*"]
workflow_dispatch:
inputs:
image_tag:
description: "Image tag to deploy (e.g., sha-abc1234 or v1.0.0)"
required: true
type: string
environment:
description: "Target environment"
required: true
type: choice
options:
- staging
- production

env:
ACR_NAME: adracr
IMAGE_NAME: ckan

jobs:
build:
if: github.event_name != 'workflow_dispatch'
runs-on: ubuntu-latest
outputs:
image_tag: ${{ steps.set-env.outputs.image_tag }}
environment: ${{ steps.set-env.outputs.environment }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
submodules: recursive

- name: Determine environment and image tag
id: set-env
run: |
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
echo "environment=production" >> $GITHUB_OUTPUT
echo "image_tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT
else
echo "environment=staging" >> $GITHUB_OUTPUT
echo "image_tag=sha-$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT
fi

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Docker meta
id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.6.1
with:
images: ${{ env.ACR_NAME }}.azurecr.io/${{ env.IMAGE_NAME }}
tags: |
type=sha
type=ref,event=tag

- name: Login to ACR
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
registry: ${{ env.ACR_NAME }}.azurecr.io
username: ${{ secrets.ACR_USERNAME }}
password: ${{ secrets.ACR_PASSWORD }}

- name: Build and push
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.10.0
with:
context: .
file: deploy/Dockerfile.prod
push: true
cache-from: type=gha
cache-to: type=gha,mode=max
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

deploy:
if: always() && (needs.build.result == 'success' || github.event_name == 'workflow_dispatch')
needs: build
runs-on: ubuntu-latest
environment:
name: ${{ github.event_name == 'workflow_dispatch' && inputs.environment || needs.build.outputs.environment }}
url: ${{ steps.params.outputs.url }}
steps:
- name: Set deploy params
id: params
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
ENV="${{ inputs.environment }}"
echo "image_tag=${{ inputs.image_tag }}" >> $GITHUB_OUTPUT
else
ENV="${{ needs.build.outputs.environment }}"
echo "image_tag=${{ needs.build.outputs.image_tag }}" >> $GITHUB_OUTPUT
fi

if [[ "$ENV" == "production" ]]; then
echo "namespace=adr-p" >> $GITHUB_OUTPUT
echo "url=https://adr-p.fjelltopp.org" >> $GITHUB_OUTPUT
else
echo "namespace=adr-s" >> $GITHUB_OUTPUT
echo "url=https://dev.adr.fjelltopp.org" >> $GITHUB_OUTPUT
fi

- name: Setup kubeconfig
run: |
mkdir -p ~/.kube
echo "${{ secrets.KUBECONFIG_BASE64 }}" | base64 -d > ~/.kube/config
chmod 600 ~/.kube/config

- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Deploy to AKS
run: |
# Determine env config file
if [[ "${{ steps.params.outputs.namespace }}" == "adr-p" ]]; then
ENV_CONFIG="deploy/production.ini"
else
ENV_CONFIG="deploy/staging.ini"
fi

# Create/update env ConfigMap
kubectl create configmap ckan-env-config \
--from-file=env.ini=$ENV_CONFIG \
-n ${{ steps.params.outputs.namespace }} \
--dry-run=client -o yaml | kubectl apply -f -

# Update image
kubectl set image deployment/ckan \
ckan=${{ env.ACR_NAME }}.azurecr.io/${{ env.IMAGE_NAME }}:${{ steps.params.outputs.image_tag }} \
-n ${{ steps.params.outputs.namespace }}
kubectl rollout status deployment/ckan -n ${{ steps.params.outputs.namespace }} --timeout=5m
38 changes: 38 additions & 0 deletions .github/workflows/reindex-solr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Rebuild Solr Index

on:
workflow_dispatch:
inputs:
environment:
description: "Target environment"
required: true
type: choice
options:
- staging
- production

jobs:
reindex:
runs-on: ubuntu-latest
environment:
name: ${{ inputs.environment }}
steps:
- name: Set namespace
id: params
run: |
if [[ "${{ inputs.environment }}" == "production" ]]; then
echo "namespace=adr-p" >> $GITHUB_OUTPUT
else
echo "namespace=adr-s" >> $GITHUB_OUTPUT
fi

- name: Setup kubeconfig
run: |
mkdir -p ~/.kube
echo "${{ secrets.KUBECONFIG_BASE64 }}" | base64 -d > ~/.kube/config
chmod 600 ~/.kube/config

- name: Rebuild Solr index
run: |
kubectl exec deployment/ckan -n ${{ steps.params.outputs.namespace }} -- \
ckan -c /tmp/production.ini search-index rebuild -i -q
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,7 @@ src/
# Hide translation .po file copies
build/translations/*
demo_venv/

# Local configuration and utility scripts (for personal use)
.vuhitra/
rebuild_solr_index.sh
2 changes: 2 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,5 @@
[submodule "submodules/ckanext-geoview"]
path = submodules/ckanext-geoview
url = https://github.com/ckan/ckanext-geoview.git
[submodule "submodules/ckanext-unaids"]
url = git@github.com:/fjelltopp/ckanext-unaids.git
56 changes: 42 additions & 14 deletions ckan/ckan_supervisor.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ file=/tmp/supervisor.sock

[supervisord]
nodaemon=true
logfile=/dev/fd/1
logfile=/dev/stdout
logfile_maxbytes=0
pidfile=/tmp/supervisord.pid

Expand All @@ -17,41 +17,41 @@ serverurl=unix:///tmp/supervisor.sock
; ===============================
[program:ckan_gather_consumer]

command=/usr/local/bin/ckan --config=/etc/ckan/ckan.ini harvester gather-consumer
command=%(ENV_CKAN_VENV)s/bin/ckan --config=%(ENV_CONFIG)s harvester gather-consumer

; user that owns virtual environment.
user=root

stdout_logfile=/dev/fd/1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/fd/2
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autostart=true
autorestart=true

[program:ckan_fetch_consumer]

command=/usr/local/bin/ckan --config=/etc/ckan/ckan.ini harvester fetch-consumer
command=%(ENV_CKAN_VENV)s/bin/ckan --config=%(ENV_CONFIG)s harvester fetch-consumer

; user that owns virtual environment.
user=root

stdout_logfile=/dev/fd/1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/fd/2
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autostart=true
autorestart=true

[program:ckan_harvester_run]

command=/bin/bash -c "sleep 2m && /usr/local/bin/ckan --config=/etc/ckan/ckan.ini harvester run "
command=/bin/bash -c "sleep 2m && %(ENV_CKAN_VENV)s/bin/ckan --config=%(ENV_CONFIG)s harvester run "
; user that owns virtual environment.
user=root

stdout_logfile=/dev/fd/1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/fd/2
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autostart=true
autorestart=true
Expand All @@ -63,11 +63,11 @@ autorestart=true
[program:ckan-worker]

; Use the full paths to the virtualenv and your configuration file here.
command=/usr/local/bin/ckan -c /etc/ckan/ckan.ini jobs worker
command=%(ENV_CKAN_VENV)s/bin/ckan -c %(ENV_CONFIG)s jobs worker


; User the worker runs as.
user=ckan
user=root


; Start just a single worker. Increase this number if you have many or
Expand All @@ -77,9 +77,9 @@ process_name=%(program_name)s-%(process_num)02d


; Log files.
stdout_logfile=/dev/fd/1
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/fd/2
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

; Make sure that the worker is started on system start and automatically
Expand All @@ -95,3 +95,31 @@ startsecs=10
; Need to wait for currently executing tasks to finish at shutdown.
; Increase this if you have very long running tasks.
stopwaitsecs = 600

; ===============================
; nginx reverse proxy
; ===============================
[program:nginx]
command=/usr/sbin/nginx -g "daemon off;"
user=root
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autostart=true
autorestart=true
priority=10

; ===============================
; uWSGI CKAN application
; ===============================
[program:uwsgi]
command=/usr/local/bin/uwsgi --ini /usr/lib/adx/uwsgi.ini
user=root
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autostart=true
autorestart=true
priority=20
Loading
Loading