Skip to content
Merged
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
37 changes: 26 additions & 11 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,44 @@
<!-- SPECKIT START -->
For additional context about technologies to be used, project structure,
shell commands, and edge-case handling details, read specs/002-multiarch-image-cache/plan.md and treat it as the authoritative implementation context.
shell commands, and edge-case handling details, read specs/002-multiarch-image-cache/plan.md
and treat it as the authoritative implementation context.
<!-- SPECKIT END -->

<!-- project-specific instructions start -->

# Instructions

The purpose of this project is to build a Docker container image providing the latest patch release within the Ruby 2.6.x series (intentionally pinned to 2.6, not a newer major version). The 2.6.x pin is a hard requirement.
The purpose of this project is to build a Docker container image providing the latest patch release
within the Ruby 2.6.x series (intentionally pinned to 2.6, not a newer major version). The 2.6.x pin
is a hard requirement.

The image must include the `jemalloc` implementation of `malloc` for improved memory performance. To support
development and testing, the resulting container will be multi-architecture, supporting both
The image must include the `jemalloc` implementation of `malloc` for improved memory performance.
To support development and testing, the resulting container will be multi-architecture, supporting both
`linux/amd64` and `linux/arm64` architectures.

The project will use `dependabot` to keep the pinned versions of Ruby, OpenSSL, and jemalloc up to date.
The project will use `dependabot` to keep the pinned versions of Ruby, OpenSSL, and jemalloc up to
date.

## Docker Specification

The resulting Docker image will be based on the "scratch" image, and have a minimal runtime footprint.
It will use a multi-stage build to limit image contents to only the compiled Ruby binaries and necessary
runtime libraries.
It will use a multi-stage build to limit image contents to only the compiled Ruby binaries, necessary
runtime libraries, and files needed for testing and validating the image.

The `Dockerfile` will be formatted with "here-doc" `RUN` blocks for clarity and maintainability.

## CICD

[registry]: ghcr.io/umnlibraries/ruby2.6-jemalloc-docker

* The CI workflow will be implemented with GitHub Actions, using `Buildx` for multi-architecture
builds and cache management. Buildx cache must use the GitHub Actions cache backend (`type=gha`) with `mode=max` to cache all build layers across workflow runs.
* The workflow must push the final multi-arch manifest to [registry/image:tag]. Tags must include the full Ruby
version (e.g. `2.6.10`) and a `latest` alias for the highest 2.6.x version. The registry credentials will be
* The workflow must push the final multi-arch manifest to [registry]:latest. Tags must include the full Ruby
version (e.g. `2.6.10`) and a `latest` alias for the highest 2.6.x version. The `latest` tag must be updated only
when the image being built carries a Ruby patch version higher than any previously published 2.6.x tag in the
registry; the workflow should derive the Ruby version from build args and compare it against existing registry tags
before deciding to also push `latest`. The registry credentials will be
provided via GitHub Actions secrets named `REGISTRY_USERNAME` and `REGISTRY_PASSWORD`.
* Use the `pre-commit` toolchain for local development to ensure code quality and consistency.

## Version Control

Expand All @@ -39,4 +47,11 @@ The `Dockerfile` will be formatted with "here-doc" `RUN` blocks for clarity and
* Pull requests will be used for all changes, with code review and automated testing before merging.
* Use `dependabot` to keep dependencies up to date.

<!-- project-specific instructions end -->
## Validation

* The project will use the `pre-commit` toolchain for local development to ensure code quality
and consistency.
* A `make lint` target will be used to lint all markdown files in the repository, ensuring
documentation quality.

<!-- project-specific instructions end -->
6 changes: 4 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: Build and publish Docker image

on:
"on":
push:
branches: [main]
pull_request:
Expand Down Expand Up @@ -149,4 +149,6 @@ jobs:

- name: Verify Ruby and jemalloc runtime
run: |
./scripts/verify-ruby-jemalloc.sh "ruby2.6-jemalloc:ci-${{ matrix.arch }}" "${{ matrix.platform }}"
./scripts/verify-ruby-jemalloc.sh \
"ruby2.6-jemalloc:ci-${{ matrix.arch }}" \
"${{ matrix.platform }}"
11 changes: 0 additions & 11 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,3 @@ repos:
hooks:
- id: yamllint
args: [--strict, -c=.yamllint.yml]

# Ansible linter
- repo: https://github.com/ansible/ansible-lint
rev: v26.4.0
hooks:
- id: ansible-lint
name: ansible-lint
description: Run ansible-lint on Ansible files
entry: ansible-lint
language: python
files: \.(yml|yaml)$
245 changes: 243 additions & 2 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@
{
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
},
{
"path": "detect_secrets.filters.common.is_baseline_file",
"filename": ".secrets.baseline"
},
{
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
"min_level": 2
Expand Down Expand Up @@ -122,6 +126,243 @@
"path": "detect_secrets.filters.heuristic.is_templated_secret"
}
],
"results": {},
"generated_at": "2026-06-04T21:06:06Z"
"results": {
".specify/integrations/copilot.manifest.json": [
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "c411fdf15c58e5b80af9cb5e1dbd88cb6f892dfa",
"is_verified": false,
"line_number": 6,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "8d163f350d6bb3293357e2e569c1faefac453204",
"is_verified": false,
"line_number": 7,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "e7b82dfc011fe97ba1148b179afaf7fb70e2aa62",
"is_verified": false,
"line_number": 8,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "717b90528dc337ca4a7b7534ec9b7799bfba1809",
"is_verified": false,
"line_number": 9,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "5b58af287c11f117b71eb112128daad1eb2e281b",
"is_verified": false,
"line_number": 10,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "05018fd2f129d19f907b629f68833056c34ea447",
"is_verified": false,
"line_number": 11,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "ca049b32bb963377ff1506a93f49e31e6487bb09",
"is_verified": false,
"line_number": 12,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "b887e8b2f4e4d500ac956aa7839a977f7e73295e",
"is_verified": false,
"line_number": 13,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "1e9e9555c75851ee3a8bc9bd1cef78f886160848",
"is_verified": false,
"line_number": 14,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "2a18bcff31e5fe30d3456516b5b219353ab86251",
"is_verified": false,
"line_number": 15,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "bcc56203d1b06207d79806f61f00926124bc93f6",
"is_verified": false,
"line_number": 16,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "1bd5808d29f0baf6ccdd8f64a926dd1370cdf3de",
"is_verified": false,
"line_number": 17,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "a7cf10ee7692289db628adc1e8283d0022fa7bac",
"is_verified": false,
"line_number": 18,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "62117cb86f604a29509407c32339f2411e1580e8",
"is_verified": false,
"line_number": 19,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "0970c1a55f879ff3aa7de54153c191a879a13483",
"is_verified": false,
"line_number": 20,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "53c87594c22acf617ae6a0210f6e0df6785bb6da",
"is_verified": false,
"line_number": 21,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "e0620c8016795ec1eb61894aa96a692dc567d935",
"is_verified": false,
"line_number": 22,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "b1533078191b915610220e62f11b4b3ce604d6e0",
"is_verified": false,
"line_number": 23,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/copilot.manifest.json",
"hashed_secret": "3666b0731bcc8efe81cd2eab8a15480465d39bfe",
"is_verified": false,
"line_number": 24,
"is_secret": false
}
],
".specify/integrations/speckit.manifest.json": [
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/speckit.manifest.json",
"hashed_secret": "606979ec481dce48794c78b983ed49f775e4fd44",
"is_verified": false,
"line_number": 6,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/speckit.manifest.json",
"hashed_secret": "643cb98b17fa3813e10afaa7ed5af5d334da85d2",
"is_verified": false,
"line_number": 7,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/speckit.manifest.json",
"hashed_secret": "ddd6844f6a7c3ee5f7e6dd51eded83db3567faba",
"is_verified": false,
"line_number": 8,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/speckit.manifest.json",
"hashed_secret": "246bc69bc522df923194fe62fc2ef6f4cf157bfe",
"is_verified": false,
"line_number": 9,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/speckit.manifest.json",
"hashed_secret": "bb8d6742113eef5d976133e844c73d4389aa4d5c",
"is_verified": false,
"line_number": 10,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/speckit.manifest.json",
"hashed_secret": "ecde51343aeae413aaba7dc0a5eb327c83bdd97f",
"is_verified": false,
"line_number": 11,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/speckit.manifest.json",
"hashed_secret": "25c4a42ae4038007ad01f74d7e01a9d3352ef6ce",
"is_verified": false,
"line_number": 12,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/speckit.manifest.json",
"hashed_secret": "6c481bf584ec89fe5868814e71db48013022ff8e",
"is_verified": false,
"line_number": 13,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/speckit.manifest.json",
"hashed_secret": "9ca09f61b0fce77137bb336a5537503f9f28be91",
"is_verified": false,
"line_number": 14,
"is_secret": false
},
{
"type": "Hex High Entropy String",
"filename": ".specify/integrations/speckit.manifest.json",
"hashed_secret": "5a2c5ffb2fa4fb14d9cc8098f9aff3769a5f0894",
"is_verified": false,
"line_number": 15,
"is_secret": false
}
]
},
"generated_at": "2026-06-10T17:35:52Z"
}
Loading
Loading