Skip to content

Commit 536e2ec

Browse files
authored
feat(ci): #39 add GitHub Actions workflow for build and test (#40)
1 parent 12560f6 commit 536e2ec

File tree

8 files changed

+139
-23
lines changed

8 files changed

+139
-23
lines changed

.github/workflows/ci.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: build
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
- 39-create-a-new-ciyml
8+
tags:
9+
- '*'
10+
paths-ignore:
11+
- '*.md'
12+
pull_request:
13+
paths-ignore:
14+
- '*.md'
15+
16+
jobs:
17+
build:
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
24+
- name: Set up Docker Buildx
25+
id: buildx
26+
uses: docker/setup-buildx-action@v3
27+
28+
- name: Build Docker image
29+
env:
30+
GITHUB_REF: ${{ github.ref }}
31+
run: |
32+
make info
33+
make build
34+
35+
- name: Test and Lint
36+
run: |
37+
make test
38+
make lint
39+
40+
- name: Report coverage
41+
env:
42+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
43+
run: |
44+
pip install coveralls
45+
cd app && coveralls --service=github
46+
47+
- name: Available platforms
48+
run: |
49+
echo "Name: ${{ steps.buildx.outputs.name }}"
50+
echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}"
51+
echo "Status: ${{ steps.buildx.outputs.status }}"
52+
echo "Flags: ${{ steps.buildx.outputs.flags }}"
53+
echo "Platforms: ${{ steps.buildx.outputs.platforms }}"
54+
55+
- name: Deploy tagged (latest) to GitHub Packages (ghcr.io) and DockerHub
56+
if: ${{ startsWith(github.ref, 'refs/tags/') }}
57+
env:
58+
GITHUB_PACKAGE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
59+
DOCKER_HUB_TOKEN: ${{ secrets.DOCKER_HUB_TOKEN }}
60+
USERNAME: ${{ github.actor }}
61+
GITHUB_SHA: ${{ github.sha }}
62+
GITHUB_REF: ${{ github.ref }}
63+
run: |
64+
ref="$(echo ${GITHUB_REF} | cut -d'/' -f3)"
65+
echo GITHUB_REF - $ref
66+
echo ${GITHUB_PACKAGE_TOKEN} | docker login ghcr.io -u ${USERNAME} --password-stdin
67+
echo ${DOCKER_HUB_TOKEN} | docker login -u ${USERNAME} --password-stdin
68+
docker buildx build --push \
69+
--build-arg CI=github --build-arg GIT_SHA=${GITHUB_SHA} --build-arg GIT_TAG=${ref} \
70+
--platform linux/amd64,linux/arm/v7,linux/arm64 \
71+
-t ghcr.io/${USERNAME}/doku:${ref} \
72+
-t ${USERNAME}/doku:${ref} .

.github/workflows/docs.yml

Whitespace-only changes.

Dockerfile

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ COPY --from=builder /install /usr/local
1616
ARG APP_DIR=/usr/src/app
1717
ARG SUPERVISOR_CONF=/usr/local/etc/supervisord.conf
1818
ARG GITHUB_REPO=amerkurev/doku
19-
ARG REV
19+
ARG GIT_SHA
20+
ARG GIT_TAG
2021

2122
# this is used in the code
2223
LABEL github.repo=$GITHUB_REPO
@@ -31,14 +32,14 @@ LABEL org.opencontainers.image.source="https://github.com/amerkurev/doku"
3132
ENV IN_DOCKER=1 \
3233
# used in supervisord.conf
3334
APP_DIR=$APP_DIR \
34-
GITHUB_REPO=$GITHUB_REPO
35+
GITHUB_REPO=$GITHUB_REPO \
36+
GIT_SHA=$GIT_SHA \
37+
GIT_TAG=$GIT_TAG
3538

3639

3740
COPY app $APP_DIR
3841
COPY conf/supervisord.conf $SUPERVISOR_CONF
3942

40-
RUN echo "revision = '${REV}'" | tee $APP_DIR/version.py
41-
4243
WORKDIR $APP_DIR
4344

4445
CMD ["supervisord", "-c", "/usr/local/etc/supervisord.conf"]

Makefile

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
1-
GIT_BRANCH=$(shell git rev-parse --abbrev-ref HEAD)
2-
GIT_SHA=$(shell git rev-parse --short HEAD)
3-
GIT_TAG=$(shell git describe --tags --abbrev=0 2>/dev/null || echo "0.0.0")
4-
BUILD_DATE=$(shell date +%Y%m%d-%H:%M:%S)
5-
# If we're exactly on a tag, just show tag, otherwise show detailed version with commits
6-
GIT_DESCRIBE=$(shell git describe --tags 2>/dev/null)
7-
ifeq ($(GIT_TAG),$(GIT_DESCRIBE))
8-
# We're exactly on a tag
9-
REV=$(GIT_TAG) ($(BUILD_DATE))
1+
ifdef GITHUB_REF
2+
# CI environment - use provided ref
3+
GIT_TAG=$(shell echo $(GITHUB_REF) | cut -d'/' -f3)
104
else
11-
# We're off a tag
12-
REV=$(shell git describe --tags) ($(BUILD_DATE))
5+
# Local environment - calculate from git
6+
GIT_TAG=$(shell git describe --tags --abbrev=0 2>/dev/null || git rev-parse --abbrev-ref HEAD)
137
endif
8+
9+
ifdef GITHUB_SHA
10+
# CI environment - use provided sha
11+
GIT_SHA=$(GITHUB_SHA)
12+
else
13+
# Local environment - calculate from git
14+
GIT_SHA=$(shell git rev-parse --short HEAD)
15+
endif
16+
17+
REV=$(GIT_TAG)-$(GIT_SHA)
1418
PWD=$(shell pwd)
1519

1620
info:
1721
- @echo "revision $(REV)"
1822

1923
build:
20-
- @docker buildx build --build-arg REV="${REV}" -t amerkurev/doku:latest --progress=plain .
24+
- @docker buildx build --load --build-arg GIT_SHA="${GIT_SHA}" --build-arg GIT_TAG="${GIT_TAG}" -t amerkurev/doku:latest --progress=plain .
2125

2226
lint:
2327
- @ruff check app
@@ -27,6 +31,8 @@ fmt: lint
2731

2832
test:
2933
- @docker run --rm -t -v $(PWD)/app:/usr/src/app amerkurev/doku ./pytest.sh
34+
35+
cov:
3036
- @docker run --rm -t -v $(PWD)/app:/usr/src/app amerkurev/doku coverage html
3137

3238
dev: build
@@ -44,4 +50,4 @@ dev: build
4450
-p 9090:9090 \
4551
amerkurev/doku
4652

47-
.PHONY: info build lint fmt dev
53+
.PHONY: info build lint fmt test cov dev

app/server/router/context.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828

2929
def total_size(items: Sequence | None, field_name='size') -> str:
30+
if items is None:
31+
return '0'
3032
total = sum(map(attrgetter(field_name), items))
3133
return pretty_size(total)
3234

app/server/tests/test_context.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from dataclasses import dataclass
2+
3+
from server.router.context import total_size
4+
5+
6+
@dataclass
7+
class Item:
8+
size: int
9+
10+
11+
@dataclass
12+
class ItemShared:
13+
shared_size: int
14+
15+
16+
def test_total_size():
17+
# Test total_size function
18+
items = [
19+
Item(size=1),
20+
Item(size=2),
21+
Item(size=3),
22+
]
23+
assert total_size(items) == '6 Bytes'
24+
25+
items = [
26+
ItemShared(shared_size=1024),
27+
ItemShared(shared_size=1024 * 1024),
28+
ItemShared(shared_size=1024 * 1024 * 1024),
29+
]
30+
assert total_size(items, field_name='shared_size') == '1.1 GB'
31+
32+
assert total_size([]) == '0'
33+
34+
assert total_size(None) == '0'

app/settings.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@
88
from pydantic import Field, PositiveInt, ValidationError, field_validator
99
from pydantic_settings import BaseSettings
1010

11-
from version import revision
12-
13-
14-
REVISION = revision # e.g. 'v1.0.0 (20250301-00:56:09)'
15-
VERSION = REVISION.split()[0] # 'v1.0.0'
1611

1712
load_dotenv() # take environment variables from .env.
1813

@@ -75,6 +70,10 @@ class Settings(BaseSettings):
7570
docker_max_pool_size: PositiveInt = Field(alias='DOCKER_MAX_POOL_SIZE', default=docker.DEFAULT_MAX_POOL_SIZE)
7671
docker_use_ssh_client: bool = Field(alias='DOCKER_USE_SSH_CLIENT', default=False)
7772

73+
# version settings
74+
git_tag: str = Field(alias='GIT_TAG', default='v0.0.0')
75+
git_sha: str = Field(alias='GIT_SHA', default='')
76+
7877
@field_validator('log_level', mode='before')
7978
def lowercase_log_level(cls, v):
8079
if isinstance(v, str):
@@ -99,6 +98,9 @@ def log_level_num(self) -> int:
9998
raise SystemExit(err) from err
10099

101100

101+
VERSION = _settings.git_tag
102+
REVISION = f'{_settings.git_tag}-{_settings.git_sha[:7]}'
103+
102104
# general settings
103105
HOST = _settings.host
104106
PORT = _settings.port

app/version.py

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)