Skip to content

Commit 91fc546

Browse files
committed
AP-501: set up github actions
1 parent ef7df5b commit 91fc546

File tree

8 files changed

+300
-28
lines changed

8 files changed

+300
-28
lines changed

.github/workflows/build.yml

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
name: Build / Test / Push
2+
3+
on:
4+
push:
5+
branches:
6+
- '**'
7+
workflow_dispatch:
8+
9+
env:
10+
BUILD_SUFFIX: -build-${{ github.run_id }}_${{ github.run_attempt }}
11+
DOCKER_METADATA_SET_OUTPUT_ENV: 'true'
12+
13+
jobs:
14+
build:
15+
runs-on: ${{ matrix.runner }}
16+
outputs:
17+
image-arm64: ${{ steps.gen-output.outputs.image-arm64 }}
18+
image-x64: ${{ steps.gen-output.outputs.image-x64 }}
19+
strategy:
20+
fail-fast: false
21+
matrix:
22+
runner:
23+
- ubuntu-24.04
24+
- ubuntu-24.04-arm
25+
steps:
26+
- name: Checkout code
27+
uses: actions/checkout@v4
28+
29+
- name: Set up Docker Buildx
30+
uses: docker/setup-buildx-action@v3
31+
32+
- name: Login to GitHub Container Registry
33+
uses: docker/login-action@v3
34+
with:
35+
registry: ghcr.io
36+
username: ${{ github.actor }}
37+
password: ${{ secrets.GITHUB_TOKEN }}
38+
39+
- id: build-meta
40+
name: Docker meta
41+
uses: docker/metadata-action@v5
42+
with:
43+
images: ghcr.io/${{ github.repository }}
44+
tags: type=sha,suffix=${{ env.BUILD_SUFFIX }}
45+
46+
# Build cache is shared among all builds of the same architecture
47+
- id: cache-meta
48+
name: Docker meta
49+
uses: docker/metadata-action@v5
50+
with:
51+
images: ghcr.io/${{ github.repository }}
52+
tags: type=raw,value=buildcache-${{ runner.arch }}
53+
54+
- id: get-registry
55+
name: Get the sanitized registry name
56+
run: |
57+
echo "registry=$(echo '${{ steps.build-meta.outputs.tags }}' | cut -f1 -d:)" | tee -a "$GITHUB_OUTPUT"
58+
59+
- id: build
60+
name: Build/push the arch-specific image
61+
uses: docker/build-push-action@v6
62+
with:
63+
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
64+
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
65+
labels: ${{ steps.build-meta.outputs.labels }}
66+
provenance: mode=max
67+
sbom: true
68+
tags: ${{ steps.get-registry.outputs.registry }}
69+
outputs: type=image,push-by-digest=true,push=true
70+
71+
- id: gen-output
72+
name: Write arch-specific image digest to outputs
73+
run: |
74+
echo "image-${RUNNER_ARCH,,}=${{ steps.get-registry.outputs.registry }}@${{ steps.build.outputs.digest }}" | tee -a "$GITHUB_OUTPUT"
75+
76+
merge:
77+
runs-on: ubuntu-24.04
78+
needs: build
79+
env:
80+
DOCKER_APP_IMAGE_ARM64: ${{ needs.build.outputs.image-arm64 }}
81+
DOCKER_APP_IMAGE_X64: ${{ needs.build.outputs.image-x64 }}
82+
outputs:
83+
image: ${{ steps.meta.outputs.tags }}
84+
steps:
85+
- name: Checkout code
86+
uses: actions/checkout@v4
87+
88+
- name: Set up Docker Buildx
89+
uses: docker/setup-buildx-action@v3
90+
91+
- name: Login to GitHub Container Registry
92+
uses: docker/login-action@v3
93+
with:
94+
registry: ghcr.io
95+
username: ${{ github.actor }}
96+
password: ${{ secrets.GITHUB_TOKEN }}
97+
98+
- id: meta
99+
name: Generate tag for the app image
100+
uses: docker/metadata-action@v5
101+
with:
102+
images: ghcr.io/${{ github.repository }}
103+
tags: type=sha,suffix=${{ env.BUILD_SUFFIX }}
104+
105+
- name: Push the multi-platform app image
106+
run: |
107+
docker buildx imagetools create \
108+
--tag "$DOCKER_METADATA_OUTPUT_TAGS" \
109+
"$DOCKER_APP_IMAGE_ARM64" "$DOCKER_APP_IMAGE_X64"
110+
111+
test:
112+
runs-on: ubuntu-24.04
113+
needs: merge
114+
env:
115+
COMPOSE_FILE: docker-compose.yml:docker-compose.ci.yml
116+
DOCKER_APP_IMAGE: ${{ needs.merge.outputs.image }}
117+
steps:
118+
- name: Checkout code
119+
uses: actions/checkout@v4
120+
121+
- name: Set up Docker Compose
122+
uses: docker/setup-compose-action@v1
123+
124+
- name: Login to GitHub Container Registry
125+
uses: docker/login-action@v3
126+
with:
127+
registry: ghcr.io
128+
username: ${{ github.actor }}
129+
password: ${{ secrets.GITHUB_TOKEN }}
130+
131+
- name: Setup the stack
132+
run: |
133+
docker compose build --quiet
134+
docker compose pull --quiet
135+
docker compose up --wait
136+
docker compose exec app rails assets:precompile db:migrate
137+
docker compose exec -u root app chown -R nara:nara artifacts
138+
139+
- name: Run RSpec
140+
if: ${{ always() }}
141+
run: |
142+
docker compose exec -e RAILS_ENV=test app rspec --format progress --format html --out artifacts/rspec.html
143+
144+
- name: Run Rubocop
145+
if: ${{ always() }}
146+
run: |
147+
docker compose exec -e RAILS_ENV=test app rubocop --format progress --format html --out artifacts/rubocop.html
148+
149+
- name: Run Brakeman
150+
if: ${{ always() }}
151+
run: |
152+
docker compose exec -e RAILS_ENV=test app brakeman -o artifacts/brakeman.html
153+
154+
- name: Copy out artifacts
155+
if: ${{ always() }}
156+
run: |
157+
docker compose cp app:/opt/app/artifacts ./
158+
docker compose logs > artifacts/docker-compose-services.log
159+
docker compose config > artifacts/docker-compose.merged.yml
160+
161+
- name: Upload the test report
162+
if: ${{ always() }}
163+
uses: actions/upload-artifact@v4
164+
with:
165+
name: ruby-nara Build Report (${{ github.run_id }}_${{ github.run_attempt }})
166+
path: artifacts/*
167+
if-no-files-found: error
168+
169+
push:
170+
runs-on: ubuntu-24.04
171+
needs:
172+
- merge
173+
- test
174+
env:
175+
DOCKER_APP_IMAGE: ${{ needs.merge.outputs.image }}
176+
steps:
177+
- name: Checkout code
178+
uses: actions/checkout@v4
179+
180+
- name: Login to GitHub Container Registry
181+
uses: docker/login-action@v3
182+
with:
183+
registry: ghcr.io
184+
username: ${{ github.actor }}
185+
password: ${{ secrets.GITHUB_TOKEN }}
186+
187+
- name: Produce permanent image tags
188+
uses: docker/metadata-action@v5
189+
with:
190+
images: ghcr.io/${{ github.repository }}
191+
tags: |
192+
type=sha
193+
type=ref,event=branch
194+
type=raw,value=latest,enable={{is_default_branch}}
195+
196+
- name: Retag and push the image
197+
run: |
198+
docker pull "$DOCKER_APP_IMAGE"
199+
echo "$DOCKER_METADATA_OUTPUT_TAGS" | tr ' ' '\n' | xargs -n1 docker tag "$DOCKER_APP_IMAGE"
200+
docker push --all-tags "$(echo "$DOCKER_APP_IMAGE" | cut -f1 -d:)"

.github/workflows/release.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: Push Release Tags
2+
3+
on:
4+
push:
5+
tags:
6+
- '**'
7+
workflow_dispatch:
8+
9+
env:
10+
DOCKER_METADATA_SET_OUTPUT_ENV: 'true'
11+
12+
jobs:
13+
retag:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v4
18+
19+
- name: Set up Docker Buildx
20+
uses: docker/setup-buildx-action@v3
21+
22+
- name: Login to GitHub Container Registry
23+
uses: docker/login-action@v3
24+
with:
25+
registry: ghcr.io
26+
username: ${{ github.actor }}
27+
password: ${{ secrets.GITHUB_TOKEN }}
28+
29+
- name: Determine the sha-based image tag to retag
30+
id: get-base-image
31+
uses: docker/metadata-action@v5
32+
with:
33+
images: ghcr.io/${{ github.repository }}
34+
tags: type=sha
35+
36+
- name: Verify that the image was previously built
37+
env:
38+
BASE_IMAGE: ${{ steps.get-base-image.outputs.tags }}
39+
run: |
40+
docker pull "$BASE_IMAGE"
41+
42+
- name: Produce release tags
43+
id: tag-meta
44+
uses: docker/metadata-action@v5
45+
with:
46+
images: ghcr.io/${{ github.repository }}
47+
flavor: latest=false
48+
tags: |
49+
type=ref,event=tag
50+
type=semver,pattern={{major}}
51+
type=semver,pattern={{major}}.{{minor}}
52+
type=semver,pattern={{version}}
53+
54+
- name: Retag the pulled image
55+
env:
56+
BASE_IMAGE: ${{ steps.get-base-image.outputs.tags }}
57+
run: |
58+
echo "$DOCKER_METADATA_OUTPUT_TAGS" | tr ' ' '\n' | xargs -n1 docker tag "$BASE_IMAGE"
59+
docker push --all-tags "$(echo "$BASE_IMAGE" | cut -f1 -d:)"

README.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
# NARA casefiles web database
22

3-
Rails web app for viewing the NARA case files database. This application runs on VM154 using port 3001. The database itself runs on mysql.lib.berkeley.edu.
3+
Rails web app for viewing the NARA case files database. This application runs on Docker Swarm.
44

5-
The Nara database app can be found under the existing Chinese immigration website at https://bancroft.berkeley.edu/collections/chinese-immigration-to-the-united-states-1884-1944/ alternatively, you can visit the website at https://nara.lib.berkeley.edu/
5+
The Nara database app can be found under the archived Chinese immigration website at <https://web.archive.org/web/20220124061848/https://bancroft.berkeley.edu/collections/chinese-immigration-to-the-united-states-1884-1944/index.html>. Alternatively, you can visit the website at https://nara.lib.berkeley.edu/
6+
7+
## Local development
8+
9+
Local development and CI is handled by Docker Compose. The app requires a custom MariaDB configuration (see [`mariadb/conf.d/nara.cnf`](dmariadb/conf.d/nara.cnf)). This should get automatically loaded as you bring the container up locally, but this setting needs to be deployed to the Swarm configuration.
10+
11+
By default, the application does not ship with any data, but you can load some if you place a dump file in `mariadb/docker-entrypoint-initdb.d` and bring the containers up with a supplemental Compose file, e.g.
12+
13+
```bash
14+
cp nara-dump.sql.gz mariadb/docker-entrypoint-initdb.d
15+
docker compose -f docker-compose.yml -f docker-compose.dump.yml up -d
16+
```
617

718
## Testing
819

9-
Nara uses a combination of Rspec and Capybara, for it's test suites. To run a suite from the command line, run 'rspec' from the projects root directory.
20+
Nara uses a combination of Rspec and Capybara for its test suites. To run a suite from the command line, run 'rspec' from the projects root directory.
1021

1122
## SimpleCov
1223

docker-compose.ci.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
3+
services:
4+
app:
5+
build: !reset
6+
image: ${DOCKER_APP_IMAGE}
7+
volumes: !override
8+
- artifacts:/opt/app/artifacts
9+
10+
volumes:
11+
artifacts:

docker-compose.dump.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
services:
2+
db:
3+
environment:
4+
- MYSQL_DATABASE=NARA
5+
volumes:
6+
- ./mariadb/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d

docker-compose.yml

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,26 @@
1-
# ######################################################################
2-
# NOTE
3-
# ######################################################################
4-
#
5-
# This docker-compose file uses a custom database image from lap/nara-db,
6-
# published in the GitLab container registry (containers.lib.berkeley.edu).
7-
#
8-
# Before running `docker-compose`, use `docker login containers.lib.berkeley.edu`
9-
# to authenticate.
10-
#
11-
# (See https://git.lib.berkeley.edu/help/user/packages/container_registry/index.md#authenticate-with-the-container-registry)
12-
131
services:
14-
# adminer:
15-
# image: adminer
16-
# restart: always
17-
# ports:
18-
# - 8080:8080
192

203
db:
21-
# For local development, set DATABASE_URL=mysql2://root:[email protected]:33306/NARA
22-
# or use `mysql -u root -proot -h 0.0.0.0 -P 33306 -D NARA`
23-
image: containers.lib.berkeley.edu/lap/nara-db/master:latest
4+
image: mariadb:10
245
environment:
25-
# Default password for the image is empty, but adminer doesn't support
26-
# that (https://www.adminer.org/en/password/), so we use 'root'
6+
# Default password for the image is empty
277
MYSQL_ROOT_PASSWORD: root
288
restart: always
299
ports:
3010
- 3306:3306
11+
volumes:
12+
- ./mariadb/conf.d:/etc/mysql/conf.d
3113

32-
rails:
14+
app:
3315
build:
3416
context: .
3517
target: development
18+
depends_on:
19+
- db
3620
environment:
3721
DATABASE_URL: 'mysql2://root:root@db:3306/NARA'
3822
ports:
3923
- 3000:3000
4024
restart: always
4125
volumes:
4226
- ./:/opt/app:delegated
43-
44-
version: "3.7"

mariadb/conf.d/nara.cnf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[mysqld]
2+
3+
ft_min_word_len = 3

mariadb/docker-entrypoint-initdb.d/.keep

Whitespace-only changes.

0 commit comments

Comments
 (0)