Strategic Plan & GitLab Migration
Long-term management strategy for the AIMS platform — covering repo structure, integrated apps architecture, the GitHub-to-GitLab migration, and team collaboration protocols.
Assessment of the current repositories under africaone-dev on GitHub before migration.
| Repo | Purpose | Assessment |
|---|---|---|
aims | Tenant dashboard (Next.js + Django) | ✓ Well-structured. Keep as-is. |
aims-core | Central platform (Next.js + Django) | ✓ Well-structured. Keep as-is. |
aims-apps / external-apps | Shared HTML apps + brand assets | Two remotes — consolidated to aims-apps. Remove external-apps remote. |
admindash | Platform admin (Django) | ✓ Clean separation. Keep as-is. |
aimsgo-argocd-apps | GitOps/K8s config | Renamed to infra on GitLab. GitHub-specific CI must be migrated. |
aimsgo-docs | Documentation site | ✓ Migrate as docs. Add description and topics. |
aims-apps repo previously had two remotes locally (external-apps and aims-apps). Standardized to a single remote pointing to GitLab aims/apps.All 5 repos have been pushed to the aims group at africaone.dev.
africaone.dev/aims/ (group: AIMS Platform — private) ├── core ← aims-core (central platform) ├── tenant ← aims (tenant dashboard) ├── apps ← aims-apps (shared HTML apps + assets) ├── admin ← admindash (platform admin) ├── infra ← aimsgo-argocd-apps (GitOps/K8s) └── docs ← aimsgo-docs (documentation)
Why this structure works
- All repos under one private group — single access control point
- Short, clear names — no repetitive
aimsgo-prefix - Group-level CI/CD variables shared across all repos
- GitLab Container Registry available per project automatically
- Group-level branch protection enforced for all repos
Configure at group level
- CI/CD variables:
OBJECT_STORAGE_*,RESEND_API_KEY - Protected branches:
main→ require MR + approval - Group deploy token for ArgoCD read access
- Shared GitLab Runner for all build jobs
- Add Dmitry as Maintainer at group level
AIMS is expanding with custom integrated apps: HR, Calendar, Template Studio, Library, Finance, Comms Hub, Guardian Portal, Clinic, and more. These live as HTML apps in aims-apps/ and as Django modules in aims/backend/.
Fundamental to every school and tightly integrated with core data. These stay as Django modules in aims/backend/ and as sections of the main dashboard. No separation needed.
Deeper functionality that could optionally be enabled per school. Keep as Django modules + aims-apps HTML surfaces, but ensure each can be toggled per tenant. Future: could be licensed separately.
features_enabled JSON field to the School model in core DB. Each Django app checks if it is enabled for the tenant before responding to requests.Accessed by people outside the school (parents, guardians, applicants). Different auth requirements and security surface. Consider deploying as separate K8s services in the future.
portal.{tenant}.aimsgo.com as a separate lightweight Next.js app. Keep backend APIs in the same Django instance but expose only portal-specific endpoints publicly.Development Conventions
| Concern | Convention |
|---|---|
| New Django app | One folder in aims/backend/. Register in INSTALLED_APPS, add endpoints under /api/{app}/. |
| New aims-apps surface | One directory in aims-apps/. Uses brand-assets/aims-shell.css for consistent styling. |
| API versioning | Prefix all new endpoints with /api/v1/ to allow future versioning without breaking clients. |
| Feature flags | Check school.features_enabled at the API level. Never expose data from disabled modules. |
| Migrations | Each Django app manages its own migrations. Never cross-reference tenant DB models in core DB migrations. |
| Permissions | All API views use the rbac module for permission checks. Never hardcode role checks in views. |
- Group
aimsatafricaone.dev/aimscreated ✓ - All 5 projects created and pushed ✓
- Set group description, add team members (Patricia, Yusuf, Dmitry)
- Configure group-level CI/CD variables
aims/core— main branch ✓aims/tenant— main branch ✓aims/apps— main branch ✓aims/admin— main branch ✓aims/infra— master + feature branch ✓
Each local repo now has a gitlab remote alongside the original GitHub origin.
git clone https://africaone.dev/aims/core.git aims-core git clone https://africaone.dev/aims/tenant.git aims git clone https://africaone.dev/aims/apps.git aims-apps git clone https://africaone.dev/aims/admin.git admindash git clone https://africaone.dev/aims/infra.git aimsgo-argocd-apps
- Convert GitHub Actions workflows to
.gitlab-ci.yml - Update ArgoCD Application manifests to use GitLab repo URLs
- Add GitLab deploy token to ArgoCD repository credentials
- Switch image pushes from GHCR to GitLab Container Registry
- Update K8s
imagePullSecretto use GitLab registry credentials
- Run full tenant provisioning test on staging
- Verify ArgoCD syncing from GitLab successfully
- Verify GitLab CI builds and pushes to GitLab Registry
- Archive GitHub repos (read-only, 30-day retention)
- Update team with new clone URLs
ArgoCD natively supports GitLab. Two approaches for granting access:
Option A — Deploy Token (Recommended)
Create a GitLab group-level deploy token with read_repository scope. Single credential for all repos in the group.
- GitLab → Group
aims→ Settings → Deploy tokens - Create token: name
argocd-reader, scope:read_repository - Add to ArgoCD repo credentials
Option B — SSH Key
Generate an SSH key pair. Add the public key to GitLab as a group deploy key. Add the private key to ArgoCD.
- Generate:
ssh-keygen -t ed25519 -C "argocd" - Add public key to GitLab group deploy keys
- Add private key to ArgoCD repo credentials
repoURL in ArgoCD manifests causes immediate re-sync. Do not commit this change until GitLab repo is live and ArgoCD credentials are configured. Coordinate with Dmitry.# In root-app.yaml and apps/applicationset.yaml — change: repoURL: https://github.com/africaone-dev/aimsgo-argocd-apps.git # To: repoURL: https://africaone.dev/aims/infra.git
Converting GitHub Actions workflows to GitLab CI pipelines.
| GitHub Actions | GitLab CI Equivalent | Notes |
|---|---|---|
build-and-deploy.yml | .gitlab-ci.yml with build + deploy stages | Push to GitLab Registry instead of GHCR |
tenant-management.yml | GitLab pipeline with when: manual | Same logic, different trigger API |
| GHCR image push | GitLab Registry (registry.africaone.dev/aims/) | Update all image: refs in Helm values |
| GitHub Secrets | GitLab Group CI/CD Variables | Set at group level — inherited by all repos |
stages:
- build
- deploy
variables:
IMAGE_NAME: registry.africaone.dev/aims/core
build:
stage: build
image: docker:24
services:
- docker:24-dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $IMAGE_NAME:$CI_COMMIT_SHA ./frontend
- docker push $IMAGE_NAME:$CI_COMMIT_SHA
- docker tag $IMAGE_NAME:$CI_COMMIT_SHA $IMAGE_NAME:latest
- docker push $IMAGE_NAME:latest
only:
- main
DEVLOG.md
Shared collaboration log at the workspace root and in each repo. Read it before starting work. Add an entry after completing changes. Keeps Patricia's and Yusuf's Claude Code instances in sync.
CLAUDE.md
Workspace instructions for Claude Code. Covers repo map, tech stack, critical rules, and GitLab migration status. Claude reads this automatically at every session start.
Branch Strategy
| Branch | Purpose | Protection |
|---|---|---|
main | Production — what ArgoCD deploys | MR required, no direct push |
dev | Integration — merge feature branches here first | Optional CI required |
feature/* | Feature or bugfix work | Open, delete after merge |
infra/* | Infrastructure changes (infra repo) | Dmitry must review |