Skip to content

Commit 282c877

Browse files
[minor] Bundle application releases and harden images
1 parent 914f500 commit 282c877

150 files changed

Lines changed: 3296 additions & 925 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ on:
3434

3535
jobs:
3636
build:
37+
env:
38+
# renovate: datasource=docker depName=moby/buildkit
39+
BUILDKIT_IMAGE: moby/buildkit:v0.31.0@sha256:a095b3d11ce1a9a05b6064ef515dfca0291ec5bcf2ea8178da8f6461924294e1
3740
strategy:
3841
matrix:
3942
runner: [ubuntu-24.04, ubuntu-24.04-arm]
@@ -138,14 +141,14 @@ jobs:
138141
done
139142
}
140143
141-
retry_with_backoff docker pull moby/buildkit:v0.31.0
144+
retry_with_backoff docker pull "${BUILDKIT_IMAGE}"
142145
143146
- name: Set up Docker Buildx
144147
id: buildx
145148
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
146149
with:
147150
driver-opts: |
148-
image=moby/buildkit:v0.31.0
151+
image=${{ env.BUILDKIT_IMAGE }}
149152
network=host
150153
151154
- id: build

.github/workflows/push.yml

Lines changed: 84 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
name: Build and Push Docker Images
22
on:
33
push:
4-
branches: ["*"]
4+
branches: ["**"]
55
paths:
6+
- ".github/workflows/**"
7+
- "ci/**"
8+
- "cmd/**"
9+
- "go.mod"
10+
- "go.sum"
611
- "images/**"
12+
- "internal/**"
13+
- "docker-bake.hcl"
14+
- "Makefile"
715
workflow_dispatch:
816
inputs:
917
image:
@@ -35,7 +43,9 @@ jobs:
3543
- uses: "actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10" # v6
3644

3745
- name: lint
38-
run: shellcheck **/*.sh
46+
run: |
47+
mapfile -d '' scripts < <(git grep -Ilz -E '^#!.*(ba)?sh')
48+
shellcheck "${scripts[@]}"
3949
4050
plan:
4151
runs-on: ubuntu-24.04
@@ -63,6 +73,8 @@ jobs:
6373
sitectl_isle_libops_image_tags: ${{ steps.plan.outputs.sitectl_isle_libops_image_tags }}
6474
sitectl_isle_images: ${{ steps.plan.outputs.sitectl_isle_images }}
6575
sitectl_create_smoke_matrix: ${{ steps.plan.outputs.sitectl_create_smoke_matrix }}
76+
sitectl_repository: ${{ steps.plan.outputs.sitectl_repository }}
77+
sitectl_ref: ${{ steps.plan.outputs.sitectl_ref }}
6678
steps:
6779
- uses: "actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10" # v6
6880
with:
@@ -73,6 +85,9 @@ jobs:
7385
with:
7486
go-version-file: go.mod
7587

88+
- name: Test planner and repository contracts
89+
run: go test -count=1 ./...
90+
7691
- id: plan
7792
name: Plan
7893
env:
@@ -124,6 +139,9 @@ jobs:
124139
local create_args="$3"
125140
local image_tags="$4"
126141
local images="$5"
142+
local local_plugin_repository="${6:-}"
143+
local local_plugin_ref="${7:-main}"
144+
local local_plugin_path="${8:-}"
127145
if [ -z "${image_tags// }" ]; then
128146
return
129147
fi
@@ -134,31 +152,79 @@ jobs:
134152
--arg create_args "$create_args" \
135153
--arg image_tags "$image_tags" \
136154
--arg images "$images" \
155+
--arg local_plugin_repository "$local_plugin_repository" \
156+
--arg local_plugin_ref "$local_plugin_ref" \
157+
--arg local_plugin_path "$local_plugin_path" \
137158
'. + [{
138159
"plugin": $plugin,
139160
"packages": $packages,
140161
"create-args": $create_args,
141162
"image-tags": $image_tags,
142-
"images": $images
163+
"images": $images,
164+
"local-plugin-repository": $local_plugin_repository,
165+
"local-plugin-ref": $local_plugin_ref,
166+
"local-plugin-path": $local_plugin_path
143167
}]' <<<"$smoke_matrix"
144168
)"
145169
}
146170
171+
coordinated_template_args() {
172+
local repository="$1"
173+
local branch="${GITHUB_REF_NAME}"
174+
175+
if [ "${branch}" = "main" ]; then
176+
return
177+
fi
178+
if [[ ! "${branch}" =~ ^[A-Za-z0-9._/-]+$ ]]; then
179+
echo "Skipping coordinated template branch with unsafe ref name: ${branch}" >&2
180+
return
181+
fi
182+
if git ls-remote --exit-code --heads "${repository}" "refs/heads/${branch}" >/dev/null 2>&1; then
183+
printf '%s' "--template-repo ${repository} --template-branch ${branch}"
184+
fi
185+
}
186+
147187
sitectl_wp_image_tags="$(planned_tag_assignment wp wp-php84)"
148188
sitectl_omeka_s_image_tags="$(planned_tag_assignment omeka-s omeka-s-php84)"
149189
sitectl_omeka_classic_image_tags="$(planned_tag_assignment omeka-classic omeka-classic-php84)"
150190
sitectl_ojs_image_tags="$(planned_tag_assignment ojs ojs-php84)"
151191
sitectl_drupal_image_tags="$(planned_tag_assignment drupal drupal-php84)"
152192
sitectl_isle_libops_image_tags="$(planned_tag_assignment drupal islandora-php84)"
153193
sitectl_isle_images=""
194+
sitectl_wp_create_args="$(coordinated_template_args https://github.com/libops/wp)"
195+
sitectl_omeka_s_create_args="$(coordinated_template_args https://github.com/libops/omeka-s)"
196+
sitectl_omeka_classic_create_args="$(coordinated_template_args https://github.com/libops/omeka-classic)"
197+
sitectl_ojs_create_args="$(coordinated_template_args https://github.com/libops/ojs)"
198+
sitectl_drupal_create_args="$(coordinated_template_args https://github.com/libops/drupal)"
199+
sitectl_isle_template_args="$(coordinated_template_args https://github.com/libops/isle)"
200+
if [ -z "${sitectl_isle_template_args}" ]; then
201+
sitectl_isle_template_args="--template-repo https://github.com/libops/isle"
202+
fi
203+
sitectl_isle_create_args="${sitectl_isle_template_args} --fcrepo off --blazegraph off --isle-file-system-uri private --iiif triplet --iiif-topology disabled --bot-mitigation off"
204+
sitectl_repository=""
205+
sitectl_ref="main"
206+
if [ -n "$(coordinated_template_args https://github.com/libops/sitectl)" ]; then
207+
sitectl_repository="libops/sitectl"
208+
sitectl_ref="${GITHUB_REF_NAME}"
209+
fi
210+
sitectl_isle_packages="sitectl sitectl-isle sitectl-drupal"
211+
sitectl_isle_plugin_repository=""
212+
sitectl_isle_plugin_ref="main"
213+
sitectl_isle_plugin_path=""
214+
if [ -n "$(coordinated_template_args https://github.com/libops/sitectl-isle)" ]; then
215+
sitectl_isle_packages="sitectl sitectl-drupal"
216+
sitectl_isle_plugin_repository="libops/sitectl-isle"
217+
sitectl_isle_plugin_ref="${GITHUB_REF_NAME}"
218+
sitectl_isle_plugin_path="sitectl-isle-source"
219+
fi
154220
155221
smoke_matrix='[]'
156-
add_smoke_row "wp" "sitectl sitectl-wp" "" "$sitectl_wp_image_tags" ""
157-
add_smoke_row "omeka-s" "sitectl sitectl-omeka-s" "" "$sitectl_omeka_s_image_tags" ""
158-
add_smoke_row "omeka-classic" "sitectl sitectl-omeka-classic" "" "$sitectl_omeka_classic_image_tags" ""
159-
add_smoke_row "ojs" "sitectl sitectl-ojs" "" "$sitectl_ojs_image_tags" ""
160-
add_smoke_row "drupal" "sitectl sitectl-drupal" "" "$sitectl_drupal_image_tags" ""
161-
add_smoke_row "isle" "sitectl sitectl-isle sitectl-drupal" "--template-repo https://github.com/libops/isle --fcrepo off --blazegraph off --isle-file-system-uri private --iiif triplet --iiif-topology disabled --bot-mitigation off" "$sitectl_isle_libops_image_tags" "$sitectl_isle_images"
222+
add_smoke_row "wp" "sitectl sitectl-wp" "$sitectl_wp_create_args" "$sitectl_wp_image_tags" ""
223+
add_smoke_row "omeka-s" "sitectl sitectl-omeka-s" "$sitectl_omeka_s_create_args" "$sitectl_omeka_s_image_tags" ""
224+
add_smoke_row "omeka-classic" "sitectl sitectl-omeka-classic" "$sitectl_omeka_classic_create_args" "$sitectl_omeka_classic_image_tags" ""
225+
add_smoke_row "ojs" "sitectl sitectl-ojs" "$sitectl_ojs_create_args" "$sitectl_ojs_image_tags" ""
226+
add_smoke_row "drupal" "sitectl sitectl-drupal" "$sitectl_drupal_create_args" "$sitectl_drupal_image_tags" ""
227+
add_smoke_row "isle" "$sitectl_isle_packages" "$sitectl_isle_create_args" "$sitectl_isle_libops_image_tags" "$sitectl_isle_images" "$sitectl_isle_plugin_repository" "$sitectl_isle_plugin_ref" "$sitectl_isle_plugin_path"
162228
163229
{
164230
echo "sitectl_wp_image_tags=${sitectl_wp_image_tags}"
@@ -169,6 +235,8 @@ jobs:
169235
echo "sitectl_isle_libops_image_tags=${sitectl_isle_libops_image_tags}"
170236
echo "sitectl_isle_images=${sitectl_isle_images}"
171237
echo "sitectl_create_smoke_matrix=${smoke_matrix}"
238+
echo "sitectl_repository=${sitectl_repository}"
239+
echo "sitectl_ref=${sitectl_ref}"
172240
} >> "$GITHUB_OUTPUT"
173241
174242
- name: Summary
@@ -375,13 +443,13 @@ jobs:
375443

376444
sitectl-create-smoke-test:
377445
if: ${{ always() && needs.plan.outputs.sitectl_create_smoke_matrix != '[]' && !cancelled() && !failure() }}
378-
needs: [plan, test-level-4]
446+
needs: [plan, test-level-0, test-level-1, test-level-2, test-level-3, test-level-4]
379447
strategy:
380448
fail-fast: false
381449
matrix:
382450
include: ${{ fromJson(needs.plan.outputs.sitectl_create_smoke_matrix) }}
383451

384-
uses: libops/.github/.github/workflows/sitectl-create-smoke-test.yaml@main
452+
uses: libops/.github/.github/workflows/sitectl-create-smoke-test.yaml@e366f7422565ea5ee71c0c626b740e03f2e2ffcd # main
385453
with:
386454
plugin: ${{ matrix.plugin }}
387455
create-definition: default
@@ -391,5 +459,10 @@ jobs:
391459
image-tags: ${{ matrix.image-tags }}
392460
images: ${{ matrix.images }}
393461
packages: ${{ matrix.packages }}
462+
local-plugin-repository: ${{ matrix.local-plugin-repository }}
463+
local-plugin-ref: ${{ matrix.local-plugin-ref }}
464+
local-plugin-path: ${{ matrix.local-plugin-path }}
465+
sitectl-repository: ${{ needs.plan.outputs.sitectl_repository }}
466+
sitectl-ref: ${{ needs.plan.outputs.sitectl_ref }}
394467
permissions:
395468
contents: read

Makefile

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@ endef
3131
# Used to include host-platform specific docker compose files.
3232
OS := $(shell uname -s | tr A-Z a-z)
3333

34-
# Used to determine set TAGS when no explicit value provided,
35-
# as well as to fetch branch specific remote caches when building.
36-
BRANCH = $(shell git rev-parse --abbrev-ref HEAD)
34+
# Used to set TAGS when no explicit value is provided and to fetch branch-specific
35+
# remote caches. Keep it aligned with the metadata helper's Docker-tag fallback
36+
# normalization so names such as feature/foo produce valid cache references.
37+
# Pipe the ref directly into the normalizer so branch text is never re-evaluated
38+
# as part of a generated shell command.
39+
BRANCH = $(shell git -c safe.directory='$(CURDIR)' rev-parse --abbrev-ref HEAD | sed -E 's/[^A-Za-z0-9_.-]+/-/g; s/^-+//; s/-+$$//')
3740

3841
# The buildkit builder to use.
3942
BUILDER ?= default
@@ -121,7 +124,7 @@ docker-buildx: | docker
121124
.SILENT: build/bake.json
122125
build/bake.json: | docker-buildx jq build folder-permissions executable-permissons
123126
set -x; \
124-
BRANCH=$(BRANCH) \
127+
BRANCH="$(BRANCH)" \
125128
CACHE_FROM_REPOSITORY=$(CACHE_FROM_REPOSITORY) \
126129
CACHE_TO_REPOSITORY=$(CACHE_TO_REPOSITORY) \
127130
REPOSITORY=$(REPOSITORY) \

README.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,26 @@ Changes in this fork:
3232
- Dropped fcrepo file persistence
3333
- Added ArchivesSpace, OJS, Omeka, and Wordpress images.
3434
- Moved Islandora buildkit's `drupal` image to `islandora` and made a drupal-only image
35-
- All of these images are intended to be infra scaffolding and app-specific codebase dropped into the container in local builds
35+
- ArchivesSpace, OJS, Omeka S, and Omeka Classic include checksum-verified upstream application releases.
36+
- Drupal and Wordpress remain infrastructure scaffolding for Composer-managed application code in downstream builds.
3637
- Tags are based on software versions
3738
- Multiple versions of the same software/image can coexist (e.g. java, solr, fcrepo, php, etc.)
3839
- `base` environment variables (e.g. `DB_NAME`) are overriden instead of `IMAGE_NAME_*` env vars
3940
- Removed Islandora multisite support
4041
- Added optional Vault-backed secret bootstrap
42+
43+
## OJS dataset initialization
44+
45+
Fresh OJS installations defer the install-time ROR registry and IP geolocation
46+
downloads so that container initialization is bounded and does not require
47+
outbound network access. OJS's built-in scheduler remains enabled and updates
48+
the ROR registry monthly on the first day of the month and the IP database
49+
monthly on the tenth.
50+
51+
To populate either dataset immediately after installation, run the corresponding
52+
OJS scheduler task from `/var/www/ojs` as the application user:
53+
54+
```sh
55+
php lib/pkp/tools/scheduler.php test --name='PKP\task\UpdateRorRegistryDataset'
56+
php lib/pkp/tools/scheduler.php test --name='PKP\task\UpdateIPGeoDB'
57+
```

ci/tests/update-sha-readme.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
root_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
6+
work_dir=$(mktemp -d)
7+
trap 'rm -rf "${work_dir}"' EXIT
8+
9+
# shellcheck disable=SC1090
10+
UPDATE_SHA_LIBRARY_ONLY=true source "${root_dir}/ci/update-sha.sh" test 1.2.3 2.0.0 ignored
11+
12+
readme="${work_dir}/README.md"
13+
printf '%s\n' 'Docker image version 1.2.3.' >"${readme}"
14+
update_readme "${readme}" 1.2.3 2.0.0
15+
grep -qx 'Docker image version 2.0.0.' "${readme}"
16+
17+
printf '%s\n' 'Docker image version 9.9.9.' >"${readme}"
18+
if update_readme "${readme}" 1.2.3 2.0.0; then
19+
echo "Missing README source version unexpectedly succeeded" >&2
20+
exit 1
21+
fi
22+
23+
printf '%s\n' 'First 1.2.3.' 'Second 1.2.3.' >"${readme}"
24+
if update_readme "${readme}" 1.2.3 2.0.0; then
25+
echo "Ambiguous README source version unexpectedly succeeded" >&2
26+
exit 1
27+
fi

0 commit comments

Comments
 (0)