Skip to content

Commit f0d37fc

Browse files
authored
AP-496: add github actions workflows (#1)
* AP-496: add github actions workflows also adds license file and updates link to B-Drive docs * version bump before release * docker-compose.ci.yml: use list/key=val syntax for environment variables
1 parent 7eb779c commit f0d37fc

8 files changed

Lines changed: 319 additions & 19 deletions

File tree

.github/workflows/build.yml

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

.github/workflows/release.yml

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

.rspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
--require spec_helper
22
--format progress
3-
--format RspecJunitFormatter
4-
--out artifacts/rspec/specs.xml
3+
--format html
4+
--out artifacts/rspec.html

Jenkinsfile

Lines changed: 0 additions & 15 deletions
This file was deleted.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 The Regents of the University of California
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
Application for fetching patron records for both studens and employees and formatting those records into XML to be loaded by Ex Libris into Alma using their sync process.
55

6-
Additional documentation can be found on B-Drive: [link](https://drive.google.com/drive/folders/1pOEKi2d5SQ4VZpwjQzUwuArwBbUJzvcF)
6+
Additional documentation can be found on B-Drive: [link](https://drive.google.com/drive/folders/1qO_7oD4tzDO9H4UMHrms7-ONzHdQ4gU2)
77

88
### Important Note
99
Because of differences in the two APIs (SIS and UCPath), these do not operate exactly the same. UCPath's API is driven by a "change log". When it runs, it looks back 7 days from the current date for any recods that have been added or updated and then processes those. SIS does not have a change log. Instead we pull the entire collection of users for the current semester everytime we run SIS.

config/settings.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Settings:
66
upload_host: "upload.lib.berkeley.edu"
77
upload_user: "ssullivan"
88
last_alma_purge: "2023-06-30"
9-
application_version: "1.5.9"
9+
application_version: "1.6.0"
1010

1111
# TODO - flesh this out
1212
# http://docopt.org/

docker-compose.ci.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
services:
2+
app:
3+
build: !reset
4+
image: ${DOCKER_APP_IMAGE}
5+
environment: !override
6+
- LDAP_HOST=ldap.fake.edu
7+
- LDAP_PASS=FAKEPW
8+
entrypoint: ["tail", "-f", "/dev/null"]
9+
volumes: !override
10+
- artifacts:/opt/app/artifacts
11+
12+
volumes:
13+
artifacts:
14+

0 commit comments

Comments
 (0)