Skip to content

Commit 7e93b83

Browse files
authored
Initial commit
0 parents  commit 7e93b83

File tree

167 files changed

+19032
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

167 files changed

+19032
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: Build Container
2+
permissions:
3+
packages: write
4+
contents: write
5+
on:
6+
workflow_run:
7+
workflows: ["Build"]
8+
types:
9+
- completed
10+
branches:
11+
- main
12+
- master
13+
workflow_dispatch:
14+
15+
# Only update envs here if you need to change them for this workflow
16+
env:
17+
DOCKER_BUILDKIT: 1
18+
KAMAL_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
19+
KAMAL_REGISTRY_USERNAME: ${{ github.actor }}
20+
KAMAL_DEPLOY_HOST: ${{ secrets.KAMAL_DEPLOY_HOST }}
21+
22+
jobs:
23+
build-container:
24+
runs-on: ubuntu-latest
25+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
26+
steps:
27+
- name: Checkout code
28+
uses: actions/checkout@v5
29+
30+
- name: Set up environment variables
31+
run: |
32+
echo "image_repository_name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
33+
echo "repository_name=$(echo ${{ github.repository }} | cut -d '/' -f 2)" >> $GITHUB_ENV
34+
echo "repository_name_lower=$(echo ${{ github.repository }} | cut -d '/' -f 2 | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
35+
echo "org_name=$(echo ${{ github.repository }} | cut -d '/' -f 1)" >> $GITHUB_ENV
36+
37+
# This step is for the deployment of the templates only, safe to delete
38+
- name: Modify csproj for template deploy
39+
env:
40+
KAMAL_DEPLOY_IP: ${{ secrets.KAMAL_DEPLOY_IP }}
41+
if: env.KAMAL_DEPLOY_IP != null
42+
run: |
43+
sed -i 's#<ContainerLabel Include="service" Value="my-app" />#<ContainerLabel Include="service" Value="${{ env.repository_name_lower }}" />#g' MyApp/MyApp.csproj
44+
45+
- name: Check for Client directory and package.json
46+
id: check_client
47+
run: |
48+
if [ -d "MyApp.Client" ] && [ -f "MyApp.Client/package.json" ]; then
49+
echo "client_exists=true" >> $GITHUB_OUTPUT
50+
else
51+
echo "client_exists=false" >> $GITHUB_OUTPUT
52+
fi
53+
54+
- name: Setup Node.js
55+
if: steps.check_client.outputs.client_exists == 'true'
56+
uses: actions/setup-node@v3
57+
with:
58+
node-version: 24
59+
60+
- name: Install npm dependencies
61+
if: steps.check_client.outputs.client_exists == 'true'
62+
working-directory: ./MyApp.Client
63+
run: npm install
64+
65+
- name: Install x tool
66+
run: dotnet tool install -g x
67+
68+
- name: Apply Production AppSettings
69+
env:
70+
APPSETTINGS_PATCH: ${{ secrets.APPSETTINGS_PATCH }}
71+
if: env.APPSETTINGS_PATCH != null
72+
working-directory: ./MyApp
73+
run: |
74+
cat <<EOF >> appsettings.json.patch
75+
${{ secrets.APPSETTINGS_PATCH }}
76+
EOF
77+
x patch appsettings.json.patch
78+
79+
- name: Login to GitHub Container Registry
80+
uses: docker/login-action@v3
81+
with:
82+
registry: ghcr.io
83+
username: ${{ env.KAMAL_REGISTRY_USERNAME }}
84+
password: ${{ env.KAMAL_REGISTRY_PASSWORD }}
85+
86+
- name: Setup .NET
87+
uses: actions/setup-dotnet@v5
88+
with:
89+
dotnet-version: 8.0.x
90+
91+
- name: Build and push Docker image
92+
env:
93+
SERVICESTACK_LICENSE: ${{ secrets.SERVICESTACK_LICENSE }}
94+
KAMAL_DEPLOY_HOST: ${{ secrets.KAMAL_DEPLOY_HOST }}
95+
run: |
96+
dotnet publish --os linux --arch x64 -c Release -p:ContainerRepository=${{ env.image_repository_name }} -p:ContainerRegistry=ghcr.io -p:ContainerImageTags=latest -p:ContainerPort=80 -p:ContainerEnvironmentVariable="SERVICESTACK_LICENSE=${{ env.SERVICESTACK_LICENSE }}"

.github/workflows/build.yml

Lines changed: 35 additions & 0 deletions
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-latest
12+
steps:
13+
- name: checkout
14+
uses: actions/checkout@v5
15+
16+
- name: Setup dotnet
17+
uses: actions/setup-dotnet@v5
18+
with:
19+
dotnet-version: 8.0.x
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: ./MyApp.Tests
35+

.github/workflows/release.yml

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
name: Release
2+
permissions:
3+
packages: write
4+
contents: write
5+
on:
6+
workflow_run:
7+
workflows: ["Build Container"]
8+
types:
9+
- completed
10+
branches:
11+
- main
12+
- master
13+
workflow_dispatch:
14+
15+
env:
16+
DOCKER_BUILDKIT: 1
17+
KAMAL_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
18+
KAMAL_REGISTRY_USERNAME: ${{ github.actor }}
19+
SERVICESTACK_LICENSE: ${{ secrets.SERVICESTACK_LICENSE }}
20+
21+
jobs:
22+
release:
23+
runs-on: ubuntu-latest
24+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
25+
steps:
26+
- name: Checkout code
27+
uses: actions/checkout@v5
28+
29+
- name: Set up environment variables
30+
run: |
31+
echo "image_repository_name=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
32+
echo "repository_name=$(echo ${{ github.repository }} | cut -d '/' -f 2)" >> $GITHUB_ENV
33+
echo "repository_name_lower=$(echo ${{ github.repository }} | cut -d '/' -f 2 | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
34+
echo "org_name=$(echo ${{ github.repository }} | cut -d '/' -f 1)" >> $GITHUB_ENV
35+
if find . -maxdepth 2 -type f -name "Configure.Db.Migrations.cs" | grep -q .; then
36+
echo "HAS_MIGRATIONS=true" >> $GITHUB_ENV
37+
else
38+
echo "HAS_MIGRATIONS=false" >> $GITHUB_ENV
39+
fi
40+
41+
# This step is for the deployment of the templates only, safe to delete
42+
- name: Modify deploy.yml
43+
env:
44+
KAMAL_DEPLOY_IP: ${{ secrets.KAMAL_DEPLOY_IP }}
45+
if: env.KAMAL_DEPLOY_IP != null
46+
run: |
47+
sed -i "s/service: my-app/service: ${{ env.repository_name_lower }}/g" config/deploy.yml
48+
sed -i "s#image: my-user/myapp#image: ${{ env.image_repository_name }}#g" config/deploy.yml
49+
sed -i "s/- 192.168.0.1/- ${{ secrets.KAMAL_DEPLOY_IP }}/g" config/deploy.yml
50+
sed -i "s/host: my-app.example.com/host: ${{ secrets.KAMAL_DEPLOY_HOST }}/g" config/deploy.yml
51+
sed -i "s/MyApp/${{ env.repository_name }}/g" config/deploy.yml
52+
53+
- name: Login to GitHub Container Registry
54+
uses: docker/login-action@v3
55+
with:
56+
registry: ghcr.io
57+
username: ${{ env.KAMAL_REGISTRY_USERNAME }}
58+
password: ${{ env.KAMAL_REGISTRY_PASSWORD }}
59+
60+
- name: Set up SSH key
61+
uses: webfactory/[email protected]
62+
with:
63+
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
64+
65+
- name: Setup Ruby
66+
uses: ruby/setup-ruby@v1
67+
with:
68+
ruby-version: 3.3.0
69+
bundler-cache: true
70+
71+
- name: Install Kamal
72+
run: gem install kamal -v 2.3.0
73+
74+
- name: Set up Docker Buildx
75+
uses: docker/setup-buildx-action@v3
76+
with:
77+
driver-opts: image=moby/buildkit:master
78+
79+
- name: Kamal bootstrap
80+
run: |
81+
kamal server bootstrap
82+
83+
- name: Check if first run and execute kamal app boot if necessary
84+
run: |
85+
FIRST_RUN_FILE=".${{ env.repository_name }}"
86+
if ! kamal server exec --no-interactive -q "test -f $FIRST_RUN_FILE"; then
87+
kamal server exec --no-interactive -q "touch $FIRST_RUN_FILE" || true
88+
kamal deploy -q -P --version latest || true
89+
else
90+
echo "Not first run, skipping kamal app boot"
91+
fi
92+
93+
- name: Ensure file permissions
94+
run: |
95+
kamal server exec --no-interactive "mkdir -p /opt/docker/${{ env.repository_name }}/App_Data && chown -R 1654:1654 /opt/docker/${{ env.repository_name }}"
96+
97+
- name: Migration
98+
if: env.HAS_MIGRATIONS == 'true'
99+
run: |
100+
kamal server exec --no-interactive 'echo "${{ env.KAMAL_REGISTRY_PASSWORD }}" | docker login ghcr.io -u ${{ env.KAMAL_REGISTRY_USERNAME }} --password-stdin'
101+
kamal server exec --no-interactive "docker pull ghcr.io/${{ env.image_repository_name }}:latest || true"
102+
kamal app exec --no-reuse --no-interactive --version=latest "--AppTasks=migrate"
103+
104+
- name: Deploy with Kamal
105+
run: |
106+
kamal lock release -v
107+
kamal server exec --no-interactive 'echo "${{ env.KAMAL_REGISTRY_PASSWORD }}" | docker login ghcr.io -u ${{ env.KAMAL_REGISTRY_USERNAME }} --password-stdin'
108+
kamal deploy -P --version latest

.gitignore

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dotnet
4+
dist/
5+
App_Data/
6+
wwwroot/
7+
*.user
8+
*.tsbuildinfo
9+
#sqlite
10+
.vs/
11+
*.sqlite
12+
*.sqlite
13+
*.sqlite-shm
14+
*.sqlite-wal
15+
16+
# dependencies
17+
node_modules/
18+
.pnp
19+
.pnp.js
20+
21+
# testing
22+
/coverage
23+
24+
# next.js
25+
.next/
26+
out/
27+
28+
# production
29+
build/
30+
31+
# misc
32+
.DS_Store
33+
*.pem
34+
35+
# debug
36+
npm-debug.log*
37+
yarn-debug.log*
38+
yarn-error.log*
39+
40+
# local env files
41+
.env.local
42+
.env.development.local
43+
.env.test.local
44+
.env.production.local
45+
46+
# vercel
47+
.vercel
48+
.idea
49+
obj/
50+
bin/
51+
MyApp/mise.toml
52+
mise.toml

.kamal/hooks/docker-setup.sample

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
echo "Docker set up on $KAMAL_HOSTS..."

.kamal/hooks/post-deploy.sample

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/sh
2+
3+
# A sample post-deploy hook
4+
#
5+
# These environment variables are available:
6+
# KAMAL_RECORDED_AT
7+
# KAMAL_PERFORMER
8+
# KAMAL_VERSION
9+
# KAMAL_HOSTS
10+
# KAMAL_ROLE (if set)
11+
# KAMAL_DESTINATION (if set)
12+
# KAMAL_RUNTIME
13+
14+
echo "$KAMAL_PERFORMER deployed $KAMAL_VERSION to $KAMAL_DESTINATION in $KAMAL_RUNTIME seconds"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
echo "Rebooted kamal-proxy on $KAMAL_HOSTS"

.kamal/hooks/pre-build.sample

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/bin/sh
2+
3+
# A sample pre-build hook
4+
#
5+
# Checks:
6+
# 1. We have a clean checkout
7+
# 2. A remote is configured
8+
# 3. The branch has been pushed to the remote
9+
# 4. The version we are deploying matches the remote
10+
#
11+
# These environment variables are available:
12+
# KAMAL_RECORDED_AT
13+
# KAMAL_PERFORMER
14+
# KAMAL_VERSION
15+
# KAMAL_HOSTS
16+
# KAMAL_ROLE (if set)
17+
# KAMAL_DESTINATION (if set)
18+
19+
if [ -n "$(git status --porcelain)" ]; then
20+
echo "Git checkout is not clean, aborting..." >&2
21+
git status --porcelain >&2
22+
exit 1
23+
fi
24+
25+
first_remote=$(git remote)
26+
27+
if [ -z "$first_remote" ]; then
28+
echo "No git remote set, aborting..." >&2
29+
exit 1
30+
fi
31+
32+
current_branch=$(git branch --show-current)
33+
34+
if [ -z "$current_branch" ]; then
35+
echo "Not on a git branch, aborting..." >&2
36+
exit 1
37+
fi
38+
39+
remote_head=$(git ls-remote $first_remote --tags $current_branch | cut -f1)
40+
41+
if [ -z "$remote_head" ]; then
42+
echo "Branch not pushed to remote, aborting..." >&2
43+
exit 1
44+
fi
45+
46+
if [ "$KAMAL_VERSION" != "$remote_head" ]; then
47+
echo "Version ($KAMAL_VERSION) does not match remote HEAD ($remote_head), aborting..." >&2
48+
exit 1
49+
fi
50+
51+
exit 0

0 commit comments

Comments
 (0)