Skip to content

Commit

Permalink
Merge pull request #21 from vividroyjeong/keycloak-deploy
Browse files Browse the repository at this point in the history
Keycloak deploy #2
  • Loading branch information
vividroyjeong authored Sep 10, 2024
2 parents 3dbad86 + fba36b6 commit c80a4d0
Show file tree
Hide file tree
Showing 9 changed files with 257 additions and 28 deletions.
180 changes: 180 additions & 0 deletions .github/workflows/.deployer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
name: .Helm Deployer

on:
workflow_call:
inputs:
### Required
# Only secrets!

### Typical / recommended
atomic:
description: Atomic deployment? That means fail all or nothing
default: true
required: false
type: string
directory:
description: Chart directory
default: 'charts/app'
required: false
type: string
environment:
description: Environment name; omit for PRs
required: false
type: string
oc_server:
default: https://api.silver.devops.gov.bc.ca:6443
description: 'OpenShift server'
required: false
type: string
params:
description: 'Extra parameters to pass to helm upgrade'
default: ''
required: false
type: string
tag:
description: Specify a tag to deploy; defaults to PR number
required: false
type: string
triggers:
description: Paths used to trigger a deployment; e.g. ('./backend/' './frontend/)
required: false
type: string

### Usually a bad idea / not recommended
timeout-minutes:
description: 'Timeout minutes'
default: 10
required: false
type: number
values:
description: 'Values file'
default: 'values.yaml'
required: false
type: string

outputs:
triggered:
description: 'Has a deployment has been triggered?'
value: ${{ jobs.deployer.outputs.triggered }}

secrets:
oc_namespace:
description: OpenShift namespace
required: true
oc_token:
description: OpenShift token
required: true

jobs:
deployer:
name: Helm
environment: ${{ inputs.environment }}
runs-on: ubuntu-22.04
outputs:
triggered: ${{ steps.triggers.outputs.triggered }}
steps:
### Triggers, tag and release

# Check triggers (omitted or matched) for deployment
- uses: bcgov-nr/action-diff-triggers@v0.2.0
id: triggers
with:
triggers: ${{ inputs.triggers }}

# Variables
- if: steps.triggers.outputs.triggered == 'true'
id: pr
uses: bcgov-nr/action-get-pr@v0.0.1
- if: steps.triggers.outputs.triggered == 'true'
id: vars
run: |
# Vars: tag and release
# Tag defaults to PR number, but can be overridden by inputs.tag
tag=${{ inputs.tag || steps.pr.outputs.pr }}
# Release name includes run numbers to ensure uniqueness
release=${{ github.event.repository.name }}-${{ inputs.environment || steps.pr.outputs.pr }}
# Summary
echo "tag=${tag}"
echo "release=${release}"
# Output
echo "tag=${tag}" >> $GITHUB_OUTPUT
echo "release=${release}" >> $GITHUB_OUTPUT
### Deploy

# OC Login
- if: steps.triggers.outputs.triggered == 'true'
run: |
# OC Login
oc login --token=${{ secrets.oc_token }} --server=${{ inputs.oc_server }}
oc project ${{ secrets.oc_namespace }} # Safeguard!
# Only stop pre-existing deployments on PRs (status = pending-upgrade)
- if: steps.triggers.outputs.triggered == 'true' && github.event_name == 'pull_request'
run: |
# Interrupt any previous deployments (PR only)
PREVIOUS=$(helm status ${{ steps.vars.outputs.release }} -o json | jq .info.status || true)
if [[ ${PREVIOUS} =~ pending ]]; then
echo "Rollback triggered"
helm rollback ${{ steps.vars.outputs.release }} || \
helm uninstall ${{ steps.vars.outputs.release }}
fi
# Package Helm chart
- if: steps.triggers.outputs.triggered == 'true'
uses: actions/checkout@v4
- if: steps.triggers.outputs.triggered == 'true'
working-directory: ${{ inputs.directory }}
run: |
# Helm package
sed -i 's/^name:.*/name: ${{ github.event.repository.name }}/' Chart.yaml
helm package -u . --app-version="tag-${{ steps.vars.outputs.tag }}_run-${{ github.run_number }}" --version=${{ steps.pr.outputs.pr }}
# Deploy Helm chart as atomic, with timeout
- if: steps.triggers.outputs.triggered == 'true' && inputs.atomic != 'false'
working-directory: ${{ inputs.directory }}
run: |
# Helm upgrade/rollout - atomic, timeout
helm upgrade \
--set-string global.repository=${{ github.repository }} \
--set-string global.tag=${{ steps.vars.outputs.tag }} \
--set frontend.env.VITE_SSO_AUTH_SERVER_URL=${{ secrets.VITE_SSO_AUTH_SERVER_URL }} \
--set frontend.env.VITE_SSO_CLIENT_ID=${{ secrets.VITE_SSO_CLIENT_ID }} \
--set frontend.env.VITE_SSO_REALM=${{ secrets.VITE_SSO_REALM }} \
--set frontend.env.VITE_SSO_REDIRECT_URI=${{ secrets.VITE_SSO_REDIRECT_URI }} \
${{ inputs.params }} \
--install --wait --atomic ${{ steps.vars.outputs.release }} \
--timeout ${{ inputs.timeout-minutes }}m \
--values ${{ inputs.values }} \
./${{ github.event.repository.name }}-${{ steps.pr.outputs.pr }}.tgz
# Deploy Helm chart without atomic or timeout
- if: steps.triggers.outputs.triggered == 'true' && inputs.atomic == 'false'
working-directory: ${{ inputs.directory }}
run: |
# Helm upgrade/rollout - non-atomic, no timeout
helm upgrade \
--set-string global.repository=${{ github.repository }} \
--set-string global.tag=${{ steps.vars.outputs.tag }} \
${{ inputs.params }} \
${{ steps.vars.outputs.release }} \
--install --wait --values ${{ inputs.values }} \
./${{ github.event.repository.name }}-${{ steps.pr.outputs.pr }}.tgz
# Helm release history
- if: steps.triggers.outputs.triggered == 'true'
run: |
# Helm release history
helm history ${{ steps.vars.outputs.release }}
### Cleanup

# Completed pod cleanup
- if: steps.triggers.outputs.triggered == 'true'
run: |
# Completed pod cleanup
oc delete po --field-selector=status.phase==Succeeded || true
11 changes: 6 additions & 5 deletions .github/workflows/openshift-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,16 @@ jobs:
deploys:
name: Deploys
needs: [builds]
uses: bcgov/quickstart-openshift-helpers/.github/workflows/.deployer.yml@v0.6.1
secrets:
oc_namespace: ${{ secrets.OC_NAMESPACE }}
oc_token: ${{ secrets.OC_TOKEN }}
uses: ./.github/workflows/.deployer.yml
secrets: inherit
# oc_namespace: ${{ secrets.OC_NAMESPACE }}
# oc_token: ${{ secrets.OC_TOKEN }}
with:
environment: dev
values: "values-dev.yaml"
triggers: ('backend/' 'frontend/' 'migrations/')
params: --set global.secrets.persist=false
params: |
--set global.secrets.persist=false \
# tests:
# name: Tests
Expand Down
8 changes: 8 additions & 0 deletions charts/app/templates/frontend/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ spec:
value: "http://{{ .Release.Name }}-backend"
- name: LOG_LEVEL
value: "info"
- name: VITE_SSO_AUTH_SERVER_URL
value: {{ .Values.frontend.env.VITE_SSO_AUTH_SERVER_URL | quote }}
- name: VITE_SSO_CLIENT_ID
value: {{ .Values.frontend.env.VITE_SSO_CLIENT_ID | quote }}
- name: VITE_SSO_REALM
value: {{ .Values.frontend.env.VITE_SSO_REALM | quote }}
- name: VITE_SSO_REDIRECT_URI
value: {{ .Values.frontend.env.VITE_SSO_REALM | quote }}
ports:
- name: http
containerPort: 3000
Expand Down
5 changes: 5 additions & 0 deletions charts/app/values-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ frontend:
pdb:
enabled: false # enable it in PRODUCTION for having pod disruption budget.
minAvailable: 1 # the minimum number of pods that must be available during the disruption budget.
env:
VITE_SSO_AUTH_SERVER_URL: ~
VITE_SSO_CLIENT_ID: ~
VITE_SSO_REALM: ~
VITE_SSO_REDIRECT_URI: ~

crunchy: # enable it for TEST and PROD, for PR based pipelines simply use single postgres
enabled: false
Expand Down
8 changes: 7 additions & 1 deletion frontend/Caddyfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@
}
level {$LOG_LEVEL}
}
handle /env.js {
header {
Content-Type text/javascript
}
respond `window.config={"VITE_SSO_AUTH_SERVER_URL":"{$VITE_SSO_AUTH_SERVER_URL}", "VITE_SSO_CLIENT_ID":"{$VITE_SSO_CLIENT_ID}", "VITE_SSO_REALM":"{$VITE_SSO_REALM}", "VITE_SSO_REDIRECT_URI":"{$VITE_SSO_REDIRECT_URI}"};`
}
root * /srv
encode zstd gzip
file_server
@spa_router {
not path /api/*
not path /api/* /env.js
file {
try_files {path} /index.html
}
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
declare global {
// eslint-disable-next-line no-unused-vars
interface Window {
config: any
}
}

export const env: Record<string, any> = { ...import.meta.env, ...window.config }
22 changes: 11 additions & 11 deletions frontend/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createApp } from 'vue'
import { registerPlugins } from '@/plugins'
import App from './App.vue'
// import { initializeKeycloak } from '@/services/keycloak'
import { initializeKeycloak } from '@/services/keycloak'

import '@bcgov/bc-sans/css/BCSans.css'
import '@/styles/style.scss'
Expand All @@ -17,17 +17,17 @@ const bootstrap = async () => {
* NOTE: Disabled user authentication for deploy testing.
*/

// try {
// const keycloak = await initializeKeycloak()
try {
const keycloak = await initializeKeycloak()

// if (keycloak?.authenticated) {
app.mount('#app')
// } else {
// keycloak?.login()
// }
// } catch (error) {
// console.error('Failed to initialize Keycloak:', error)
// }
if (keycloak?.authenticated) {
app.mount('#app')
} else {
keycloak?.login()
}
} catch (error) {
console.error('Failed to initialize Keycloak:', error)
}
}

bootstrap()
25 changes: 14 additions & 11 deletions frontend/src/services/keycloak.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@ import { useAuthStore } from '@/stores/common/authStore'
import type { KeycloakInitOptions } from 'keycloak-js'
import { KEYCLOAK } from '@/constants/constants'
import { Util } from '@/utils/util'
import { env } from '@/env'

let keycloakInstance: Keycloak | null = null

const ssoAuthServerUrl = env.VITE_SSO_AUTH_SERVER_URL
const ssoClientId = env.VITE_SSO_CLIENT_ID
const ssoRealm = env.VITE_SSO_REALM
const ssoRedirectUrl = env.VITE_SSO_REDIRECT_URI

const createKeycloakInstance = (): Keycloak => {
if (!keycloakInstance) {
keycloakInstance = new Keycloak({
url: `${import.meta.env.VITE_SSO_AUTH_SERVER_URL}` as string,
realm: `${import.meta.env.VITE_SSO_REALM}` as string,
clientId: `${import.meta.env.VITE_SSO_CLIENT_ID}` as string,
url: `${ssoAuthServerUrl}` as string,
realm: `${ssoRealm}` as string,
clientId: `${ssoClientId}` as string,
})
}
return keycloakInstance
Expand All @@ -26,7 +32,7 @@ const initOptions: KeycloakInitOptions = {
}

const loginOptions = {
redirectUri: import.meta.env.VITE_SSO_REDIRECT_URI as string,
redirectUri: ssoRedirectUrl as string,
}

export const initializeKeycloak = async (): Promise<Keycloak | undefined> => {
Expand Down Expand Up @@ -103,10 +109,7 @@ const validateAccessToken = (accessToken: string): boolean => {
const tokenParsed = JSON.parse(atob(accessToken.split('.')[1]))

// Validate issuer
if (
tokenParsed.iss !==
`${import.meta.env.VITE_SSO_AUTH_SERVER_URL}/realms/${import.meta.env.VITE_SSO_REALM}`
) {
if (tokenParsed.iss !== `${ssoAuthServerUrl}/realms/${ssoRealm}`) {
console.error('Invalid token issuer.')
return false
}
Expand Down Expand Up @@ -213,10 +216,10 @@ export const logout = (): void => {
const authStore = useAuthStore()
authStore.clearUser()
window.location.href = `https://logon7.gov.bc.ca/clp-cgi/logoff.cgi?retnow=1&returl=${encodeURIComponent(
`${import.meta.env.VITE_SSO_AUTH_SERVER_URL}/realms/${import.meta.env.VITE_SSO_REALM}/protocol/openid-connect/logout?post_logout_redirect_uri=` +
import.meta.env.VITE_SSO_REDIRECT_URI +
`${ssoAuthServerUrl}/realms/${ssoRealm}/protocol/openid-connect/logout?post_logout_redirect_uri=` +
ssoRedirectUrl +
'&client_id=' +
import.meta.env.VITE_SSO_CLIENT_ID,
ssoClientId,
)}`
}

Expand Down
18 changes: 18 additions & 0 deletions frontend/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ import packageVersion from 'vite-plugin-package-version'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
{
name: 'build-html',
apply: 'build',
transformIndexHtml: (html) => {
return {
html,
tags: [
{
tag: 'script',
attrs: {
src: '/env.js',
},
injectTo: 'head',
},
],
}
},
},
Vue(),
packageVersion(),
Vuetify({
Expand Down

0 comments on commit c80a4d0

Please sign in to comment.