Skip to content

Commit c307d86

Browse files
committed
fix(ci): split website production deploy by target cluster
Read production kubeconfigs via Bob/Seguro in reusable website workflow and add RU/EU entrypoints. Render website ingress, tuf-router ingress, and certificate separately for ru and eu targets while rejecting invalid production targetCluster values. Signed-off-by: Polina Sizintseva <polina.sizintseva@flant.com>
1 parent 8469f96 commit c307d86

File tree

8 files changed

+260
-87
lines changed

8 files changed

+260
-87
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
name: Converge website production
2+
on:
3+
workflow_call:
4+
inputs:
5+
jobName:
6+
required: true
7+
type: string
8+
targetCluster:
9+
required: true
10+
type: string
11+
kubeConfigSecretPath:
12+
required: true
13+
type: string
14+
runner:
15+
required: false
16+
default: prod-github-runner-0
17+
type: string
18+
outputs:
19+
KUBECONFIG_BASE64_PRODUCTION:
20+
value: ${{ jobs.converge.outputs.kubeconfig_base64 }}
21+
22+
env:
23+
WERF_REPO: "ghcr.io/${{ github.repository_owner }}/trdl"
24+
25+
jobs:
26+
converge:
27+
name: ${{ inputs.jobName }}
28+
runs-on: ${{ inputs.runner }}
29+
permissions:
30+
contents: read
31+
id-token: write
32+
packages: write
33+
outputs:
34+
kubeconfig_base64: ${{ steps.kubeconfig.outputs.kubeconfig_base64 }}
35+
steps:
36+
- name: Checkout code
37+
uses: actions/checkout@v4
38+
with:
39+
fetch-depth: 0
40+
41+
- name: Install werf
42+
uses: werf/actions/install@v2
43+
44+
- name: Authenticate in Seguro
45+
id: vault
46+
run: |
47+
set -euo pipefail
48+
49+
audience="github-access-aud"
50+
id_token_response="$(curl -fsSL -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${audience}")"
51+
id_token="$(printf '%s' "$id_token_response" | jq -r '.value')"
52+
53+
if [[ -z "$id_token" || "$id_token" == "null" ]]; then
54+
echo "GitHub OIDC token is empty" >&2
55+
exit 1
56+
fi
57+
58+
vault_response="$(curl -fsSL -X POST "https://seguro.flant.com/v1/auth/github/login" -H "Content-Type: application/json" -d "$(jq -nc --arg role "werf-web" --arg jwt "$id_token" '{role: $role, jwt: $jwt}')")"
59+
vault_token="$(printf '%s' "$vault_response" | jq -r '.auth.client_token')"
60+
61+
if [[ -z "$vault_token" || "$vault_token" == "null" ]]; then
62+
echo "Seguro token is empty" >&2
63+
exit 1
64+
fi
65+
66+
echo "::add-mask::$vault_token"
67+
echo "vault_token=$vault_token" >> "$GITHUB_OUTPUT"
68+
69+
- name: Read and normalize kubeconfig from Bob
70+
id: kubeconfig
71+
run: |
72+
set -euo pipefail
73+
74+
response="$(curl -fsSL -H "X-Vault-Token: ${{ steps.vault.outputs.vault_token }}" "https://seguro.flant.com/v1/${{ inputs.kubeConfigSecretPath }}")"
75+
secret_value="$(printf '%s' "$response" | jq -r '.data.data["kube.config"]')"
76+
77+
if [[ -z "$secret_value" || "$secret_value" == "null" ]]; then
78+
echo "Bob kubeconfig secret is empty" >&2
79+
exit 1
80+
fi
81+
82+
if printf '%s' "$secret_value" | base64 -d >/tmp/kubeconfig-decoded 2>/dev/null && grep -q '^apiVersion:' /tmp/kubeconfig-decoded; then
83+
kubeconfig_base64="$secret_value"
84+
else
85+
kubeconfig_base64="$(printf '%s' "$secret_value" | base64 | tr -d '\n')"
86+
fi
87+
88+
echo "::add-mask::$kubeconfig_base64"
89+
echo "kubeconfig_base64=$kubeconfig_base64" >> "$GITHUB_OUTPUT"
90+
91+
- name: Converge
92+
run: |
93+
werf_env_file="$(werf ci-env github --as-file)"
94+
. "$werf_env_file"
95+
werf converge --set global.targetCluster=${{ inputs.targetCluster }}
96+
env:
97+
WERF_DIR: "docs"
98+
WERF_ENV: "production"
99+
WERF_KUBE_CONFIG_BASE64: ${{ steps.kubeconfig.outputs.kubeconfig_base64 }}
100+
KUBECONFIG_BASE64_PRODUCTION: ${{ steps.kubeconfig.outputs.kubeconfig_base64 }}
101+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
102+
103+
- name: Summary
104+
run: |
105+
cat <<EOF >> "$GITHUB_STEP_SUMMARY"
106+
## ${{ inputs.jobName }}
107+
108+
- Event: ${{ github.event_name }}
109+
- Target cluster mode: ${{ inputs.targetCluster }}
110+
- Seguro role: werf-web
111+
- Secret path: ${{ inputs.kubeConfigSecretPath }}
112+
- Secret field used: kube.config
113+
- Helm switch: global.targetCluster=${{ inputs.targetCluster }}
114+
EOF
115+
116+
notification:
117+
name: Notification
118+
if: false
119+
needs: converge
120+
uses: werf/common-ci/.github/workflows/notification.yml@main
121+
secrets:
122+
loopNotificationGroup: ${{ secrets.LOOP_NOTIFICATION_GROUP }}
123+
webhook: ${{ secrets.LOOP_NOTIFICATION_WEBHOOK }}
124+
notificationChannel: ${{ secrets.LOOP_NOTIFICATION_CHANNEL }}

.github/workflows/website_converge.yml

Lines changed: 0 additions & 44 deletions
This file was deleted.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Converge website EU
2+
on:
3+
push:
4+
branches: [main]
5+
paths:
6+
- ".github/workflows/_website_converge.yml"
7+
- ".github/workflows/website_converge_eu.yml"
8+
- "docs/**"
9+
workflow_dispatch:
10+
11+
jobs:
12+
converge:
13+
permissions:
14+
contents: read
15+
id-token: write
16+
packages: write
17+
uses: ./.github/workflows/_website_converge.yml
18+
secrets: inherit
19+
with:
20+
jobName: Converge site to Production EU
21+
targetCluster: eu
22+
runner: prod-github-runner-0
23+
kubeConfigSecretPath: projects/data/b454e6aa-39f0-45f4-aa7c-a9465ab154cb/KUBE_CONFIG
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Converge website RU
2+
on:
3+
push:
4+
branches: [fix/ci/split-website-production-deploy]
5+
paths:
6+
- ".github/workflows/_website_converge.yml"
7+
- ".github/workflows/website_converge_ru.yml"
8+
- "docs/**"
9+
workflow_dispatch:
10+
11+
jobs:
12+
converge:
13+
permissions:
14+
contents: read
15+
id-token: write
16+
packages: write
17+
uses: ./.github/workflows/_website_converge.yml
18+
secrets: inherit
19+
with:
20+
jobName: Converge site to Production RU
21+
targetCluster: ru
22+
runner: prod-github-runner-0
23+
kubeConfigSecretPath: projects/data/b454e6aa-39f0-45f4-aa7c-a9465ab154cb/KUBE_CONFIG_RU

docs/.helm/templates/20-ingress-tuf-router.yaml

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,39 @@
1-
{{- $host := pluck .Values.werf.env .Values.host | first | default .Values.host._default }}
2-
{{- if hasPrefix "review" .Values.werf.env }}
3-
{{- $host = ( printf "%s.%s" .Values.werf.env (pluck "dev" .Values.host | first | default .Values.host._default ) | lower ) }}
1+
{{- $env := .Values.werf.env }}
2+
{{- $host := pluck $env .Values.host | first | default .Values.host._default }}
3+
{{- if hasPrefix "review" $env }}
4+
{{- $host = ( printf "%s.%s" $env (pluck "dev" .Values.host | first | default .Values.host._default ) | lower ) }}
45
{{- end }}
56
{{- $ingressClassName := pluck .Values.global.env .Values.ingressClassName | first | default .Values.ingressClassName._default | quote }}
6-
7+
{{- $targetCluster := include "targetCluster" . | trim }}
8+
{{- $isProduction := eq .Values.global.env "production" }}
9+
{{- $ruHost := include "ruHost" $host | trim }}
710
apiVersion: networking.k8s.io/v1
811
kind: Ingress
912
metadata:
1013
name: tuf-router
11-
annotations:
1214
spec:
1315
ingressClassName: {{ $ingressClassName }}
1416
tls:
1517
- hosts:
16-
- {{ $host }}
17-
{{- if eq .Values.global.env "production" }}
18-
- ru.{{ $host }}
18+
{{- if $isProduction }}
19+
{{- if eq $targetCluster "ru" }}
20+
- {{ $ruHost }}
1921
{{- else }}
20-
- ru-{{ $host }}
22+
- {{ $host }}
2123
{{- end }}
22-
{{- if eq .Values.global.env "production" }}
2324
secretName: tls-{{ $host }}
2425
{{- else }}
26+
- {{ $host }}
27+
- ru-{{ $host }}
2528
secretName: {{ pluck .Values.global.env .Values.ingressSecretName | first | default .Values.ingressSecretName._default }}
2629
{{- end }}
2730
rules:
31+
{{- if $isProduction }}
32+
{{- if eq $targetCluster "ru" }}
33+
- host: {{ $ruHost }}
34+
{{- else }}
2835
- host: {{ $host }}
36+
{{- end }}
2937
http:
3038
paths:
3139
- path: /targets
@@ -42,11 +50,25 @@ spec:
4250
name: tuf-router
4351
port:
4452
name: http
45-
{{- if eq .Values.global.env "production" }}
46-
- host: ru.{{ $host }}
4753
{{- else }}
54+
- host: {{ $host }}
55+
http:
56+
paths:
57+
- path: /targets
58+
pathType: Prefix
59+
backend:
60+
service:
61+
name: tuf-router
62+
port:
63+
name: http
64+
- path: /download
65+
pathType: Prefix
66+
backend:
67+
service:
68+
name: tuf-router
69+
port:
70+
name: http
4871
- host: ru-{{ $host }}
49-
{{- end }}
5072
http:
5173
paths:
5274
- path: /targets
@@ -63,3 +85,4 @@ spec:
6385
name: tuf-router
6486
port:
6587
name: http
88+
{{- end }}

0 commit comments

Comments
 (0)