Skip to content

Commit 21d5d45

Browse files
committed
Add GitHub Action files
1 parent 29a4503 commit 21d5d45

File tree

6 files changed

+235
-0
lines changed

6 files changed

+235
-0
lines changed

.github/workflows/README.md

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# ServiceStack mix GitHub Actions
2+
`release.yml` generated from `x mix release-ghr-vanilla`, this template in designed to help with CI deployment to a dedicated server with SSH access.
3+
4+
## Overview
5+
`release.yml` is designed to work with a ServiceStack app deploying directly to a single server via SSH. A docker image is built and stored on GitHub's `ghcr.io` docker registry when a GitHub Release is created.
6+
7+
GitHub Actions specified in `release.yml` then copy files remotely via scp and use `docker-compose` to run the app remotely via SSH.
8+
9+
## Deployment server setup
10+
To get this working, a server needs to be setup with the following:
11+
12+
- SSH access
13+
- docker
14+
- docker-compose
15+
- ports 443 and 80 for web access of your hosted application
16+
17+
This can be your own server or any cloud hosted server like Digital Ocean, AWS, Azure etc.
18+
19+
When setting up your server, you'll want to use a dedicated SSH key for access to be used by GitHub Actions. GitHub Actions will need the *private* SSH key within a GitHub Secret to authenticate. This can be done via ssh-keygen and copying the public key to the authorized clients on the server.
20+
21+
To let your server handle multiple ServiceStack applications and automate the generation and management of TLS certificates, an additional docker-compose file is provided via the `x mix` template, `nginx-proxy-compose.yml`. This docker-compose file is ready to run and can be copied to the deployment server.
22+
23+
For example, once copied to remote `~/nginx-proxy-compose.yml`, the following command can be run on the remote server.
24+
25+
```
26+
docker-compose -f ~/nginx-proxy-compose.yml up -d
27+
```
28+
29+
This will run an nginx reverse proxy along with a companion container that will watch for additional containers in the same docker network and attempt to initialize them with valid TLS certificates.
30+
31+
## GitHub Repository setup
32+
The `release.yml` assumes 6 secrets have been setup.
33+
34+
- CR_PAT - GitHub Personal Token with read/write access to packages.
35+
- DEPLOY_HOST - hostname used to SSH to, this can either be an IP address or subdomain with A record pointing to the server.
36+
- DEPLOY_PORT - SSH port, usually `22`.
37+
- DEPLOY_USERNAME - the username being logged into via SSH. Eg, `ubuntu`, `ec2-user`, `root` etc.
38+
- DEPLOY_KEY - SSH private key used to remotely access deploy server/app host.
39+
- LETSENCRYPT_EMAIL - Email address, required for Let's Encrypt automated TLS certificates.
40+
41+
These secrets are used to populate variables within GitHub Actions and other configuration files.
42+
43+
> If you are deploying multiple ServiceStack apps via this pattern, make sure the host port in the `docker-compose-template.yml` is not being used. This defaults as 8081.
44+
45+
46+
## What's the process of `release.yml`?
47+
48+
![](https://raw.githubusercontent.com/ServiceStack/docs/master/docs/images/mix/release-ghr-vanilla-diagram.png)

.github/workflows/build.yml

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Build
2+
3+
on:
4+
pull_request: {}
5+
push:
6+
branches:
7+
- '**' # matches every branch
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-20.04
12+
steps:
13+
- name: checkout
14+
uses: actions/[email protected]
15+
16+
- name: setup .net core
17+
uses: actions/[email protected]
18+
with:
19+
dotnet-version: 5.0.100
20+
21+
- name: build
22+
run: dotnet build
23+
working-directory: .
24+
25+
- name: test
26+
run: |
27+
dotnet test
28+
if [ $? -eq 0 ]; then
29+
echo TESTS PASSED
30+
else
31+
echo TESTS FAILED
32+
exit 1
33+
fi
34+
working-directory: ./ParcelTemplate.Tests
35+

.github/workflows/release.yml

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
name: Release
2+
on:
3+
release:
4+
types: [published]
5+
jobs:
6+
push_to_registry:
7+
runs-on: ubuntu-20.04
8+
steps:
9+
- name: checkout
10+
uses: actions/checkout@v2
11+
12+
- name: dotnet publish
13+
run: |
14+
dotnet publish ./ParcelTemplate/ -o publish -c release
15+
16+
- name: repository name fix
17+
run: echo "image_repository_name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
18+
19+
- name: Login to GitHub Container Registry
20+
uses: docker/login-action@v1
21+
with:
22+
registry: ghcr.io
23+
username: ${{ github.repository_owner }}
24+
password: ${{ secrets.CR_PAT }}
25+
26+
- name: Build and push Docker images
27+
uses: docker/[email protected]
28+
with:
29+
file: ParcelTemplate/Dockerfile
30+
context: .
31+
push: true
32+
tags: ghcr.io/${{ env.image_repository_name }}:${{ github.event.release.tag_name }}
33+
34+
deploy_via_ssh:
35+
needs: push_to_registry
36+
runs-on: ubuntu-20.04
37+
steps:
38+
- name: checkout
39+
uses: actions/checkout@v2
40+
41+
- name: repository name fix and env
42+
run: |
43+
echo "image_repository_name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
44+
echo "domain=${{ secrets.DEPLOY_HOST }}" >> $GITHUB_ENV
45+
echo "letsencrypt_email=${{ secrets.LETSENCRYPT_EMAIL }}" >> $GITHUB_ENV
46+
47+
- name: docker-compose file prep
48+
uses: danielr1996/[email protected]
49+
env:
50+
RELEASE_VERSION: ${{ github.event.release.tag_name }}
51+
IMAGE_REPO: ${{ env.image_repository_name }}
52+
HOST_DOMAIN: ${{ env.domain }}
53+
LETSENCRYPT_EMAIL: ${{ env.letsencrypt_email }}
54+
with:
55+
input: deploy/docker-compose-template.yml
56+
output: deploy/ParcelTemplate-docker-compose.yml
57+
58+
- name: copy compose file via scp
59+
uses: appleboy/[email protected]
60+
with:
61+
host: ${{ secrets.DEPLOY_HOST }}
62+
username: ${{ secrets.DEPLOY_USERNAME }}
63+
port: ${{ secrets.DEPLOY_PORT }}
64+
key: ${{ secrets.DEPLOY_KEY }}
65+
source: "deploy/ParcelTemplate-docker-compose.yml"
66+
target: "~/"
67+
68+
- name: Set the value
69+
run: |
70+
echo "GH_TOKEN=${{ secrets.CR_PAT }}" >> $GITHUB_ENV
71+
echo "USERNAME=${{ secrets.DEPLOY_USERNAME }}" >> $GITHUB_ENV
72+
73+
- name: remote docker-compose up via ssh
74+
uses: appleboy/[email protected]
75+
env:
76+
APPTOKEN: ${{ env.GH_TOKEN }}
77+
USERNAME: ${{ env.USERNAME }}
78+
with:
79+
host: ${{ secrets.DEPLOY_HOST }}
80+
username: ${{ secrets.DEPLOY_USERNAME }}
81+
key: ${{ secrets.DEPLOY_KEY }}
82+
port: ${{ secrets.DEPLOY_PORT }}
83+
envs: APPTOKEN,USERNAME
84+
script: |
85+
echo $APPTOKEN | docker login ghcr.io -u $USERNAME --password-stdin
86+
docker-compose -f ~/deploy/ParcelTemplate-docker-compose.yml up -d

ParcelTemplate/Dockerfile

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS runtime
2+
WORKDIR /app
3+
COPY publish/* ./
4+
ENTRYPOINT ["dotnet", "ParcelTemplate.dll"]

deploy/docker-compose-template.yml

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
version: "3.9"
2+
services:
3+
ParcelTemplate:
4+
image: ghcr.io/${IMAGE_REPO}:${RELEASE_VERSION}
5+
restart: always
6+
network_mode: bridge
7+
ports:
8+
- "80"
9+
environment:
10+
VIRTUAL_HOST: ${HOST_DOMAIN}
11+
LETSENCRYPT_HOST: ${HOST_DOMAIN}
12+
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
13+
14+
networks:
15+
shared:
16+
external:
17+
name: webproxy

deploy/nginx-proxy-compose.yml

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
version: '2'
2+
3+
services:
4+
nginx-proxy:
5+
image: jwilder/nginx-proxy
6+
container_name: nginx-proxy
7+
restart: always
8+
ports:
9+
- "80:80"
10+
- "443:443"
11+
volumes:
12+
- conf:/etc/nginx/conf.d
13+
- vhost:/etc/nginx/vhost.d
14+
- html:/usr/share/nginx/html
15+
- dhparam:/etc/nginx/dhparam
16+
- certs:/etc/nginx/certs:ro
17+
- /var/run/docker.sock:/tmp/docker.sock:ro
18+
network_mode: bridge
19+
20+
letsencrypt:
21+
image: jrcs/letsencrypt-nginx-proxy-companion
22+
container_name: nginx-proxy-le
23+
restart: always
24+
environment:
25+
26+
volumes_from:
27+
- nginx-proxy
28+
volumes:
29+
- certs:/etc/nginx/certs:rw
30+
- acme:/etc/acme.sh
31+
- /var/run/docker.sock:/var/run/docker.sock:ro
32+
network_mode: bridge
33+
34+
volumes:
35+
conf:
36+
vhost:
37+
html:
38+
dhparam:
39+
certs:
40+
acme:
41+
42+
networks:
43+
default:
44+
external:
45+
name: webproxy

0 commit comments

Comments
 (0)