Skip to content

Build of 3238/merge by @maxkadel #3708

Build of 3238/merge by @maxkadel

Build of 3238/merge by @maxkadel #3708

name: "build-test-lint"
run-name: Build of ${{ github.ref_name }} by @${{ github.actor }}
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
inputs:
debug_step:
required: false
description: "Pause the selected step to debug using tmate"
type: choice
default: ""
options:
- ""
- build
- test
- lint
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
REGISTRY: ghcr.io
IMAGE_NAME: samvera/hyku
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
jobs:
build:
strategy:
matrix:
component: ["solr", "web", "worker"]
os: ["ubuntu-latest", "ubuntu-24.04-arm"]
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
permissions: write-all
steps:
- name: Determine git sha to checkout
uses: haya14busa/action-cond@v1
id: gitsha
with:
cond: ${{ github.event_name == 'pull_request' }}
if_true: ${{ github.event.pull_request.head.sha }}
if_false: ${{ github.sha }}
- name: Set env
run: echo "TAG=${GIT_SHA::8}" >> $GITHUB_ENV
env:
GIT_SHA: ${{ steps.gitsha.outputs.value }}
- name: Downcase repo
run: echo "REPO_LOWER=${REPO,,}" >> $GITHUB_ENV
env:
REPO: "${{ github.repository }}"
- name: Set platform from matrix
run: |
if [[ "${{ matrix.os }}" == "ubuntu-latest" ]]; then
echo "PLATFORM_TAG=amd64" >> $GITHUB_ENV
else
echo "PLATFORM_TAG=arm64" >> $GITHUB_ENV
fi
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Github Container Login
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push ${{ matrix.component }} on ${{ matrix.os }}
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/${{ env.PLATFORM_TAG }}
target: hyku-${{ matrix.component }}
cache-from: |
type=registry,ref=ghcr.io/samvera/hyku/${{ matrix.component }}:latest
cache-to: type=inline
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.component }}:${{ env.TAG }}-${{ env.PLATFORM_TAG }}
push:
needs: build
runs-on: ubuntu-latest
permissions: write-all
steps:
- name: Determine git sha to checkout
uses: haya14busa/action-cond@v1
id: gitsha
with:
cond: ${{ github.event_name == 'pull_request' }}
if_true: ${{ github.event.pull_request.head.sha }}
if_false: ${{ github.sha }}
- name: Set env
run: echo "TAG=${GIT_SHA::8}" >> $GITHUB_ENV
env:
GIT_SHA: ${{ steps.gitsha.outputs.value }}
- name: Downcase repo
run: echo "REPO_LOWER=${REPO,,}" >> $GITHUB_ENV
env:
REPO: "${{ github.repository }}"
- name: Github Container Login
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create multiarch manifests
run: |
for component in solr web worker; do
docker buildx imagetools create -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/$component:${{ env.TAG }} \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/$component:${{ env.TAG }}-amd64 \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/$component:${{ env.TAG }}-arm64
done
lint:
needs: push
uses: notch8/actions/.github/workflows/lint.yaml@v1.0.6
with:
webTarget: hyku-web
workerTarget: hyku-worker
rubocop_cmd: "bundle exec rubocop --parallel --format progress"
test:
needs: push
uses: notch8/actions/.github/workflows/test.yaml@v1.0.6
with:
confdir: "/app/samvera/hyrax-webapp/solr/conf"
rspec_cmd: "gem install semaphore_test_boosters && bundle && rspec_booster --job $CI_NODE_INDEX/$CI_NODE_TOTAL"
single-tenant-test:
needs: push
runs-on: ubuntu-latest
defaults:
run:
shell: bash
permissions: write-all
steps:
- name: Determine git sha to checkout
uses: haya14busa/action-cond@v1
id: gitsha
with:
cond: ${{ github.event_name == 'pull_request' }}
if_true: ${{ github.event.pull_request.head.sha }}
if_false: ${{ github.sha }}
- name: Set env
run: echo "TAG=${GIT_SHA::8}" >> $GITHUB_ENV
env:
GIT_SHA: ${{ steps.gitsha.outputs.value }}
- name: Checkout code
uses: actions/checkout@v3
- name: Github Container Login
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Bring up single-tenant stack
run: docker compose -f docker-compose.single.yml up -d web worker > docker-compose-server.log 2>&1
- name: Ensure gems are installed in web and worker
run: |
for svc in web worker; do
docker compose -f docker-compose.single.yml exec -T "$svc" \
sh -lc 'bundle check || bundle install'
done
- name: Wait for web to be ready
run: |
for i in {1..60}; do
if docker compose -f docker-compose.single.yml exec -T web bundle exec rails runner "puts 'ok'" 2>/dev/null | grep -q ok; then
echo "web is ready"
exit 0
fi
echo "waiting for web... ($i)"
sleep 5
done
echo "web did not become ready in time"
docker compose -f docker-compose.single.yml ps
exit 1
- name: Run single-tenant specs
env:
HYKU_MULTITENANT: "false"
SOLR_ENABLE_CLOUD_MODE: "no"
SOLR_COLLECTION: hydra-development
SOLR_COLLECTION_NAME: hydra-development
run: |
docker compose -f docker-compose.single.yml exec -T \
-e HYKU_MULTITENANT=false \
-e SOLR_ENABLE_CLOUD_MODE=no \
-e SOLR_COLLECTION=hydra-development \
-e SOLR_COLLECTION_NAME=hydra-development \
web bundle exec rspec \
spec/models/user_spec.rb \
spec/models/account_spec.rb \
spec/models/solr_endpoint_spec.rb \
spec/jobs/create_solr_collection_job_spec.rb \
spec/jobs/remove_solr_collection_job_spec.rb \
spec/lib/hyku_spec.rb \
--tag ~wip
- name: Verify standalone Solr core and account endpoint
run: |
docker compose -f docker-compose.single.yml exec -T \
-e HYKU_MULTITENANT=false \
-e SOLR_COLLECTION=hydra-development \
-e SOLR_COLLECTION_NAME=hydra-development \
web bundle exec rails runner "
core = ENV.fetch('SOLR_COLLECTION', 'hydra-development')
account = Account.find_by(cname: ENV.fetch('HYKU_SINGLE_TENANT_CNAME', 'single.tenant.default'))
raise 'No single-tenant account found' unless account
raise 'Account has no SolrEndpoint' if account.solr_endpoint.is_a?(NilSolrEndpoint)
raise \"SolrEndpoint URL does not include core name '#{core}'\" unless account.solr_endpoint.url.include?(core)
base_url = ENV.fetch('SOLR_URL', 'http://solr:8983/solr/')
response = RSolr.connect(url: base_url).get('/solr/admin/cores', params: { action: 'STATUS', core: core })
raise \"Solr core '#{core}' missing from STATUS response\" unless response.dig('status', core)&.any?
puts \"Standalone Solr core '#{core}' OK — endpoint: #{account.solr_endpoint.url}\"
"
- name: Upload single-tenant logs
uses: notch8/actions/after-care@v1.0.6
if: always()
env:
COMPOSE_FILE: docker-compose.single.yml
with:
name: single-tenant-${{ env.TAG }}
reports: "single-tenant-*.xml"
- name: Tear down stack
if: always()
run: docker compose -f docker-compose.single.yml down -v --remove-orphans
env-file-lint:
# Guard against a regression class: `${VAR}` shell interpolation of any
# form placed inside `.env`. It is not reliably expanded through env_file:
# the `${VAR:-default}` form is only handled on newer Compose (>= ~2.24),
# and the dotenv CLI that stack_car (`sc`) wraps compose with mangles it
# (e.g. `${FCREPO_HOST:-fcrepo}` becomes `:-fcrepo}`). Even plain `${VAR}`
# depends on how the file is consumed. Defaults belong in the compose
# `environment:` block, which is always interpolated; `.env` stays literal.
runs-on: ubuntu-latest
defaults:
run:
shell: bash
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Reject `${...}` interpolation in .env
run: |
# Compose files (docker-compose*.yml) may use ${VAR:-default} freely; the
# compose file is always interpolated. Only `.env` is unreliable, because
# its values reach the container via env_file passthrough and the
# dotenv CLI. Note: `%{...}` (Ruby format, e.g. HYKU_DEFAULT_HOST) is fine.
env_matches=$(grep -nE '\$\{' .env 2>/dev/null || true)
if [ -n "$env_matches" ]; then
echo "::error::Found \${...} interpolation in .env. This is NOT reliably expanded via docker-compose env_file (only on Compose >= ~2.24) and is mangled by the dotenv CLI used by stack_car, so the container may receive a literal/garbled value. Use a plain literal in .env and put any overridable default in the docker-compose.yml 'environment:' (x-app-env) block instead."
echo "$env_matches"
exit 1
fi
echo "No \${...} interpolation found in .env"
reports:
if: always()
needs: [test, lint, single-tenant-test]
uses: notch8/actions/.github/workflows/report.yaml@v1.0.6