Skip to content

Commit 1173b3b

Browse files
committed
Deploy previews
1 parent 4679c3a commit 1173b3b

File tree

1 file changed

+217
-0
lines changed

1 file changed

+217
-0
lines changed
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
name: "Deploy Preview"
2+
3+
env:
4+
TEST_USERNAME: "preview-user"
5+
TEST_PASSWORD: "P@sswo3d"
6+
TEST_SUPERADMIN_USER: "preview-admin"
7+
TEST_SUPERADMIN_PASSWORD: "P@sswo3d-admin"
8+
NEBARI_IMAGE_TAG: "main"
9+
PYTHON_VERSION: "3.11"
10+
11+
on:
12+
pull_request:
13+
types: [labeled, unlabeled]
14+
15+
concurrency:
16+
group: deploy-preview-${{ github.event.pull_request.number }}
17+
cancel-in-progress: true
18+
19+
jobs:
20+
deploy-preview:
21+
if: github.event.action == 'labeled' && github.event.label.name == 'deploy-preview'
22+
runs-on: "cirun-runner--${{ github.run_id }}"
23+
defaults:
24+
run:
25+
shell: bash -l {0}
26+
env:
27+
APP_DNS: "nebari-pr-${{ github.event.pull_request.number }}.nebari.dev"
28+
SSH_DNS: "nebari-pr-${{ github.event.pull_request.number }}-ssh.nebari.dev"
29+
PREVIEW_DIR: "preview-pr-${{ github.event.pull_request.number }}"
30+
steps:
31+
- name: "Checkout Infrastructure"
32+
uses: actions/checkout@main
33+
with:
34+
fetch-depth: 0
35+
36+
- name: "Checkout PR"
37+
run: |
38+
git fetch origin pull/${{ github.event.pull_request.number }}/head:pr-${{ github.event.pull_request.number }}
39+
git checkout pr-${{ github.event.pull_request.number }}
40+
41+
# https://kind.sigs.k8s.io/docs/user/known-issues/#pod-errors-due-to-too-many-open-files
42+
- name: "Update inotify ulimit"
43+
run: |
44+
sudo sysctl fs.inotify.max_user_watches=524288
45+
sudo sysctl fs.inotify.max_user_instances=512
46+
47+
- name: Setup runner for local deployment
48+
uses: ./.github/actions/setup-local
49+
50+
- name: Set up Python
51+
uses: conda-incubator/setup-miniconda@v3
52+
env:
53+
CONDA: /home/runnerx/miniconda3
54+
with:
55+
auto-update-conda: true
56+
python-version: ${{ env.PYTHON_VERSION }}
57+
miniconda-version: "latest"
58+
activate-environment: nebari
59+
60+
- name: Install JQ
61+
run: |
62+
sudo apt-get update
63+
sudo apt-get install jq -y
64+
65+
- name: Install Nebari
66+
run: pip install .[dev]
67+
68+
- name: Initialize Nebari config for preview deployment
69+
id: init
70+
run: |
71+
mkdir -p ${{ env.PREVIEW_DIR }}
72+
cd ${{ env.PREVIEW_DIR }}
73+
74+
nebari init local --domain ${{ env.APP_DNS }} --namespace dev --auth-provider password
75+
76+
echo "domain=${{ env.APP_DNS }}" >> $GITHUB_OUTPUT
77+
echo "directory=${{ env.PREVIEW_DIR }}" >> $GITHUB_OUTPUT
78+
echo "config=nebari-config.yaml" >> $GITHUB_OUTPUT
79+
80+
- name: Deploy Nebari Preview
81+
working-directory: ${{ steps.init.outputs.directory }}
82+
run: nebari deploy --config ${{ steps.init.outputs.config }} --disable-prompt
83+
84+
- name: Health check
85+
uses: ./.github/actions/health-check
86+
with:
87+
domain: ${{ steps.init.outputs.domain }}
88+
89+
- name: Create preview users
90+
working-directory: ${{ steps.init.outputs.directory }}
91+
run: |
92+
nebari keycloak add-user --user "${TEST_USERNAME}" -p "${TEST_PASSWORD}" --config ${{ steps.init.outputs.config }}
93+
nebari keycloak add-user --user "${TEST_SUPERADMIN_USER}" -p "${TEST_SUPERADMIN_PASSWORD}" --config ${{ steps.init.outputs.config }} --groups superadmin
94+
nebari keycloak list-users --config ${{ steps.init.outputs.config }}
95+
96+
- name: Await Workloads
97+
uses: jupyterhub/action-k8s-await-workloads@v3
98+
with:
99+
workloads: "" # all
100+
namespace: "dev"
101+
timeout: 300
102+
max-restarts: 3
103+
104+
- name: Setup FRP Tunnel
105+
uses: cirunlabs/frp-tunnel-action@main
106+
with:
107+
timeout_minutes: 0
108+
frp_client_config: |
109+
serverAddr = "frp.nebari.dev"
110+
serverPort = 7000
111+
auth.method = "token"
112+
auth.token = "${{ secrets.FRP_TOKEN }}"
113+
114+
[[proxies]]
115+
name = "nebari-ssh--${{ github.run_id }}-${{ github.sha }}"
116+
type = "tcpmux"
117+
multiplexer = "httpconnect"
118+
localIP = "127.0.0.1"
119+
localPort = 22
120+
customDomains = ["${{ env.SSH_DNS }}"]
121+
122+
[[proxies]]
123+
name = "nebari-http--${{ github.run_id }}-${{ github.sha }}"
124+
type = "https"
125+
localIP = "127.0.0.1"
126+
localPort = 443
127+
customDomains = ["${{ env.APP_DNS }}"]
128+
129+
- name: Comment on PR with deployment info
130+
uses: actions/github-script@v7
131+
with:
132+
script: |
133+
const { data: comments } = await github.rest.issues.listComments({
134+
owner: context.repo.owner,
135+
repo: context.repo.repo,
136+
issue_number: ${{ github.event.pull_request.number }}
137+
});
138+
139+
const existingComment = comments.find(comment =>
140+
comment.body.includes('🚀 Deploy Preview') && comment.user.login === 'github-actions[bot]'
141+
);
142+
143+
const body = `## 🚀 Deploy Preview Ready!
144+
145+
Your Nebari preview deployment is now available:
146+
147+
**🌐 Preview URL:** https://${{ env.APP_DNS }}
148+
149+
**👤 Test Credentials:**
150+
- **User:** \`${{ env.TEST_USERNAME }}\` / \`${{ env.TEST_PASSWORD }}\`
151+
- **Admin:** \`${{ env.TEST_SUPERADMIN_USER }}\` / \`${{ env.TEST_SUPERADMIN_PASSWORD }}\`
152+
153+
**🔗 SSH Access:**
154+
\`\`\`bash
155+
ssh ubuntu@${{ env.SSH_DNS }}
156+
\`\`\`
157+
158+
**🔄 Auto-cleanup:** This preview will be automatically cleaned up when the \`deploy-preview\` label is removed or the runner terminates.
159+
160+
---
161+
_This preview was generated from commit ${context.sha.slice(0, 7)}_`;
162+
163+
if (existingComment) {
164+
await github.rest.issues.updateComment({
165+
owner: context.repo.owner,
166+
repo: context.repo.repo,
167+
comment_id: existingComment.id,
168+
body: body
169+
});
170+
} else {
171+
await github.rest.issues.createComment({
172+
owner: context.repo.owner,
173+
repo: context.repo.repo,
174+
issue_number: ${{ github.event.pull_request.number }},
175+
body: body
176+
});
177+
}
178+
179+
cleanup-preview:
180+
if: github.event.action == 'unlabeled' && github.event.label.name == 'deploy-preview'
181+
runs-on: ubuntu-latest
182+
steps:
183+
- name: Comment on PR about cleanup
184+
uses: actions/github-script@v7
185+
with:
186+
script: |
187+
const { data: comments } = await github.rest.issues.listComments({
188+
owner: context.repo.owner,
189+
repo: context.repo.repo,
190+
issue_number: ${{ github.event.pull_request.number }}
191+
});
192+
193+
const existingComment = comments.find(comment =>
194+
comment.body.includes('🚀 Deploy Preview') && comment.user.login === 'github-actions[bot]'
195+
);
196+
197+
const body = `## 🧹 Deploy Preview Cleaned Up
198+
199+
The preview deployment for PR #${{ github.event.pull_request.number }} has been cleaned up.
200+
201+
To create a new preview, add the \`deploy-preview\` label again.`;
202+
203+
if (existingComment) {
204+
await github.rest.issues.updateComment({
205+
owner: context.repo.owner,
206+
repo: context.repo.repo,
207+
comment_id: existingComment.id,
208+
body: body
209+
});
210+
} else {
211+
await github.rest.issues.createComment({
212+
owner: context.repo.owner,
213+
repo: context.repo.repo,
214+
issue_number: ${{ github.event.pull_request.number }},
215+
body: body
216+
});
217+
}

0 commit comments

Comments
 (0)