Warning, /containers/AGENTS.md is written in an unsupported language. File is not indexed.
0001 # Copilot Agent Instructions for EIC Containers Repository
0002
0003 This file provides comprehensive guidance for GitHub Copilot agents working on the Electron-Ion Collider (EIC) container infrastructure repository.
0004
0005 ## Repository Overview
0006
0007 This repository builds and maintains multi-architecture container images for the EIC scientific software environment using:
0008 - **Docker/OCI** for containerization
0009 - **Spack** for scientific package management
0010 - **GitHub Actions** for CI/CD
0011 - **Multi-stage builds** for efficient layering
0012
0013 The repository produces container images available at:
0014 - `ghcr.io/eic/debian_stable_base` - Base image with compilers and Spack
0015 - `ghcr.io/eic/eic_ci` - Minimal CI environment
0016 - `ghcr.io/eic/eic_xl` - Full development environment
0017
0018 ## Architecture
0019
0020 ### Multi-Stage Build Strategy
0021
0022 The build follows a **two-track approach** (builder and runtime) to ensure efficient builds while producing lightweight images:
0023
0024 **Builder Track:**
0025 1. `builder_concretization_default` - Concretize default Spack environment
0026 2. `builder_installation_default` - Build default packages
0027 3. `builder_concretization_custom` - Concretize custom versions (e.g., specific commits)
0028 4. `builder_installation_custom` - Build custom packages
0029
0030 **Runtime Track:**
0031 1. `runtime_concretization_default` - Copy spack.lock from builder
0032 2. `runtime_installation_default` - Install from buildcache
0033 3. `runtime_concretization_custom` - Copy custom spack.lock
0034 4. `runtime_installation_custom` - Install custom packages from buildcache
0035
0036 The builder track creates binary caches that the runtime track installs from, avoiding expensive builds in the runtime image.
0037
0038 ### Multi-Architecture Support
0039
0040 All images support both `linux/amd64` and `linux/arm64` architectures through parallel builds and manifest creation.
0041
0042 ## Key Files and Structure
0043
0044 ```
0045 .
0046 ├── .github/workflows/
0047 │ ├── build-push.yml # Main CI/CD pipeline
0048 │ ├── docs.yml # Documentation deployment
0049 │ └── mirror.yaml # Mirror synchronization
0050 ├── containers/
0051 │ ├── debian/Dockerfile # Base image with Spack and compilers
0052 │ └── eic/Dockerfile # EIC environment (multi-stage)
0053 ├── spack-environment/
0054 │ ├── packages.yaml # Package versions, variants, and preferences
0055 │ ├── ci/spack.yaml # CI environment spec
0056 │ └── xl/spack.yaml # Full (XL) environment spec
0057 ├── spack.sh # Spack core version and cherry-picks
0058 ├── spack-packages.sh # Spack-packages version and cherry-picks
0059 ├── eic-spack.sh # EIC-spack repository configuration
0060 ├── key4hep-spack.sh # Key4HEP-spack repository configuration
0061 └── docs/ # Documentation (Docsify site)
0062 ```
0063
0064 ## Spack Package Management
0065
0066 ### Repository Hierarchy
0067
0068 Spack package definitions come from multiple repositories with **priority ordering** (highest to lowest):
0069 1. **eic/eic-spack** - EIC-specific packages
0070 2. **key4hep/key4hep-spack** - Key4HEP packages
0071 3. **spack/spack-packages** - Community packages
0072
0073 ### Version Management
0074
0075 - **Default versions** are specified in `spack-environment/packages.yaml`
0076 - **Spack core version** is set in `spack.sh`
0077 - **Cherry-picks** from upstream Spack commits are listed in `spack.sh` and `spack-packages.sh`
0078
0079 ### Adding Package Cherry-Picks
0080
0081 When adding cherry-picks to `spack-packages.sh`:
0082 1. Add the commit hash to the `SPACKPACKAGES_CHERRYPICKS` list
0083 2. Add a descriptive comment line with format: `## [hash]: [description]`
0084
0085 Example:
0086 ```bash
0087 ## 1234567: Add xrootd@5.6.9 version
0088 1234567abcdef1234567abcdef1234567abcdef
0089 ```
0090
0091 ### Package Version Constraints
0092
0093 Use the syntax `@X.Y.Z:X` to restrict packages to major version X series:
0094 ```yaml
0095 fmt:
0096 require:
0097 - '@11.2.0:11' # Requires fmt 11.x series
0098 ```
0099
0100 For open-ended constraints, use `@X.Y.Z:` format.
0101
0102 ### Package Preferences Pattern
0103
0104 The `packages.yaml` uses a **dual pattern** for preferences:
0105 ```yaml
0106 packages:
0107 all:
0108 prefer:
0109 - '%gcc'
0110 - +ipo
0111 require:
0112 - '%gcc'
0113 - any_of: [+ipo, '@:']
0114 ```
0115
0116 This is intentional because:
0117 - `require` entries for `all` are **overwritten** by package-specific requirements
0118 - `prefer` entries are **retained** as weaker preferences even when overridden
0119
0120 ## Building and Testing
0121
0122 ### Local Builds
0123
0124 For local builds, see `docs/building-locally.md`. The recommended approach uses:
0125 ```bash
0126 docker buildx build --target <stage> -f containers/debian/Dockerfile .
0127 docker buildx build --target <stage> -f containers/eic/Dockerfile .
0128 ```
0129
0130 Common stages:
0131 - `builder_concretization_default` - Test concretization only
0132 - `final` - Complete build
0133
0134 ### CI/CD Pipeline
0135
0136 This repository uses **dual CI workflows**: GitHub Actions and GitLab CI (EICweb).
0137
0138 **Important**: Passing GitHub Actions is **necessary but not sufficient**, and vice versa. Both CI systems must pass for changes to be considered validated.
0139
0140 #### GitHub Actions Workflow
0141
0142 The GitHub Actions workflow (`build-push.yml`) runs on:
0143 - **Schedule**: Every 6 hours
0144 - **Push**: To `master` branch
0145 - **Pull Request**: Against `master` branch
0146 - **Manual**: Via workflow_dispatch
0147
0148 Job flow:
0149 1. `env` - Set environment outputs
0150 2. `base` (parallel per-arch) - Build `debian_stable_base`
0151 3. `base-manifest` - Create multi-arch manifest
0152 4. `eic` (parallel per-env and per-arch) - Build `eic_ci` and `eic_xl`
0153 5. `eic-manifest` - Create multi-arch manifests
0154
0155 #### GitLab CI Workflow (EICweb)
0156
0157 The repository is **mirrored to GitLab** at `eicweb.phy.anl.gov/containers/eic_container` (project ID 290). The `mirror.yaml` workflow:
0158 - Syncs all pushes to the GitLab mirror
0159 - Triggers GitLab CI pipeline with context from GitHub (repository, SHA, PR number)
0160 - Reports GitLab CI status back to GitHub as `eicweb/eic_container` status check
0161
0162 The GitLab CI configuration (`.gitlab-ci.yml`) runs similar build jobs but in the GitLab environment with different runner configurations and registry targets.
0163
0164 **Key Differences:**
0165 - GitHub Actions uses fewer parallel jobs (`JOBS: 4`) due to runner limitations
0166 - GitLab CI uses more parallel jobs (`JOBS: 32`) on dedicated hardware
0167 - Both systems push to their respective registries (GitHub Container Registry and GitLab Registry)
0168 - GitLab CI status appears as a separate check on GitHub PRs
0169
0170 ## Coding Conventions
0171
0172 ### Docker/Dockerfile
0173
0174 - Use **BuildKit syntax**: `#syntax=docker/dockerfile:1.10`
0175 - Enable **dockerfile linter checks**: `#check=error=true`
0176 - Use **multi-stage builds** with descriptive stage names
0177 - Leverage **BuildKit mount caches** for apt, ccache, and spack
0178 - Use **heredoc syntax** (`<<EOF`) for multi-line RUN commands
0179 - Set `ARG` before `FROM` for build-time variables
0180 - Always specify **TARGETPLATFORM** for multi-arch awareness
0181
0182 ### Shell Scripts
0183
0184 - Use `set -e` to exit on errors
0185 - Use `set -x` for debugging when needed
0186 - Prefer **heredoc** in Dockerfile RUN commands for readability
0187 - Use **read -r -d '' VAR <<- \---** pattern for multi-line variables in bash
0188
0189 ### YAML Configuration
0190
0191 - **GitLab CI**: Variables should be key-value pairs, not list items
0192 - Use `!reference` in `before_script`/`after_script`/`rules` sections, not in `variables`
0193 - Indent consistently (2 spaces for YAML)
0194
0195 ### Version Tracking
0196
0197 - Update versions in **both** places when applicable:
0198 - `spack-environment/xl/epic/spack.yaml`
0199 - `spack-environment/cuda/epic/spack.yaml`
0200 - Update version files (`*.sh`) for Spack repository changes
0201 - Document version updates in commit messages
0202
0203 ## Security Considerations
0204
0205 - **Never commit secrets** to the repository
0206 - Use GitHub secrets for registry credentials
0207 - Build caches are public; ensure no sensitive data leaks
0208 - Validate external inputs in scripts
0209 - Use specific commit SHAs for external dependencies when security-critical
0210
0211 ## Testing and Validation
0212
0213 ### Spack Environment Testing
0214
0215 When modifying `spack-environment/packages.yaml`:
0216 1. Test concretization: Build `builder_concretization_default` stage
0217 2. Check for duplicate packages (intentionally allowed: `epic`, `llvm`, `py-setuptools`, `py-urllib3`)
0218 3. Verify no unexpected duplicates appear in concretization output
0219
0220 ### Build Testing
0221
0222 - Test both architectures locally if possible (use QEMU for cross-arch)
0223 - Verify buildcache creation and reuse
0224 - Check final image size for unexpected growth
0225 - Validate entrypoint and scripts work correctly
0226
0227 ### CI Validation
0228
0229 - Monitor GitHub Actions workflow runs
0230 - Check build logs for warnings
0231 - Verify multi-arch manifest creation
0232 - Ensure images pushed to correct registries
0233
0234 ## Common Tasks
0235
0236 ### Updating a Package Version
0237
0238 **Scenario 1**: Package updated in upstream Spack after our Spack version upgrade
0239 - Modify `spack-environment/packages.yaml` with new version requirement
0240
0241 **Scenario 2**: Package updated in upstream Spack before our Spack version upgrade
0242 - Add cherry-pick to `spack-packages.sh` with commit hash and comment
0243 - Modify `spack-environment/packages.yaml` with new version requirement
0244
0245 ### Adding a New Package
0246
0247 1. Ensure package is available in one of the Spack repositories (eic-spack, key4hep-spack, or spack-packages)
0248 2. Add to appropriate `spack-environment/*/spack.yaml` specs list
0249 3. Optionally add version/variant preferences to `spack-environment/packages.yaml`
0250
0251 ### Modifying Build Arguments
0252
0253 1. Update ARG defaults in Dockerfile
0254 2. Update environment variables in `.github/workflows/build-push.yml`
0255 3. Update GitLab CI variables in `.gitlab-ci.yml` if mirroring
0256
0257 ### Changing Compiler Versions
0258
0259 Supported distributions and compilers (as of last update):
0260 - **Debian trixie**: GCC-14, Clang-20, Flang-20
0261 - **Ubuntu noble**: GCC-14, Clang-20, Flang-20
0262
0263 Update in `containers/debian/Dockerfile` with version-specific logic.
0264
0265 ## Documentation
0266
0267 - Documentation is built with **Docsify** from `docs/` directory
0268 - Deployed via GitHub Pages through `docs.yml` workflow
0269 - Update relevant documentation when making architectural changes
0270 - Use Mermaid diagrams for visual explanations
0271 - Keep `README.md` updated with major changes
0272
0273 ## Git and GitHub Workflow
0274
0275 ### Branch Naming
0276
0277 - Feature branches: `feature/description`
0278 - Bug fixes: `fix/description`
0279 - Copilot branches: `copilot/*`
0280
0281 ### Commit Messages
0282
0283 - Use conventional commit format when possible: `type(scope): description`
0284 - Examples: `build(deps): bump package`, `feat(spack): add new package`
0285 - Reference issues: `Fixes #123` or `Closes #123`
0286
0287 ### Pull Requests
0288
0289 - Ensure CI passes before merging
0290 - Request review for significant changes
0291 - Update documentation in the same PR as code changes
0292 - Squash commits if many small iterations
0293
0294 ## Buildcache Management
0295
0296 - Buildcache tags follow pattern: `{BUILD_IMAGE}-{GITHUB_REF_POINT_SLUG}-{arch}`
0297 - Tags are automatically cleaned on PR close by cleanup workflows
0298 - Buildcaches stored in GitLab registry at `eicweb.phy.anl.gov` (project ID 290)
0299
0300 ## Additional Resources
0301
0302 - [EIC Software Organization](https://github.com/eic)
0303 - [Spack Documentation](https://spack.readthedocs.io/)
0304 - [Docker BuildKit](https://docs.docker.com/build/buildkit/)
0305 - Internal documentation in `docs/` directory