-
Notifications
You must be signed in to change notification settings - Fork 0
151 lines (147 loc) · 6.2 KB
/
Copy pathdeploy.yml
File metadata and controls
151 lines (147 loc) · 6.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
name: Deploy
on:
workflow_dispatch:
concurrency:
group: deploy-docs-tigrbl-com
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install uv
run: python -m pip install --upgrade uv
- name: Install Python docs dependencies
run: uv sync --frozen --group dev
- run: npm ci
- run: npm run check
- run: npm run build
- name: Validate Docker proxy target
run: npm run proxy:target-check
- uses: actions/upload-artifact@v4
with:
name: docs-site
path: site
if-no-files-found: error
deploy:
needs: build
runs-on: deployment
environment: deployment
env:
NPM_BASE_URL: ${{ secrets.NPM_BASE_URL }}
NPM_IDENTITY: ${{ secrets.NPM_IDENTITY }}
NPM_SECRET: ${{ secrets.NPM_SECRET || secrets.NPM_PASSWORD || secrets.NGINX_PROXY_MANAGER_SECRET }}
NPM_TIMEOUT_S: 30
NAMECHEAP_API_USER: ${{ secrets.NAMECHEAP_API_USER }}
NAMECHEAP_API_KEY: ${{ secrets.NAMECHEAP_API_KEY }}
NAMECHEAP_USERNAME: ${{ secrets.NAMECHEAP_USERNAME }}
NAMECHEAP_CLIENT_IP: ${{ secrets.NAMECHEAP_CLIENT_IP }}
SITE_SERVER_IP: ${{ secrets.SITE_SERVER_IP || secrets.SERVER_IP || secrets.DEPLOY_SERVER_IP }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- uses: actions/download-artifact@v4
with:
name: docs-site
path: site
- name: Install npmctl from PyPI
run: python -m pip install --upgrade "npmctl>=0.3.10" "npmctl-namecheap>=0.3.10"
- name: Validate npmctl orchestration secrets
shell: bash
run: |
missing=0
for name in NPM_BASE_URL NPM_IDENTITY NPM_SECRET NAMECHEAP_API_USER NAMECHEAP_API_KEY NAMECHEAP_USERNAME NAMECHEAP_CLIENT_IP SITE_SERVER_IP; do
if [ -z "${!name}" ]; then
echo "Missing required secret-backed environment variable: ${name}"
missing=1
fi
done
exit ${missing}
- name: Validate Docker proxy target
run: npm run proxy:target-check
- name: Render proxy desired state
shell: bash
run: |
mkdir -p .tmp/npmctl
sed "s/__NPM_IDENTITY__/${NPM_IDENTITY}/g" desired-state/proxy.yaml > .tmp/npmctl/proxy.yaml
- name: Validate npmctl proxy desired state
run: npmctl validate .tmp/npmctl/proxy.yaml
- name: Build site image
run: docker-compose -f docker-compose.yaml build docs-tigrbl-com
- name: Restart site container
run: |
docker-compose -f docker-compose.yaml stop docs-tigrbl-com || true
docker-compose -f docker-compose.yaml rm -f docs-tigrbl-com || true
docker rm -f docs-tigrbl-com || true
docker-compose -f docker-compose.yaml up -d --no-build --force-recreate --no-deps docs-tigrbl-com
- name: Render DNS desired state
shell: bash
run: |
mkdir -p .tmp
sed "s/__SITE_SERVER_IP__/${SITE_SERVER_IP}/g" desired-state/dns.yaml > .tmp/dns.yaml
- name: Validate DNS desired state
run: npmctl validate .tmp/dns.yaml
- name: Validate Namecheap provider
run: npmctl dns doctor --provider namecheap
- name: Normalize Namecheap DNS records
run: python scripts/namecheap-normalize-dns.py .tmp/dns.yaml
- name: Apply Namecheap DNS with npmctl
continue-on-error: true
run: npmctl apply .tmp/dns.yaml --owner docs-tigrbl-com
- name: Check Nginx Proxy Manager API schema
continue-on-error: true
run: npmctl schema check
- name: Adopt matching unmanaged NPM resources
continue-on-error: true
run: npmctl adopt .tmp/npmctl/proxy.yaml --owner docs-tigrbl-com --force
- name: Plan Nginx Proxy Manager host with npmctl
run: npmctl plan .tmp/npmctl/proxy.yaml --owner docs-tigrbl-com
- name: Apply Nginx Proxy Manager host with npmctl
run: npmctl apply .tmp/npmctl/proxy.yaml --owner docs-tigrbl-com
- name: Verify public HTTPS and HTTP redirect
shell: bash
run: |
node <<'NODE'
const fs = require('node:fs');
const { spawnSync } = require('node:child_process');
const manifest = JSON.parse(fs.readFileSync('site.manifest.json', 'utf8'));
const primary = manifest.host || manifest.site;
const hosts = [primary];
if (!primary.startsWith('docs.') && !primary.startsWith('www.')) {
hosts.push(`www.${primary}`);
}
let failed = false;
for (const host of hosts) {
const https = spawnSync('curl', ['-I', '-sS', '--max-time', '25', '-o', '/dev/null', '-w', '%{http_code}|%{errormsg}', `https://${host}/`], { encoding: 'utf8' });
const httpsOut = `${https.stdout || ''}${https.stderr || ''}`.trim();
const httpsCode = Number((https.stdout || '').split('|')[0]);
console.log(`${host} HTTPS ${httpsOut}`);
if (https.status !== 0 || httpsCode !== 200 || httpsOut.includes('502') || /timed out|Could not resolve|Failed to connect/i.test(httpsOut)) {
failed = true;
}
const http = spawnSync('curl', ['-I', '-sS', '--max-time', '25', '-o', '/dev/null', '-w', '%{http_code}|%{redirect_url}|%{errormsg}', `http://${host}/`], { encoding: 'utf8' });
const httpOut = `${http.stdout || ''}${http.stderr || ''}`.trim();
const httpCode = Number((http.stdout || '').split('|')[0]);
console.log(`${host} HTTP ${httpOut}`);
if (http.status !== 0 || httpCode < 300 || httpCode >= 400 || httpOut.includes('502') || /timed out|Could not resolve|Failed to connect/i.test(httpOut)) {
failed = true;
}
}
if (failed) process.exit(1);
NODE