Compare commits
16 Commits
33da34151d
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb590af8d7 | ||
|
|
1209e50c58 | ||
|
|
2fb8f5ec6a | ||
|
|
0a8b0b0120 | ||
|
|
1c55b0b562 | ||
|
|
c0917724f2 | ||
|
|
242ddecfa4 | ||
|
|
5a682a9618 | ||
|
|
3bdff103aa | ||
|
|
9d5786cda8 | ||
|
|
e63b3aa56f | ||
|
|
0be80ebb4a | ||
|
|
a4f3f5abf8 | ||
|
|
184a5b4e0f | ||
|
|
48a8d13580 | ||
|
|
d2c361de4a |
@@ -1,23 +0,0 @@
|
||||
REACT_APP_AUTH_CALLBACK_URL=https://ota-admin.cec-euprd.fiskerinc.com
|
||||
REACT_APP_AUTH_SERVICE_URL=https://gw.cec-prd.fiskerinc.com/compute_auth
|
||||
REACT_APP_CERT_SERVICE_URL=https://gw.cec-prd.fiskerinc.com/certificate
|
||||
REACT_APP_ENV=cec-euprd
|
||||
REACT_APP_MAGNA_PROVIDER=Magna
|
||||
REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
|
||||
REACT_APP_OTA_SERVICE_URL=https://gw.cec-euprd.fiskerinc.com/ota_update
|
||||
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
||||
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
||||
REACT_APP_SUPERSET_URL=https://superset.cec-euprd.fiskerinc.com
|
||||
REACT_APP_ROLE_CREATE=e92f2b3e-1b80-42e5-9483-8ae648224dc6
|
||||
REACT_APP_ROLE_READ_ONLY=ae5123e3-7a6a-4ca9-947b-a0f184f82cbd
|
||||
REACT_APP_ROLE_DELETE=bfd1cccc-213a-4f31-b3d1-6e685976aec8
|
||||
REACT_APP_ROLE_GENERATE_CERTIFICATE=9af2d8c0-c26d-4d6d-bbd1-ac53cbd37ebc
|
||||
REACT_APP_ROLE_MANUFACTURE=3412e11a-a2d1-4355-be3e-ef9aa5065b69
|
||||
REACT_APP_ROLE_SUPPLIER_APPROVER=a6c9805e-80b2-42b2-bfbb-9df52e5504d8
|
||||
REACT_APP_ROLE_MANIFEST_MIGRATION=42798c8a-9fa7-4fb4-82c0-9582cabe364f
|
||||
REACT_APP_ROLE_CAR_DIAGNOSTIC=2914e67f-fb85-4b78-b79d-656f4f37faa1
|
||||
REACT_APP_ROLE_UPDATE_DEPLOY=e4af2c4c-6c5e-4784-9097-7c18e776d7b6
|
||||
REACT_APP_ECCKEY_ENV=
|
||||
REACT_APP_HOME_MAP_DEFAULT_LOCATION={"lat":49.8327,"lng":9.8816,"zoom":4.5}
|
||||
REACT_APP_ENABLE_DEBUGMASK=1
|
||||
REACT_APP_SHOW_AFTERSALES_EU_CERT_BUTTON=0
|
||||
23
.env.cec-prd
23
.env.cec-prd
@@ -1,23 +0,0 @@
|
||||
REACT_APP_AUTH_CALLBACK_URL=https://ota-admin.cec-prd.fiskerinc.com
|
||||
REACT_APP_AUTH_SERVICE_URL=https://gw.cec-prd.fiskerinc.com/compute_auth
|
||||
REACT_APP_CERT_SERVICE_URL=https://gw.cec-prd.fiskerinc.com/certificate
|
||||
REACT_APP_ENV=cec-prd
|
||||
REACT_APP_MAGNA_PROVIDER=Magna
|
||||
REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
|
||||
REACT_APP_OTA_SERVICE_URL=https://gw.cec-prd.fiskerinc.com/ota_update
|
||||
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
||||
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
||||
REACT_APP_SUPERSET_URL=https://superset.cec-prd.fiskerinc.com
|
||||
REACT_APP_ROLE_CREATE=e92f2b3e-1b80-42e5-9483-8ae648224dc6
|
||||
REACT_APP_ROLE_READ_ONLY=ae5123e3-7a6a-4ca9-947b-a0f184f82cbd
|
||||
REACT_APP_ROLE_DELETE=bfd1cccc-213a-4f31-b3d1-6e685976aec8
|
||||
REACT_APP_ROLE_GENERATE_CERTIFICATE=9af2d8c0-c26d-4d6d-bbd1-ac53cbd37ebc
|
||||
REACT_APP_ROLE_MANUFACTURE=3412e11a-a2d1-4355-be3e-ef9aa5065b69
|
||||
REACT_APP_ROLE_SUPPLIER_APPROVER=a6c9805e-80b2-42b2-bfbb-9df52e5504d8
|
||||
REACT_APP_ROLE_MANIFEST_MIGRATION=42798c8a-9fa7-4fb4-82c0-9582cabe364f
|
||||
REACT_APP_ROLE_CAR_DIAGNOSTIC=2914e67f-fb85-4b78-b79d-656f4f37faa1
|
||||
REACT_APP_ROLE_UPDATE_DEPLOY=e4af2c4c-6c5e-4784-9097-7c18e776d7b6
|
||||
REACT_APP_ECCKEY_ENV=
|
||||
REACT_APP_HOME_MAP_DEFAULT_LOCATION={"lat":37.0902,"lng":-95.7129,"zoom":4.5}
|
||||
REACT_APP_ENABLE_DEBUGMASK=1
|
||||
REACT_APP_SHOW_AFTERSALES_EU_CERT_BUTTON=1
|
||||
23
.env.dev
23
.env.dev
@@ -1,23 +0,0 @@
|
||||
REACT_APP_AUTH_CALLBACK_URL=https://dev-ota-admin.cloud.fiskerinc.com
|
||||
REACT_APP_AUTH_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/compute_auth
|
||||
REACT_APP_CERT_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/certificate
|
||||
REACT_APP_ENV=dev
|
||||
REACT_APP_MAGNA_PROVIDER=Magna
|
||||
REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
|
||||
REACT_APP_OTA_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/ota_update
|
||||
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
||||
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
||||
REACT_APP_SUPERSET_URL=https://dev-superset.cloud.fiskerinc.com
|
||||
REACT_APP_ROLE_CREATE=efcc3025-e2d8-4212-8227-805c7be39d2c
|
||||
REACT_APP_ROLE_READ_ONLY=a729bbd4-2038-4649-9127-16782bb1e701
|
||||
REACT_APP_ROLE_DELETE=8f78dce7-f5f9-4033-a10c-c9c7408bfcfe
|
||||
REACT_APP_ROLE_GENERATE_CERTIFICATE=746f34b0-9ba0-4b5d-8d84-0256a9c8e390
|
||||
REACT_APP_ROLE_MANUFACTURE=3412e11a-a2d1-4355-be3e-ef9aa5065b69
|
||||
REACT_APP_ROLE_SUPPLIER_APPROVER=a6c9805e-80b2-42b2-bfbb-9df52e5504d8
|
||||
REACT_APP_ROLE_MANIFEST_MIGRATION=42798c8a-9fa7-4fb4-82c0-9582cabe364f
|
||||
REACT_APP_ROLE_CAR_DIAGNOSTIC=2914e67f-fb85-4b78-b79d-656f4f37faa1
|
||||
REACT_APP_ROLE_UPDATE_DEPLOY=3590ec3f-1c05-428b-81a4-40b00baf83de
|
||||
REACT_APP_ECCKEY_ENV=stage,prod
|
||||
REACT_APP_HOME_MAP_DEFAULT_LOCATION={"lat":37.0902,"lng":-95.7129,"zoom":4.5}
|
||||
REACT_APP_ENABLE_DEBUGMASK=1
|
||||
REACT_APP_SHOW_AFTERSALES_EU_CERT_BUTTON=1
|
||||
@@ -2,6 +2,12 @@ REACT_APP_AUTH_CALLBACK_URL=http://localhost:3000
|
||||
REACT_APP_AUTH_SERVICE_URL=http://localhost/compute_auth
|
||||
REACT_APP_CERT_SERVICE_URL=http://localhost/certificate
|
||||
REACT_APP_ENV=local
|
||||
|
||||
# Keycloak OIDC
|
||||
REACT_APP_KEYCLOAK_ENABLED=true
|
||||
REACT_APP_KEYCLOAK_URL=https://keycloak.mini.cloud.fiskerinc.com
|
||||
REACT_APP_KEYCLOAK_REALM=compute-auth
|
||||
REACT_APP_KEYCLOAK_CLIENT_ID=ota-portal
|
||||
REACT_APP_MAGNA_PROVIDER=Magna
|
||||
REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
|
||||
REACT_APP_OTA_SERVICE_URL=http://localhost/ota_update
|
||||
|
||||
21
.env.mini
21
.env.mini
@@ -1,13 +1,20 @@
|
||||
REACT_APP_AUTH_CALLBACK_URL=https://ota-admin.mini.cloud.fiskerinc.com
|
||||
REACT_APP_AUTH_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/compute_auth
|
||||
REACT_APP_CERT_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/certificate
|
||||
REACT_APP_AUTH_SERVICE_URL=https://gw.cloud.fiskerinc.com/compute_auth
|
||||
REACT_APP_CERT_SERVICE_URL=https://gw.cloud.fiskerinc.com/certificate
|
||||
REACT_APP_ENV=mini
|
||||
|
||||
# Keycloak OIDC (set to true to enable)
|
||||
REACT_APP_KEYCLOAK_ENABLED=true
|
||||
REACT_APP_KEYCLOAK_URL=https://keycloak.mini.cloud.fiskerinc.com
|
||||
REACT_APP_KEYCLOAK_REALM=compute-auth
|
||||
REACT_APP_KEYCLOAK_CLIENT_ID=ota-portal
|
||||
|
||||
REACT_APP_MAGNA_PROVIDER=Magna
|
||||
REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
|
||||
REACT_APP_OTA_SERVICE_URL=https://dev-gw.cloud.fiskerinc.com/ota_update
|
||||
REACT_APP_OTA_SERVICE_URL=https://gw.cloud.fiskerinc.com/ota_update
|
||||
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
||||
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
||||
REACT_APP_SUPERSET_URL=https://dev-superset.cloud.fiskerinc.com
|
||||
REACT_APP_SUPERSET_URL=https://superset.cloud.fiskerinc.com
|
||||
REACT_APP_ROLE_CREATE=efcc3025-e2d8-4212-8227-805c7be39d2c
|
||||
REACT_APP_ROLE_READ_ONLY=a729bbd4-2038-4649-9127-16782bb1e701
|
||||
REACT_APP_ROLE_DELETE=8f78dce7-f5f9-4033-a10c-c9c7408bfcfe
|
||||
@@ -16,8 +23,8 @@ REACT_APP_ROLE_MANUFACTURE=3412e11a-a2d1-4355-be3e-ef9aa5065b69
|
||||
REACT_APP_ROLE_SUPPLIER_APPROVER=a6c9805e-80b2-42b2-bfbb-9df52e5504d8
|
||||
REACT_APP_ROLE_MANIFEST_MIGRATION=42798c8a-9fa7-4fb4-82c0-9582cabe364f
|
||||
REACT_APP_ROLE_CAR_DIAGNOSTIC=2914e67f-fb85-4b78-b79d-656f4f37faa1
|
||||
REACT_APP_ROLE_UPDATE_DEPLOY=3590ec3f-1c05-428b-81a4-40b00baf83de
|
||||
REACT_APP_ECCKEY_ENV=stage,prod
|
||||
REACT_APP_ROLE_UPDATE_DEPLOY=e4af2c4c-6c5e-4784-9097-7c18e776d7b6
|
||||
REACT_APP_ECCKEY_ENV=stage
|
||||
REACT_APP_HOME_MAP_DEFAULT_LOCATION={"lat":37.0902,"lng":-95.7129,"zoom":4.5}
|
||||
REACT_APP_ENABLE_DEBUGMASK=1
|
||||
REACT_APP_SHOW_AFTERSALES_EU_CERT_BUTTON=1
|
||||
REACT_APP_SHOW_AFTERSALES_EU_CERT_BUTTON=0
|
||||
|
||||
23
.env.prd
23
.env.prd
@@ -1,23 +0,0 @@
|
||||
REACT_APP_AUTH_CALLBACK_URL=https://ota-admin.cloud.fiskerinc.com
|
||||
REACT_APP_AUTH_SERVICE_URL=https://gw.cloud.fiskerinc.com/compute_auth
|
||||
REACT_APP_CERT_SERVICE_URL=https://gw.cloud.fiskerinc.com/certificate
|
||||
REACT_APP_ENV=prd
|
||||
REACT_APP_MAGNA_PROVIDER=Magna
|
||||
REACT_APP_MAGNA_GROUP_ID=68273225-9da4-4fa7-aea5-38e16ec471fe
|
||||
REACT_APP_OTA_SERVICE_URL=https://gw.cloud.fiskerinc.com/ota_update
|
||||
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
||||
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
||||
REACT_APP_SUPERSET_URL=https://superset.cloud.fiskerinc.com
|
||||
REACT_APP_ROLE_CREATE=efcc3025-e2d8-4212-8227-805c7be39d2c
|
||||
REACT_APP_ROLE_READ_ONLY=a729bbd4-2038-4649-9127-16782bb1e701
|
||||
REACT_APP_ROLE_DELETE=8f78dce7-f5f9-4033-a10c-c9c7408bfcfe
|
||||
REACT_APP_ROLE_GENERATE_CERTIFICATE=746f34b0-9ba0-4b5d-8d84-0256a9c8e390
|
||||
REACT_APP_ROLE_MANUFACTURE=3412e11a-a2d1-4355-be3e-ef9aa5065b69
|
||||
REACT_APP_ROLE_SUPPLIER_APPROVER=a6c9805e-80b2-42b2-bfbb-9df52e5504d8
|
||||
REACT_APP_ROLE_MANIFEST_MIGRATION=42798c8a-9fa7-4fb4-82c0-9582cabe364f
|
||||
REACT_APP_ROLE_CAR_DIAGNOSTIC=2914e67f-fb85-4b78-b79d-656f4f37faa1
|
||||
REACT_APP_ROLE_UPDATE_DEPLOY=e4af2c4c-6c5e-4784-9097-7c18e776d7b6
|
||||
REACT_APP_ECCKEY_ENV=stage
|
||||
REACT_APP_HOME_MAP_DEFAULT_LOCATION={"lat":37.0902,"lng":-95.7129,"zoom":4.5}
|
||||
REACT_APP_ENABLE_DEBUGMASK=1
|
||||
REACT_APP_SHOW_AFTERSALES_EU_CERT_BUTTON=0
|
||||
@@ -1,22 +0,0 @@
|
||||
REACT_APP_AUTH_CALLBACK_URL=http://localhost:3000
|
||||
REACT_APP_AUTH_SERVICE_URL=http://localhost/compute_auth
|
||||
REACT_APP_CERT_SERVICE_URL=http://localhost/certificate
|
||||
REACT_APP_ENV=local
|
||||
REACT_APP_MAGNA_PROVIDER=DISABLED
|
||||
REACT_APP_MAGNA_GROUP_ID=DISABLED
|
||||
REACT_APP_OTA_SERVICE_URL=http://localhost/ota_update
|
||||
REACT_APP_SECURITY_DLL_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_32.dll
|
||||
REACT_APP_SECURITY_DLL_64_URL=https://assets.fiskerdps.com/cloud-supplier/fisker_security_64.dll
|
||||
REACT_APP_SUPERSET_URL=https://dev-superset.cloud.fiskerinc.com
|
||||
REACT_APP_ROLE_CREATE=efcc3025-e2d8-4212-8227-805c7be39d2c
|
||||
REACT_APP_ROLE_READ_ONLY=a729bbd4-2038-4649-9127-16782bb1e701
|
||||
REACT_APP_ROLE_DELETE=8f78dce7-f5f9-4033-a10c-c9c7408bfcfe
|
||||
REACT_APP_ROLE_GENERATE_CERTIFICATE=746f34b0-9ba0-4b5d-8d84-0256a9c8e390
|
||||
REACT_APP_ROLE_MANUFACTURE=3412e11a-a2d1-4355-be3e-ef9aa5065b69
|
||||
REACT_APP_ROLE_SUPPLIER_APPROVER=a6c9805e-80b2-42b2-bfbb-9df52e5504d8
|
||||
REACT_APP_ROLE_MANIFEST_MIGRATION=42798c8a-9fa7-4fb4-82c0-9582cabe364f
|
||||
REACT_APP_ROLE_CAR_DIAGNOSTIC=2914e67f-fb85-4b78-b79d-656f4f37faa1
|
||||
REACT_APP_ROLE_UPDATE_DEPLOY=3590ec3f-1c05-428b-81a4-40b00baf83de
|
||||
REACT_APP_ECCKEY_ENV=dev,stage,prod
|
||||
REACT_APP_HOME_MAP_DEFAULT_LOCATION={"lat":37.0902,"lng":-95.7129,"zoom":4.5}
|
||||
REACT_APP_SHOW_AFTERSALES_EU_CERT_BUTTON=0
|
||||
7
.github/CODEOWNERS
vendored
7
.github/CODEOWNERS
vendored
@@ -1,7 +0,0 @@
|
||||
# default codeowners
|
||||
* @Fisker-Inc/cloud
|
||||
|
||||
# devops
|
||||
.github @Fisker-Inc/devops @Fisker-Inc/cloud
|
||||
k8s @Fisker-Inc/devops @Fisker-Inc/cloud
|
||||
Dockerfile @Fisker-Inc/devops @Fisker-Inc/cloud
|
||||
38
.github/workflows/blackduck.yml
vendored
38
.github/workflows/blackduck.yml
vendored
@@ -1,38 +0,0 @@
|
||||
name: Blackduck Intelligent Scan
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# run scans twice a month
|
||||
- cron: '0 2 1,15 * *'
|
||||
|
||||
jobs:
|
||||
blackduck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: npm
|
||||
|
||||
- run: npm install
|
||||
- run: npm run build
|
||||
|
||||
- name: Run Synopsys Detect INTELLIGENT
|
||||
run: |
|
||||
bash <(curl -s -L https://detect.synopsys.com/detect9.sh) \
|
||||
--blackduck.url=${{ secrets.BLACKDUCK_URL }} \
|
||||
--blackduck.api.token=${{ secrets.BLACKDUCK_API_KEY }} \
|
||||
--blackduck.trust.cert=true \
|
||||
--detect.project.version.update=true \
|
||||
--detect.project.name='ota-admin-portal' \
|
||||
--detect.excluded.directories='node_modules' \
|
||||
--detect.project.version.name=$GITHUB_REF_NAME \
|
||||
--detect.blackduck.scan.mode="INTELLIGENT" \
|
||||
--detect.detector.search.depth=3 \
|
||||
--detect.detector.search.continue=true \
|
||||
--detect.npm.include.dev.dependencies=false
|
||||
# --detect.policy.check.fail.on.severities=ALL,NONE,UNSPECIFIED,TRIVIAL,MINOR,MAJOR,CRITICAL,BLOCKER - Use it if you want to fail the build on a certain severity type
|
||||
# --detect.detector.search.continue=true - If true, the bom tool search will continue to look for nested bom tools of the same type to the maximum search depth
|
||||
41
.github/workflows/blackduck_rapid.yml
vendored
41
.github/workflows/blackduck_rapid.yml
vendored
@@ -1,41 +0,0 @@
|
||||
name: Blackduck Rapid scan
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
blackduck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: npm
|
||||
|
||||
- run: npm install
|
||||
- run: npm run build
|
||||
|
||||
- name: Run Synopsys Detect RAPID
|
||||
run: |
|
||||
bash <(curl -s -L https://detect.synopsys.com/detect9.sh) \
|
||||
--blackduck.url=${{ secrets.BLACKDUCK_URL }} \
|
||||
--blackduck.api.token=${{ secrets.BLACKDUCK_API_KEY }} \
|
||||
--blackduck.trust.cert=true \
|
||||
--detect.project.version.update=true \
|
||||
--detect.project.name='ota-admin-portal' \
|
||||
--detect.excluded.directories='node_modules' \
|
||||
--detect.project.version.name=$GITHUB_REF_NAME \
|
||||
--detect.blackduck.scan.mode="RAPID" \
|
||||
--detect.detector.search.depth=3 \
|
||||
--detect.detector.search.continue=true \
|
||||
--detect.npm.include.dev.dependencies=false
|
||||
# --detect.detector.search.continue=true - If true, the bom tool search will continue to look for nested bom tools of the same type to the maximum search depth
|
||||
135
.github/workflows/deploy-on-demand-v2.yml
vendored
135
.github/workflows/deploy-on-demand-v2.yml
vendored
@@ -1,135 +0,0 @@
|
||||
name: OTA Admin Portal v2 Deploy - On Demand
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
environment:
|
||||
description: "Environment"
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- dev
|
||||
- preprod
|
||||
- cec-prd
|
||||
- cec-euprd
|
||||
|
||||
env:
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
SLACK_CHANNEL: "#cloud-builds"
|
||||
SLACK_FOOTER: ""
|
||||
SLACK_USERNAME: GitHub Actions
|
||||
SLACK_ICON: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
|
||||
JFROG_NPMRC: ${{ secrets.JFROG_NPMRC }}
|
||||
TAG: ${{ github.sha }}
|
||||
PROJECT: ota-admin-portal-v2
|
||||
REGISTRY: fiskercloud.azurecr.io
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Slack Notification
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Azure Login
|
||||
uses: azure/login@v2
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID_DEV }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID_DEV }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID_DEV }}
|
||||
|
||||
- name: ACR Login
|
||||
run: |
|
||||
az acr login --name ${{ env.REGISTRY }}
|
||||
|
||||
- name: JFrog Auth
|
||||
run: echo ${JFROG_NPMRC} | base64 -d > .npmrc
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
build-args: ENVIRONMENT=${{ inputs.environment }}
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.PROJECT }}:${{ env.TAG }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Notify if failure
|
||||
if: ${{ failure() }}
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_COLOR: ${{ job.status }}
|
||||
SLACK_MESSAGE: "Failed to build ${{ env.PROJECT }} in ${{ inputs.environment }}! :this-is-fine:"
|
||||
|
||||
deploy:
|
||||
needs: build
|
||||
runs-on: arc-azure-${{ inputs.environment }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Notify deploy
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
MSG_MINIMAL: true
|
||||
SLACK_MESSAGE: "Deploying ${{ env.PROJECT }} to ${{ inputs.environment }}... :partydeploy:"
|
||||
|
||||
- name: Set env
|
||||
run: |
|
||||
case ${{ inputs.environment }} in
|
||||
dev)
|
||||
KUBECONFIG=${{ secrets.KUBECONFIG_AZURE_DEV }};;
|
||||
preprod)
|
||||
KUBECONFIG=${{ secrets.KUBECONFIG_AZURE_PREPROD }};;
|
||||
cec-prd)
|
||||
KUBECONFIG=${{ secrets.KUBECONFIG_AZURE_CEC_PRD }};;
|
||||
cec-euprd)
|
||||
KUBECONFIG=${{ secrets.KUBECONFIG_AZURE_CEC_EUPRD }};;
|
||||
*)
|
||||
KUBECONFIG=${{ secrets.KUBECONFIG_AZURE_DEV }};;
|
||||
esac
|
||||
|
||||
echo "KUBECONFIG=${KUBECONFIG}" >> $GITHUB_ENV
|
||||
|
||||
- name: Deploy to env
|
||||
id: deploy
|
||||
uses: koslib/helm-eks-action@v1.28.0
|
||||
env:
|
||||
KUBE_CONFIG_DATA: ${{ env.KUBECONFIG }}
|
||||
with:
|
||||
command: |
|
||||
helm upgrade \
|
||||
--atomic \
|
||||
--create-namespace \
|
||||
--namespace default \
|
||||
--set image.registry=$REGISTRY \
|
||||
--set image.name=$PROJECT \
|
||||
--set image.tag=$TAG \
|
||||
--wait -i -f k8s/values-${{ inputs.environment }}.yaml $PROJECT k8s/
|
||||
|
||||
- name: Deploy Response
|
||||
run: echo "Response was ${{ steps.deploy.outputs.response }}"
|
||||
|
||||
- name: Notify deploy failure
|
||||
if: ${{ failure() }}
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_COLOR: ${{ job.status }}
|
||||
SLACK_MESSAGE: "Failed to deploy ${{ env.PROJECT }} on ${{ inputs.environment }}! :this-is-fine:"
|
||||
|
||||
- name: Notify deploy success
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
MSG_MINIMAL: true
|
||||
SLACK_MESSAGE: "Successfully deployed ${{ env.PROJECT }} to ${{ inputs.environment }}! :gopher_party:"
|
||||
131
.github/workflows/deploy-on-demand.yml
vendored
131
.github/workflows/deploy-on-demand.yml
vendored
@@ -1,131 +0,0 @@
|
||||
name: OTA Portal Deploy - On Demand
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
environment:
|
||||
description: "Environment"
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- dev
|
||||
- preprod
|
||||
- cec-prd
|
||||
- cec-euprd
|
||||
|
||||
env:
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
SLACK_CHANNEL: "#cloud-builds"
|
||||
SLACK_FOOTER: ""
|
||||
SLACK_USERNAME: GitHub Actions
|
||||
SLACK_ICON: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
|
||||
TAG: ${{ github.sha }}
|
||||
PROJECT: ota-admin-portal
|
||||
REGISTRY: fiskercloud.azurecr.io
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Slack Notification
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Azure Login
|
||||
uses: azure/login@v2
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID_DEV }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID_DEV }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID_DEV }}
|
||||
|
||||
- name: ACR Login
|
||||
run: |
|
||||
az acr login --name ${{ env.REGISTRY }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
build-args: ENVIRONMENT=${{ inputs.environment }}
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.PROJECT }}:${{ env.TAG }}-${{ inputs.environment }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Notify if failure
|
||||
if: ${{ failure() }}
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_COLOR: ${{ job.status }}
|
||||
SLACK_MESSAGE: "Failed to build ${{ env.PROJECT }} in ${{ inputs.environment }}! :this-is-fine:"
|
||||
|
||||
deploy:
|
||||
needs: build
|
||||
runs-on: arc-azure-${{ inputs.environment }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Notify deploy
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
MSG_MINIMAL: true
|
||||
SLACK_MESSAGE: "Deploying ${{ env.PROJECT }} to ${{ inputs.environment }}... :partydeploy:"
|
||||
|
||||
- name: Set env
|
||||
run: |
|
||||
case ${{ inputs.environment }} in
|
||||
dev)
|
||||
KUBECONFIG=${{ secrets.KUBECONFIG_AZURE_DEV }};;
|
||||
preprod)
|
||||
KUBECONFIG=${{ secrets.KUBECONFIG_AZURE_PREPROD }};;
|
||||
cec-prd)
|
||||
KUBECONFIG=${{ secrets.KUBECONFIG_AZURE_CEC_PRD }};;
|
||||
cec-euprd)
|
||||
KUBECONFIG=${{ secrets.KUBECONFIG_AZURE_CEC_EUPRD }};;
|
||||
*)
|
||||
KUBECONFIG=${{ secrets.KUBECONFIG_AZURE_DEV }};;
|
||||
esac
|
||||
|
||||
echo "KUBECONFIG=${KUBECONFIG}" >> $GITHUB_ENV
|
||||
|
||||
- name: Deploy to env
|
||||
id: deploy
|
||||
uses: koslib/helm-eks-action@v1.28.0
|
||||
env:
|
||||
KUBE_CONFIG_DATA: ${{ env.KUBECONFIG }}
|
||||
with:
|
||||
command: |
|
||||
helm upgrade \
|
||||
--atomic \
|
||||
--create-namespace \
|
||||
--namespace default \
|
||||
--set image.registry=$REGISTRY \
|
||||
--set image.name=$PROJECT \
|
||||
--set image.tag=$TAG-${{ inputs.environment }} \
|
||||
--wait -i -f k8s/values-${{ inputs.environment }}.yaml $PROJECT k8s/
|
||||
|
||||
- name: Deploy Response
|
||||
run: echo "Response was ${{ steps.deploy.outputs.response }}"
|
||||
|
||||
- name: Notify deploy failure
|
||||
if: ${{ failure() }}
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_COLOR: ${{ job.status }}
|
||||
SLACK_MESSAGE: "Failed to deploy ${{ env.PROJECT }} to ${{ inputs.environment }}! :this-is-fine:"
|
||||
|
||||
- name: Notify deploy success
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
MSG_MINIMAL: true
|
||||
SLACK_MESSAGE: "Successfully deployed ${{ env.PROJECT }} to ${{ inputs.environment }}! :gopher_party:"
|
||||
371
.github/workflows/deploy.yml
vendored
371
.github/workflows/deploy.yml
vendored
@@ -1,371 +0,0 @@
|
||||
name: OTA Portal Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
SLACK_CHANNEL: "#cloud-builds"
|
||||
SLACK_FOOTER: ""
|
||||
SLACK_USERNAME: GitHub Actions
|
||||
SLACK_ICON: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
|
||||
TAG: ${{ github.sha }}
|
||||
PROJECT: ota-admin-portal
|
||||
REGISTRY: fiskercloud.azurecr.io
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build-dev:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Slack Notification
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Azure Login
|
||||
uses: azure/login@v2
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID_DEV }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID_DEV }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID_DEV }}
|
||||
|
||||
- name: ACR Login
|
||||
run: |
|
||||
az acr login --name ${{ env.REGISTRY }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and push DEV
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
build-args: ENVIRONMENT=dev
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.PROJECT }}:${{ env.TAG }}-dev
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Notify if failure
|
||||
if: ${{ failure() }}
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_COLOR: ${{ job.status }}
|
||||
SLACK_MESSAGE: "Failed to build ${{ env.PROJECT }} dev! :this-is-fine:"
|
||||
|
||||
deploy-dev:
|
||||
needs: [build-dev]
|
||||
runs-on: [ arc-azure-dev ]
|
||||
environment: dev
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Notify deploy
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
MSG_MINIMAL: true
|
||||
SLACK_MESSAGE: "Deploying ${{ env.PROJECT }} to dev... :partydeploy:"
|
||||
|
||||
- name: Deploy to dev
|
||||
id: deploy
|
||||
uses: koslib/helm-eks-action@v1.28.0
|
||||
env:
|
||||
KUBE_CONFIG_DATA: ${{ secrets.KUBECONFIG_AZURE_DEV }}
|
||||
with:
|
||||
command: |
|
||||
helm upgrade \
|
||||
--atomic \
|
||||
--create-namespace \
|
||||
--namespace default \
|
||||
--set image.registry=$REGISTRY \
|
||||
--set image.name=$PROJECT \
|
||||
--set image.tag=$TAG-dev \
|
||||
--wait -i -f k8s/values-dev.yaml $PROJECT k8s/
|
||||
|
||||
- name: Deploy Response
|
||||
run: echo "Response was ${{ steps.deploy.outputs.response }}"
|
||||
|
||||
- name: Notify deploy failure
|
||||
if: ${{ failure() }}
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_COLOR: ${{ job.status }}
|
||||
SLACK_MESSAGE: "Failed to deploy ${{ env.PROJECT }} on dev! :this-is-fine:"
|
||||
|
||||
- name: Notify deploy success
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
MSG_MINIMAL: true
|
||||
SLACK_MESSAGE: "Successfully deployed ${{ env.PROJECT }} to dev! :gopher_party:"
|
||||
|
||||
build-preprod:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [deploy-dev]
|
||||
steps:
|
||||
- name: Slack Notification
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Azure Login
|
||||
uses: azure/login@v2
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID_DEV }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID_DEV }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID_DEV }}
|
||||
|
||||
- name: ACR Login
|
||||
run: |
|
||||
az acr login --name ${{ env.REGISTRY }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and push PREPROD
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
build-args: ENVIRONMENT=preprod
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.PROJECT }}:${{ env.TAG }}-prd
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Notify if failure
|
||||
if: ${{ failure() }}
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_COLOR: ${{ job.status }}
|
||||
SLACK_MESSAGE: "Failed to build ${{ env.PROJECT }} preprod! :this-is-fine:"
|
||||
|
||||
deploy-preprod:
|
||||
needs: [deploy-dev, build-preprod]
|
||||
runs-on: [ arc-azure-preprod ]
|
||||
environment: preprod
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Notify deploy
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
MSG_MINIMAL: true
|
||||
SLACK_MESSAGE: "Deploying ${{ env.PROJECT }} to preprod... :partydeploy:"
|
||||
|
||||
- name: Deploy to preprod
|
||||
id: deploy
|
||||
uses: koslib/helm-eks-action@v1.28.0
|
||||
env:
|
||||
KUBE_CONFIG_DATA: ${{ secrets.KUBECONFIG_AZURE_PREPROD }}
|
||||
with:
|
||||
command: |
|
||||
helm upgrade \
|
||||
--atomic \
|
||||
--create-namespace \
|
||||
--namespace default \
|
||||
--set image.registry=$REGISTRY \
|
||||
--set image.name=$PROJECT \
|
||||
--set image.tag=$TAG-prd \
|
||||
--wait -i -f k8s/values-preprod.yaml $PROJECT k8s/
|
||||
|
||||
- name: Deploy Response
|
||||
run: echo "Response was ${{ steps.deploy.outputs.response }}"
|
||||
|
||||
- name: Notify deploy failure
|
||||
if: ${{ failure() }}
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_COLOR: ${{ job.status }}
|
||||
SLACK_MESSAGE: "Failed to deploy ${{ env.PROJECT }} on preprod! :this-is-fine:"
|
||||
|
||||
- name: Notify deploy success
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
MSG_MINIMAL: true
|
||||
SLACK_MESSAGE: "Successfully deployed ${{ env.PROJECT }} to preprod! :gopher_party:"
|
||||
|
||||
build-cec-prd:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [deploy-dev, deploy-preprod]
|
||||
steps:
|
||||
- name: Slack Notification
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Azure Login
|
||||
uses: azure/login@v2
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID_DEV }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID_DEV }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID_DEV }}
|
||||
|
||||
- name: ACR Login
|
||||
run: |
|
||||
az acr login --name ${{ env.REGISTRY }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and push CEC-PRD
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
build-args: ENVIRONMENT=cec-prd
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.PROJECT }}:${{ env.TAG }}-cec-prd
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Notify if failure
|
||||
if: ${{ failure() }}
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_COLOR: ${{ job.status }}
|
||||
SLACK_MESSAGE: "Failed to build ${{ env.PROJECT }} cec-prd! :this-is-fine:"
|
||||
|
||||
deploy-cec-prd:
|
||||
needs: [deploy-dev, deploy-preprod, build-cec-prd]
|
||||
runs-on: [ arc-azure-cec-prd ]
|
||||
environment: prd
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Notify deploy
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
MSG_MINIMAL: true
|
||||
SLACK_MESSAGE: "Deploying ${{ env.PROJECT }} to cec-prd... :partydeploy:"
|
||||
|
||||
- name: Deploy to cec-prd
|
||||
id: deploy
|
||||
uses: koslib/helm-eks-action@v1.28.0
|
||||
env:
|
||||
KUBE_CONFIG_DATA: ${{ secrets.KUBECONFIG_AZURE_CEC_PRD }}
|
||||
with:
|
||||
command: |
|
||||
helm upgrade \
|
||||
--atomic \
|
||||
--create-namespace \
|
||||
--namespace default \
|
||||
--set image.registry=$REGISTRY \
|
||||
--set image.name=$PROJECT \
|
||||
--set image.tag=$TAG-cec-prd \
|
||||
--wait -i -f k8s/values-cec-prd.yaml $PROJECT k8s/
|
||||
|
||||
- name: Deploy Response
|
||||
run: echo "Response was ${{ steps.deploy.outputs.response }}"
|
||||
|
||||
- name: Notify deploy failure
|
||||
if: ${{ failure() }}
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_COLOR: ${{ job.status }}
|
||||
SLACK_MESSAGE: "Failed to deploy ${{ env.PROJECT }} on cec-prd! :this-is-fine:"
|
||||
|
||||
- name: Notify deploy success
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
MSG_MINIMAL: true
|
||||
SLACK_MESSAGE: "Successfully deployed ${{ env.PROJECT }} to cec-prd! :gopher_party:"
|
||||
|
||||
build-cec-euprd:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [deploy-dev, deploy-preprod]
|
||||
steps:
|
||||
- name: Slack Notification
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Azure Login
|
||||
uses: azure/login@v2
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID_DEV }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID_DEV }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID_DEV }}
|
||||
|
||||
- name: ACR Login
|
||||
run: |
|
||||
az acr login --name ${{ env.REGISTRY }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and push CEC-EUPRD
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
build-args: ENVIRONMENT=cec-euprd
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.PROJECT }}:${{ env.TAG }}-cec-euprd
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Notify if failure
|
||||
if: ${{ failure() }}
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_COLOR: ${{ job.status }}
|
||||
SLACK_MESSAGE: "Failed to build ${{ env.PROJECT }} cec-euprd! :this-is-fine:"
|
||||
|
||||
deploy-cec-euprd:
|
||||
needs: [deploy-dev, deploy-preprod, build-cec-euprd]
|
||||
runs-on: [ arc-azure-cec-euprd ]
|
||||
environment: prd
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Notify deploy
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
MSG_MINIMAL: true
|
||||
SLACK_MESSAGE: "Deploying ${{ env.PROJECT }} to cec-euprd... :partydeploy:"
|
||||
|
||||
- name: Deploy to cec-euprd
|
||||
id: deploy
|
||||
uses: koslib/helm-eks-action@v1.28.0
|
||||
env:
|
||||
KUBE_CONFIG_DATA: ${{ secrets.KUBECONFIG_AZURE_CEC_EUPRD }}
|
||||
with:
|
||||
command: |
|
||||
helm upgrade \
|
||||
--atomic \
|
||||
--create-namespace \
|
||||
--namespace default \
|
||||
--set image.registry=$REGISTRY \
|
||||
--set image.name=$PROJECT \
|
||||
--set image.tag=$TAG-cec-euprd \
|
||||
--wait -i -f k8s/values-cec-euprd.yaml $PROJECT k8s/
|
||||
|
||||
- name: Deploy Response
|
||||
run: echo "Response was ${{ steps.deploy.outputs.response }}"
|
||||
|
||||
- name: Notify deploy failure
|
||||
if: ${{ failure() }}
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
SLACK_COLOR: ${{ job.status }}
|
||||
SLACK_MESSAGE: "Failed to deploy ${{ env.PROJECT }} on cec-euprd! :this-is-fine:"
|
||||
|
||||
- name: Notify deploy success
|
||||
uses: rtCamp/action-slack-notify@v2
|
||||
env:
|
||||
MSG_MINIMAL: true
|
||||
SLACK_MESSAGE: "Successfully deployed ${{ env.PROJECT }} to cec-euprd! :gopher_party:"
|
||||
12
.github/workflows/pr.yml
vendored
12
.github/workflows/pr.yml
vendored
@@ -1,12 +0,0 @@
|
||||
name: Pull Request Jira Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
types: [opened, edited, synchronize, reopened]
|
||||
|
||||
|
||||
jobs:
|
||||
prcheck:
|
||||
uses: Fisker-Inc/github-actions/.github/workflows/pr.yml@v1.0.16
|
||||
35
.github/workflows/test.yml
vendored
35
.github/workflows/test.yml
vendored
@@ -1,35 +0,0 @@
|
||||
name: Node.js CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
cache: "npm"
|
||||
- run: npm install
|
||||
- run: npm run build --if-present
|
||||
- run: npm test -- --coverage --coverageDirectory='coverage' --watchAll=false
|
||||
env:
|
||||
CI: true
|
||||
|
||||
- name: SonarCloud Scan
|
||||
uses: sonarsource/sonarcloud-github-action@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
30
.vscode/launch.json
vendored
30
.vscode/launch.json
vendored
@@ -1,30 +0,0 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "pwa-node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "${file}"
|
||||
},
|
||||
{
|
||||
"name": "Debug CRA Tests",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/react-scripts",
|
||||
"args": ["test", "--runInBand", "--no-cache", "--watchAll=false"],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"protocol": "inspector",
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"env": { "CI": "true" },
|
||||
"disableOptimisticBPs": true
|
||||
}
|
||||
]
|
||||
}
|
||||
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
// spacing
|
||||
"editor.tabSize": 2,
|
||||
"editor.insertSpaces": true,
|
||||
"editor.detectIndentation": false
|
||||
}
|
||||
83
README.md
83
README.md
@@ -1,69 +1,42 @@
|
||||
# Fisker Admin Portal
|
||||
# OTA Admin Portal
|
||||
|
||||
Front-end web application for administrating services.
|
||||
Front-end web application for OTA administration.
|
||||
|
||||
# Setup
|
||||
## Setup
|
||||
|
||||
Running locally
|
||||
```bash
|
||||
npm install
|
||||
npm start
|
||||
# Access at http://localhost:3000
|
||||
```
|
||||
|
||||
1. Install Node 16
|
||||
2. Run `npm install`
|
||||
3. Copy .env.template to .env and edit the service urls for authentication and api services
|
||||
4. Run `./run.sh` from the terminal
|
||||
5. Access portal at localhost:3000
|
||||
## Build & Deploy
|
||||
|
||||
Running Docker container
|
||||
```bash
|
||||
# Build and push Docker image
|
||||
docker build --build-arg ENVIRONMENT=mini -t gitea.mini.cloud.fiskerinc.com/admin/ota-admin-portal:latest .
|
||||
docker login gitea.mini.cloud.fiskerinc.com -u admin
|
||||
docker push gitea.mini.cloud.fiskerinc.com/admin/ota-admin-portal:latest
|
||||
```
|
||||
|
||||
1. Copy .env.template to .env and edit the service urls for authentication and api services
|
||||
2. Build the image `docker build --build-arg ENVIRONMENT=local -t fiskerinc/portal .`
|
||||
3. Start the container `docker run -p 3000:80 fiskerinc/portal`
|
||||
4. Access portal at localhost:3000
|
||||
## Environment
|
||||
|
||||
## Available Scripts
|
||||
- `.env.local` - Local development
|
||||
- `.env.mini` - Mini cluster (Mac Mini)
|
||||
|
||||
In the project directory, you can run:
|
||||
## Deployment
|
||||
|
||||
### `npm start`
|
||||
Deployed via ArgoCD from `k8s/` helm chart with `values-mini.yaml`.
|
||||
|
||||
Runs the app in the development mode.\
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
URL: https://ota-admin.mini.cloud.fiskerinc.com
|
||||
|
||||
The page will reload if you make edits.\
|
||||
You will also see any lint errors in the console.
|
||||
## Mini Cluster Login (Keycloak)
|
||||
|
||||
### `npm test`
|
||||
The mini cluster uses Keycloak instead of Cognito. Test users for the `compute-auth` realm:
|
||||
|
||||
Launches the test runner in the interactive watch mode.\
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
| User | Password | Role |
|
||||
|------|----------|------|
|
||||
| admin | Admin123! | Full access |
|
||||
| operator | Operator123! | Operator access |
|
||||
|
||||
### `npm run build`
|
||||
|
||||
Builds the app for production to the `build` folder.\
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.\
|
||||
Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `npm run eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
|
||||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
||||
|
||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
|
||||
|
||||
### Deployment
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
|
||||
|
||||
### `npm run build` fails to minify
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
|
||||
Keycloak admin console: https://keycloak.mini.cloud.fiskerinc.com (admin / admin123)
|
||||
|
||||
12
devbox.json
Normal file
12
devbox.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/jetify-com/devbox/main/.schema/devbox.schema.json",
|
||||
"packages": [
|
||||
"nodejs_18",
|
||||
"docker"
|
||||
],
|
||||
"shell": {
|
||||
"init_hook": [
|
||||
"echo 'OTA Admin Portal dev environment ready'"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ spec:
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.image.registry }}/{{ .Values.image.name }}:{{ .Values.image.tag}}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy | default "Always" }}
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
env:
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
ingress:
|
||||
hostname: ota-admin.cec-euprd.fiskerinc.com
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
#cpu: 250m
|
||||
memory: 256Mi
|
||||
|
||||
replicas: 3
|
||||
@@ -1,12 +0,0 @@
|
||||
ingress:
|
||||
hostname: ota-admin.cec-prd.fiskerinc.com
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
#cpu: 250m
|
||||
memory: 256Mi
|
||||
|
||||
replicas: 3
|
||||
@@ -1,12 +0,0 @@
|
||||
ingress:
|
||||
hostname: dev-ota-admin.cloud.fiskerinc.com
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
#cpu: 250m
|
||||
memory: 256Mi
|
||||
|
||||
replicas: 1
|
||||
@@ -3,14 +3,15 @@ ingress:
|
||||
className: traefik
|
||||
|
||||
image:
|
||||
registry: gitea.mini.cloud.fiskerinc.com
|
||||
name: admin/ota-admin-portal
|
||||
tag: latest
|
||||
registry: localhost:32000
|
||||
name: ota-admin-portal
|
||||
tag: preprod4
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
memory: 256Mi
|
||||
limits:
|
||||
memory: 256Mi
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
ingress:
|
||||
hostname: ota-admin.cloud.fiskerinc.com
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
#cpu: 250m
|
||||
memory: 256Mi
|
||||
|
||||
replicas: 3
|
||||
106
package-lock.json
generated
106
package-lock.json
generated
@@ -34,10 +34,12 @@
|
||||
"leaflet": "^1.8.0",
|
||||
"material-ui-dropzone": "^3.5.0",
|
||||
"moment": "^2.29.4",
|
||||
"oidc-client-ts": "^3.4.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-leaflet": "^3.2.5",
|
||||
"react-leaflet-cluster": "^1.0.3",
|
||||
"react-oidc-context": "^3.3.0",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-router-hash-link": "^2.4.3",
|
||||
"react-scripts": "^5.0.1",
|
||||
@@ -3952,6 +3954,21 @@
|
||||
"string.prototype.matchall": "^4.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@surma/rollup-plugin-off-main-thread/node_modules/ejs": {
|
||||
"version": "3.1.9",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz",
|
||||
"integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"jake": "^10.8.5"
|
||||
},
|
||||
"bin": {
|
||||
"ejs": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-add-jsx-attribute": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz",
|
||||
@@ -7361,20 +7378,6 @@
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
||||
},
|
||||
"node_modules/ejs": {
|
||||
"version": "3.1.10",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
|
||||
"integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
|
||||
"dependencies": {
|
||||
"jake": "^10.8.5"
|
||||
},
|
||||
"bin": {
|
||||
"ejs": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.567",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.567.tgz",
|
||||
@@ -12215,6 +12218,27 @@
|
||||
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
|
||||
"integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg=="
|
||||
},
|
||||
"node_modules/oidc-client-ts": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/oidc-client-ts/-/oidc-client-ts-3.4.1.tgz",
|
||||
"integrity": "sha512-jNdst/U28Iasukx/L5MP6b274Vr7ftQs6qAhPBCvz6Wt5rPCA+Q/tUmCzfCHHWweWw5szeMy2Gfrm1rITwUKrw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"jwt-decode": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/oidc-client-ts/node_modules/jwt-decode": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
|
||||
"integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/on-finished": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||
@@ -14170,6 +14194,19 @@
|
||||
"react-leaflet": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/react-oidc-context": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-oidc-context/-/react-oidc-context-3.3.0.tgz",
|
||||
"integrity": "sha512-302T/ma4AOVAxrHdYctDSKXjCq9KNHT564XEO2yOPxRfxEP58xa4nz+GQinNl8x7CnEXECSM5JEjQJk3Cr5BvA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"oidc-client-ts": "^3.1.0",
|
||||
"react": ">=16.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-refresh": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
|
||||
@@ -19970,10 +20007,20 @@
|
||||
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
|
||||
"integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==",
|
||||
"requires": {
|
||||
"ejs": "^3.1.6",
|
||||
"ejs": "3.1.9",
|
||||
"json5": "^2.2.0",
|
||||
"magic-string": "^0.25.0",
|
||||
"string.prototype.matchall": "^4.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"ejs": {
|
||||
"version": "3.1.9",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz",
|
||||
"integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==",
|
||||
"requires": {
|
||||
"jake": "^10.8.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@svgr/babel-plugin-add-jsx-attribute": {
|
||||
@@ -22470,14 +22517,6 @@
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
||||
},
|
||||
"ejs": {
|
||||
"version": "3.1.10",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
|
||||
"integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
|
||||
"requires": {
|
||||
"jake": "^10.8.5"
|
||||
}
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.4.567",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.567.tgz",
|
||||
@@ -26023,6 +26062,21 @@
|
||||
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
|
||||
"integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg=="
|
||||
},
|
||||
"oidc-client-ts": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/oidc-client-ts/-/oidc-client-ts-3.4.1.tgz",
|
||||
"integrity": "sha512-jNdst/U28Iasukx/L5MP6b274Vr7ftQs6qAhPBCvz6Wt5rPCA+Q/tUmCzfCHHWweWw5szeMy2Gfrm1rITwUKrw==",
|
||||
"requires": {
|
||||
"jwt-decode": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"jwt-decode": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
|
||||
"integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||
@@ -27253,6 +27307,12 @@
|
||||
"leaflet.markercluster": "^1.4.1"
|
||||
}
|
||||
},
|
||||
"react-oidc-context": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-oidc-context/-/react-oidc-context-3.3.0.tgz",
|
||||
"integrity": "sha512-302T/ma4AOVAxrHdYctDSKXjCq9KNHT564XEO2yOPxRfxEP58xa4nz+GQinNl8x7CnEXECSM5JEjQJk3Cr5BvA==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-refresh": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
|
||||
|
||||
13
package.json
13
package.json
@@ -29,10 +29,12 @@
|
||||
"leaflet": "^1.8.0",
|
||||
"material-ui-dropzone": "^3.5.0",
|
||||
"moment": "^2.29.4",
|
||||
"oidc-client-ts": "^3.4.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-leaflet": "^3.2.5",
|
||||
"react-leaflet-cluster": "^1.0.3",
|
||||
"react-oidc-context": "^3.3.0",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-router-hash-link": "^2.4.3",
|
||||
"react-scripts": "^5.0.1",
|
||||
@@ -48,18 +50,11 @@
|
||||
},
|
||||
"scripts": {
|
||||
"start": "env-cmd -f .env.local react-scripts start",
|
||||
"build": "env-cmd -f .env.local react-scripts build",
|
||||
"build:dev": "env-cmd -f .env.dev react-scripts build",
|
||||
"build:stg": "env-cmd -f .env.stg react-scripts build",
|
||||
"build:preprod": "env-cmd -f .env.prd react-scripts build",
|
||||
"build:cec-prd": "env-cmd -f .env.cec-prd react-scripts build",
|
||||
"build:cec-euprd": "env-cmd -f .env.cec-euprd react-scripts build",
|
||||
"build": "env-cmd -f .env.mini react-scripts build",
|
||||
"build:mini": "env-cmd -f .env.mini react-scripts build",
|
||||
"build:local": "env-cmd -f .env.local react-scripts build",
|
||||
"test": "env-cmd -f .env.local react-scripts test --no-cache",
|
||||
"test:debug": "react-scripts --inspect-brk test --runInBand --no-cache",
|
||||
"test:coverage": "npm test -- --coverage --watchAll=false --no-cache",
|
||||
"eject": "react-scripts eject"
|
||||
"test:coverage": "npm test -- --coverage --watchAll=false --no-cache"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
sonar.projectKey=Fisker-Inc_ota-admin-portal
|
||||
sonar.organization=fisker-inc
|
||||
sonar.sourceEncoding=UTF-8
|
||||
sonar.javascript.coveragePlugin=lcov
|
||||
sonar.javascript.lcov.reportPaths=coverage/lcov.info
|
||||
sonar.sources=src
|
||||
@@ -1,13 +1,15 @@
|
||||
import React from "react";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import { AuthProvider } from "react-oidc-context";
|
||||
import { UserProvider } from "../Contexts/UserContext";
|
||||
import { StatusProvider } from "../Contexts/StatusContext";
|
||||
import { CssBaseline } from "@material-ui/core";
|
||||
import MenuDrawer from "../Layouts/MenuDrawer";
|
||||
import SiteRoutes from "../Routes/SiteRoutes";
|
||||
import { } from "../../services/monitoring";
|
||||
import { keycloakConfig, isKeycloakEnabled } from "../../services/keycloak";
|
||||
|
||||
function App() {
|
||||
function AppContent() {
|
||||
return (
|
||||
<StatusProvider>
|
||||
<UserProvider>
|
||||
@@ -22,4 +24,25 @@ function App() {
|
||||
);
|
||||
}
|
||||
|
||||
const onSigninCallback = () => {
|
||||
// Remove OIDC params from URL after signin
|
||||
window.history.replaceState({}, document.title, window.location.pathname);
|
||||
};
|
||||
|
||||
function App() {
|
||||
// Only wrap with AuthProvider if Keycloak is enabled
|
||||
if (isKeycloakEnabled()) {
|
||||
return (
|
||||
<AuthProvider
|
||||
{...keycloakConfig}
|
||||
onSigninCallback={onSigninCallback}
|
||||
>
|
||||
<AppContent />
|
||||
</AuthProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return <AppContent />;
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -3,6 +3,7 @@ import auth from "../../services/auth";
|
||||
import getTimerWorker from "../../services/getTimerWorker";
|
||||
import { parsePayload } from "../../utils/jwt";
|
||||
import {getGroups, getProviders} from "../../utils/roles";
|
||||
import { isKeycloakEnabled } from "../../services/keycloak";
|
||||
|
||||
const UserContext = React.createContext();
|
||||
|
||||
@@ -12,6 +13,7 @@ export const UserProvider = ({ children }) => {
|
||||
const [groups, setGroups] = useState(null);
|
||||
const [providers, setProviders] = useState(null);
|
||||
const [error, setError] = useState(null);
|
||||
const [authSource, setAuthSource] = useState(null); // 'cognito' or 'keycloak'
|
||||
let timer;
|
||||
|
||||
useEffect(() => {
|
||||
@@ -19,8 +21,18 @@ export const UserProvider = ({ children }) => {
|
||||
if (!localStorage) return;
|
||||
const t = JSON.parse(localStorage.getItem("token"));
|
||||
if (!t) return;
|
||||
|
||||
// Check if it's a Keycloak token (different structure)
|
||||
if (t.authSource === 'keycloak') {
|
||||
setToken(t);
|
||||
setAuthSource('keycloak');
|
||||
return;
|
||||
}
|
||||
|
||||
// Cognito token format
|
||||
if (!t.idToken || !t.idToken.jwtToken) throw new Error("Invalid token");
|
||||
setToken(t);
|
||||
setAuthSource('cognito');
|
||||
} catch (e) {
|
||||
document.location = signOut();
|
||||
}
|
||||
@@ -29,12 +41,16 @@ export const UserProvider = ({ children }) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (!token) return;
|
||||
verifyToken();
|
||||
if (authSource === 'keycloak') {
|
||||
verifyKeycloakToken();
|
||||
} else {
|
||||
verifyToken();
|
||||
}
|
||||
return () => {
|
||||
if (timer) timer.terminate();
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [token]);
|
||||
}, [token, authSource]);
|
||||
|
||||
const refreshTokens = async () => {
|
||||
if (!token || !token.refreshToken || !token.refreshToken.token) return null;
|
||||
@@ -42,25 +58,57 @@ export const UserProvider = ({ children }) => {
|
||||
};
|
||||
|
||||
const startSessionTimer = () => {
|
||||
if (!token || !token.idToken || !token.idToken.jwtToken) {
|
||||
throw new Error("No id token");
|
||||
let jwtToken;
|
||||
if (authSource === 'keycloak') {
|
||||
jwtToken = token.idToken;
|
||||
} else {
|
||||
if (!token || !token.idToken || !token.idToken.jwtToken) {
|
||||
throw new Error("No id token");
|
||||
}
|
||||
jwtToken = token.idToken.jwtToken;
|
||||
}
|
||||
const payload = parsePayload(token.idToken.jwtToken);
|
||||
|
||||
const payload = parsePayload(jwtToken);
|
||||
if (!payload || !payload.exp) throw new Error("Bad id token payload");
|
||||
const duration = 1000 * payload.exp - new Date().getTime();
|
||||
if (!timer) {
|
||||
timer = getTimerWorker();
|
||||
timer.onMessage(async (e) => {
|
||||
if (e.data === "timeout") {
|
||||
const t = await refreshTokens();
|
||||
if (t && !t.error) return;
|
||||
document.location = signOut();
|
||||
if (authSource === 'keycloak') {
|
||||
// For Keycloak, just sign out - OIDC library handles refresh
|
||||
document.location = signOut();
|
||||
} else {
|
||||
const t = await refreshTokens();
|
||||
if (t && !t.error) return;
|
||||
document.location = signOut();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
timer.start(duration);
|
||||
};
|
||||
|
||||
const verifyKeycloakToken = async () => {
|
||||
try {
|
||||
const idToken = token.idToken;
|
||||
const payload = parsePayload(idToken);
|
||||
|
||||
// For Keycloak, we trust the token if it's not expired
|
||||
if (!payload || !payload.exp) throw new Error("Invalid Keycloak token");
|
||||
if (payload.exp * 1000 < Date.now()) throw new Error("Token expired");
|
||||
|
||||
// Extract groups from Keycloak token (realm_access.roles or groups claim)
|
||||
const keycloakGroups = payload.groups || payload.realm_access?.roles || [];
|
||||
setGroups(keycloakGroups);
|
||||
setProviders([]);
|
||||
startSessionTimer();
|
||||
} catch (e) {
|
||||
setError(`Keycloak verify error. ${e.message}`);
|
||||
document.location = signOut();
|
||||
}
|
||||
};
|
||||
|
||||
const verifyToken = async () => {
|
||||
try {
|
||||
const {
|
||||
@@ -96,6 +144,7 @@ export const UserProvider = ({ children }) => {
|
||||
throw new Error(result.message);
|
||||
}
|
||||
|
||||
setAuthSource('cognito');
|
||||
signedIn(result);
|
||||
} catch (err) {
|
||||
setError(`Sign in error. ${err.message}`);
|
||||
@@ -106,13 +155,42 @@ export const UserProvider = ({ children }) => {
|
||||
return result;
|
||||
};
|
||||
|
||||
// Sign in with Keycloak OIDC token
|
||||
const signInWithKeycloak = (oidcUser) => {
|
||||
if (!oidcUser || !oidcUser.id_token) return;
|
||||
|
||||
const keycloakToken = {
|
||||
authSource: 'keycloak',
|
||||
idToken: oidcUser.id_token,
|
||||
accessToken: oidcUser.access_token,
|
||||
refreshToken: oidcUser.refresh_token,
|
||||
profile: oidcUser.profile,
|
||||
};
|
||||
|
||||
setAuthSource('keycloak');
|
||||
setToken(keycloakToken);
|
||||
if (localStorage) {
|
||||
localStorage.setItem("token", JSON.stringify(keycloakToken));
|
||||
}
|
||||
};
|
||||
|
||||
const signOut = () => {
|
||||
setGroups(null);
|
||||
setProviders(null);
|
||||
setToken(null);
|
||||
setAuthSource(null);
|
||||
if (localStorage) {
|
||||
localStorage.removeItem("token");
|
||||
}
|
||||
|
||||
// For Keycloak, we need to redirect to Keycloak logout
|
||||
if (authSource === 'keycloak' && isKeycloakEnabled()) {
|
||||
const keycloakUrl = process.env.REACT_APP_KEYCLOAK_URL || 'https://keycloak.mini.cloud.fiskerinc.com';
|
||||
const realm = process.env.REACT_APP_KEYCLOAK_REALM || 'compute-auth';
|
||||
const redirectUri = process.env.REACT_APP_AUTH_CALLBACK_URL;
|
||||
return `${keycloakUrl}/realms/${realm}/protocol/openid-connect/logout?post_logout_redirect_uri=${encodeURIComponent(redirectUri)}`;
|
||||
}
|
||||
|
||||
return getLogoutURL();
|
||||
};
|
||||
|
||||
@@ -158,10 +236,12 @@ export const UserProvider = ({ children }) => {
|
||||
groups,
|
||||
providers,
|
||||
token,
|
||||
authSource,
|
||||
getAuthorizeURL,
|
||||
getLogoutURL,
|
||||
setError,
|
||||
signIn,
|
||||
signInWithKeycloak,
|
||||
signOut,
|
||||
refresh,
|
||||
}}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Button } from "@material-ui/core";
|
||||
import clsx from "clsx";
|
||||
import React, { useEffect } from "react";
|
||||
import { useAuth } from "react-oidc-context";
|
||||
|
||||
import { useUserContext } from "../Contexts/UserContext";
|
||||
import useStyles from "../useStyles";
|
||||
import { isKeycloakEnabled } from "../../services/keycloak";
|
||||
|
||||
const getCode = (search) => {
|
||||
if (!search) return null;
|
||||
@@ -11,7 +13,66 @@ const getCode = (search) => {
|
||||
return s.get("code");
|
||||
};
|
||||
|
||||
export default function SignInForm() {
|
||||
// Keycloak-enabled version of the form - only rendered when inside AuthProvider
|
||||
function KeycloakSignInForm() {
|
||||
const classes = useStyles();
|
||||
const { getAuthorizeURL, signIn, signInWithKeycloak, fetching } = useUserContext();
|
||||
const auth = useAuth();
|
||||
|
||||
// Handle Cognito callback
|
||||
useEffect(() => {
|
||||
const code = getCode(document.location.search);
|
||||
// Only process if it's a Cognito code (not a Keycloak callback)
|
||||
if (!code || auth?.isLoading || auth?.isAuthenticated) return;
|
||||
signIn(code);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
// Handle Keycloak authentication callback
|
||||
useEffect(() => {
|
||||
if (auth?.isAuthenticated && auth?.user) {
|
||||
signInWithKeycloak(auth.user);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [auth?.isAuthenticated, auth?.user]);
|
||||
|
||||
const handleKeycloakLogin = () => {
|
||||
auth.signinRedirect();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={clsx(classes.paper, classes.textJustifyAlign)}>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
className={classes.submit}
|
||||
href={getAuthorizeURL()}
|
||||
disabled={fetching}
|
||||
>
|
||||
{fetching ? "Please wait..." : "Sign In with Cognito"}
|
||||
</Button>
|
||||
|
||||
<div style={{ margin: '16px 0', textAlign: 'center', color: '#666' }}>
|
||||
— or —
|
||||
</div>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
className={classes.submit}
|
||||
onClick={handleKeycloakLogin}
|
||||
disabled={fetching || auth?.isLoading}
|
||||
>
|
||||
{auth?.isLoading ? "Loading..." : "Sign In with Keycloak"}
|
||||
</Button>
|
||||
|
||||
<p><strong>Note: Your email address will be used as the user id</strong></p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Standard Cognito-only form
|
||||
function CognitoSignInForm() {
|
||||
const classes = useStyles();
|
||||
const { getAuthorizeURL, signIn, fetching } = useUserContext();
|
||||
|
||||
@@ -38,3 +99,10 @@ export default function SignInForm() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function SignInForm() {
|
||||
if (isKeycloakEnabled()) {
|
||||
return <KeycloakSignInForm />;
|
||||
}
|
||||
return <CognitoSignInForm />;
|
||||
}
|
||||
|
||||
21
src/services/keycloak.js
Normal file
21
src/services/keycloak.js
Normal file
@@ -0,0 +1,21 @@
|
||||
// Keycloak OIDC configuration
|
||||
const KEYCLOAK_URL = process.env.REACT_APP_KEYCLOAK_URL || 'https://keycloak.mini.cloud.fiskerinc.com';
|
||||
const KEYCLOAK_REALM = process.env.REACT_APP_KEYCLOAK_REALM || 'compute-auth';
|
||||
const KEYCLOAK_CLIENT_ID = process.env.REACT_APP_KEYCLOAK_CLIENT_ID || 'ota-portal';
|
||||
const CALLBACK_URL = process.env.REACT_APP_AUTH_CALLBACK_URL;
|
||||
|
||||
export const keycloakConfig = {
|
||||
authority: `${KEYCLOAK_URL}/realms/${KEYCLOAK_REALM}`,
|
||||
client_id: KEYCLOAK_CLIENT_ID,
|
||||
redirect_uri: CALLBACK_URL,
|
||||
post_logout_redirect_uri: CALLBACK_URL,
|
||||
response_type: 'code',
|
||||
scope: 'openid',
|
||||
// Handle silent renew and callback automatically
|
||||
automaticSilentRenew: true,
|
||||
loadUserInfo: true,
|
||||
};
|
||||
|
||||
export const isKeycloakEnabled = () => {
|
||||
return process.env.REACT_APP_KEYCLOAK_ENABLED === 'true';
|
||||
};
|
||||
Reference in New Issue
Block a user