Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 0 additions & 62 deletions .github/workflows/build.yaml

This file was deleted.

114 changes: 114 additions & 0 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
on:
push:
tags:
- 'v*.*.*'
jobs:
check-master:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- run: git branch -r --contains $GITHUB_SHA | grep -q 'origin/master'
api:
runs-on: ubuntu-latest
needs: check-master
environment: dockerhub-push
steps:
- uses: actions/checkout@v3
- uses: docker/login-action@v2
with:
username: hurtki
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- uses: docker/setup-buildx-action@v2
- name: Docker build
run: |
VERSION="${GITHUB_REF_NAME#v}"
docker buildx build --push -t hurtki/github-banners-api:$VERSION ./api/
renderer:
runs-on: ubuntu-latest
needs: check-master
environment: dockerhub-push
steps:
- uses: actions/checkout@v3
- uses: docker/login-action@v2
with:
username: hurtki
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- uses: docker/setup-buildx-action@v2
- name: Docker build
run: |
VERSION="${GITHUB_REF_NAME#v}"
docker buildx build --push -t hurtki/github-banners-renderer:$VERSION ./renderer/
storage:
runs-on: ubuntu-latest
needs: check-master
environment: dockerhub-push
steps:
- uses: actions/checkout@v3
- uses: docker/login-action@v2
with:
username: hurtki
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- uses: docker/setup-buildx-action@v2
- name: Docker build
run: |
VERSION="${GITHUB_REF_NAME#v}"
docker buildx build --push -t hurtki/github-banners-storage:$VERSION ./storage/
deploy:
runs-on: ubuntu-latest
needs: [api, renderer, storage]
environment: ssh-deploy
steps:
- uses: actions/checkout@v3
- name: Get version
run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
- name: Deploy via SSH
uses: appleboy/ssh-action@v0.1.7
env:
VERSION: ${{ env.VERSION }}
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
script: |
cd /deploy/github-banners/
export VER=$VERSION
docker-compose -f docker-compose.prod.yaml pull
docker-compose -f docker-compose.prod.yaml up -d
health-check:
runs-on: ubuntu-latest
needs: deploy
environment: health-check
steps:
- name: http preview endpoint check
run: |
curl -o /dev/null -s -w "%{http_code}" "https://$DOMAIN/banners/preview?username=hurtki&type=dark" | grep -q "^200$"
rollback:
needs: health-check
if: needs.health-check.result == 'failure'
runs-on: ubuntu-latest
environment: ssh-deploy
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get previous version
run: |
PREV_TAG=$(git tag --sort=-creatordate | sed -n \'2p\' | sed \'s/^v//\')
echo "PREV_VERSION=${PREV_TAG}" >> $GITHUB_ENV
- name: Rollback via ssh
uses: appleboy/ssh-action@v0.1.7
env:
VERSION: ${{ env.PREV_VERSION }}
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
script: |
cd /deploy/github-banners/
export VER=$VERSION
docker-compose -f docker-compose.prod.yaml pull
docker-compose -f docker-compose.prod.yaml up -d
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ go.work.sum

api/renderer_impl.go
api/storage_impl.go
nginx/default.svg
110 changes: 110 additions & 0 deletions docker-compose.prod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
services:
# api service
api:
image: hurtki/github-banners-api:${VER:?VER is required}
platform: linux/amd64
container_name: api
restart: always
env_file: ./api/.env
environment:
SERVICES_SECRET_KEY: "$SERVICES_SECRET_KEY"
STORAGE_BASE_URL: "$STORAGE_BASE_URL"
networks:
- banners-net
- api-net
- kafka-net
depends_on:
kafka:
condition: service_healthy
api-psgr:
condition: service_started
# api service's Postgres database
api-psgr:
image: postgres:15
env_file: ./api/.env
container_name: api-psgr
networks:
- api-net
volumes:
- pgdata:/var/lib/postgresql/data
# one instance of rendere service
renderer:
image: hurtki/github-banners-renderer:${VER:?VER is required}
platform: linux/amd64
env_file: ./renderer/.env
container_name: renderer
environment:
SERVICES_SECRET_KEY: "${SERVICES_SECRET_KEY}"
STORAGE_BASE_URL: "$STORAGE_BASE_URL"
networks:
- banners-net
- kafka-net
depends_on:
kafka:
condition: service_healthy
# storage service
storage:
image: hurtki/github-banners-storage:${VER:?VER is required}
platform: linux/amd64
container_name: storage
volumes:
- banners-storage:/var/www/banners
networks:
- banners-net
# nginx api gateway
nginx:
build:
context: ./nginx/
dockerfile: ./nginx/Dockerfile.prod
container_name: nginx
volumes:
- banners-storage:/var/www/banners:ro
# key + cert
- /etc/nginx/ssl:/etc/nginx/ssl:ro
ports:
- 80:80
networks:
- banners-net
depends_on:
- api
kafka:
image: apache/kafka:4.2.0
container_name: kafka
environment:
KAFKA_NODE_ID: 1
KAFKA_PROCESS_ROLES: broker,controller
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
KAFKA_NUM_PARTITIONS: 3
KAFKA_LOG4J_ROOT_LOGLEVEL: WARN
KAFKA_LOG_DIRS: /var/lib/kafka/data
networks:
- kafka-net
healthcheck:
test: ["CMD-SHELL", "/opt/kafka/bin/kafka-topics.sh --bootstrap-server localhost:9092 --list || exit 1"]
interval: 5s
timeout: 5s
retries: 10
volumes:
- kafka-data:/var/lib/kafka/data
volumes:
pgdata:
name: postgres_db_banners_api_ms
kafka-data:
name: kafka-data
banners-storage:
name: banners-storage
networks:
api-net:
driver: bridge
banners-net:
driver: bridge
kafka-net:
driver: bridge
4 changes: 3 additions & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ services:
- banners-net
# nginx api gateway
nginx:
build: ./nginx/
build:
context: ./nginx/
dockerfile: Dockerfile.dev
container_name: nginx
volumes:
- banners-storage:/var/www/banners:ro
Expand Down
2 changes: 1 addition & 1 deletion nginx/Dockerfile → nginx/Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ FROM nginx:latest

COPY ./default.svg /var/www/banners/default.svg

COPY ./nginx.conf /etc/nginx/conf.d/default.conf
COPY ./nginx.dev.conf /etc/nginx/conf.d/default.conf

EXPOSE 80
8 changes: 8 additions & 0 deletions nginx/Dockerfile.prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM nginx:latest

COPY ./default.svg /var/www/banners/default.svg

COPY ./nginx.prod.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

File renamed without changes.
File renamed without changes.
33 changes: 33 additions & 0 deletions nginx/nginx.prod.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# --- HTTPS thorugh Cloudflare Origin Certificate ---
server {
listen 443 ssl;
server_name _;

ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;

root /var/www/;

# --- API proxy ---
location = /banners {
proxy_pass http://api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location ^~ /banners/preview {
proxy_pass http://api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}

# --- Static banners serving ---
location ^~ /banners/ {
try_files $uri.svg /banners/default;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
add_header Last-Modified "";
etag off;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
add_header Surrogate-Control "no-store" always;
}
}
Loading