diff --git a/.github/workflows/pr-open.yml b/.github/workflows/pr-open.yml
index b933a78..c9e2f78 100644
--- a/.github/workflows/pr-open.yml
+++ b/.github/workflows/pr-open.yml
@@ -87,7 +87,39 @@ jobs:
# Deploy Helm Chart
cd charts/pubcode
helm dependency update
- helm upgrade --install --wait --atomic pubcode-${{ github.event.number }} --values values-pr.yaml --set-string global.repository=${{ github.repository }} --set-string api.containers[0].tag="${{ github.sha }}" --set-string frontend.containers[0].tag="${{ github.sha }}" --set-string global.secrets.emailRecipients="${{ secrets.EMAIL_RECIPIENTS }}" --set-string global.secrets.chesTokenURL="${{ secrets.CHES_TOKEN_URL }}" --set-string global.secrets.chesClientID="${{ secrets.CHES_CLIENT_ID }}" --set-string global.secrets.chesClientSecret="${{ secrets.CHES_CLIENT_SECRET }}" --set-string global.secrets.chesAPIURL="${{ secrets.CHES_API_URL }}" --set-string global.secrets.databaseAdminPassword="${{ secrets.DB_PWD }}" --set-string global.env.VITE_SCHEMA_BRANCH=${{ github.event.pull_request.head.ref }} --set-string namespace="${{ vars.oc_namespace }}" --timeout 5m .
+ helm upgrade --install --wait --atomic pubcode-${{ github.event.number }} \
+ --set-string global.repository=${{ github.repository }} \
+ --set-string api.containers[0].tag="${{ github.sha }}" \
+ --set-string api.containers[0].resources.limits.cpu="250m" \
+ --set-string api.containers[0].resources.limits.memory="250Mi" \
+ --set-string api.containers[0].resources.requests.cpu="100m" \
+ --set-string api.containers[0].resources.requests.memory="150Mi" \
+ --set api.autoscaling.minReplicas=1 \
+ --set api.autoscaling.maxReplicas=1 \
+ --set frontend.autoscaling.minReplicas=1 \
+ --set frontend.autoscaling.maxReplicas=1 \
+ --set-string frontend.containers[0].tag="${{ github.sha }}" \
+ --set-string frontend.containers[0].resources.limits.cpu="200m" \
+ --set-string frontend.containers[0].resources.limits.memory="150Mi" \
+ --set-string frontend.containers[0].resources.requests.cpu="100m" \
+ --set-string frontend.containers[0].resources.requests.memory="50Mi" \
+ --set-string database.containers[0].resources.limits.cpu="500m" \
+ --set-string database.containers[0].resources.limits.memory="450Mi" \
+ --set-string database.containers[0].resources.requests.cpu="100m" \
+ --set-string database.containers[0].resources.requests.memory="150Mi" \
+ --set-string database.initContainers[0].resources.limits.cpu="500m" \
+ --set-string database.initContainers[0].resources.limits.memory="450Mi" \
+ --set-string database.initContainers[0].resources.requests.cpu="100m" \
+ --set-string database.initContainers[0].resources.requests.memory="150Mi" \
+ --set-string database.pvc.size="350Mi" \
+ --set-string global.secrets.emailRecipients="${{ secrets.EMAIL_RECIPIENTS }}" \
+ --set-string global.secrets.chesTokenURL="${{ secrets.CHES_TOKEN_URL }}" \
+ --set-string global.secrets.chesClientID="${{ secrets.CHES_CLIENT_ID }}" \
+ --set-string global.secrets.chesClientSecret="${{ secrets.CHES_CLIENT_SECRET }}" \
+ --set-string global.secrets.chesAPIURL="${{ secrets.CHES_API_URL }}" \
+ --set-string global.secrets.databaseAdminPassword="${{ secrets.DB_PWD }}" \
+ --set-string global.env.VITE_SCHEMA_BRANCH=${{ github.event.pull_request.head.ref }} \
+ --set-string namespace="${{ vars.oc_namespace }}" -f values.yaml --timeout 5m .
cypress-e2e:
name: Cypress end to end test
diff --git a/api/src/app.js b/api/src/app.js
index 44c18ec..d9e3630 100644
--- a/api/src/app.js
+++ b/api/src/app.js
@@ -40,5 +40,9 @@ app.get("/", (req, res, next) => {
});
app.use(/(\/api)?/, apiRouter);
apiRouter.use("/pub-code", pubcodeRouter);
+app.use((req, res, next) => {
+ res.status(404).send(
+ "
Not Found.
");
+});
module.exports = app;
diff --git a/api/src/email/ches-service.js b/api/src/email/ches-service.js
index d7661eb..adb717f 100644
--- a/api/src/email/ches-service.js
+++ b/api/src/email/ches-service.js
@@ -26,7 +26,7 @@ class ChesService {
});
return { data, status };
} catch (e) {
- console.log(SERVICE, e);
+ console.error(SERVICE, e);
}
}
@@ -52,7 +52,7 @@ class ChesService {
return { data, status };
}
} catch (e) {
- console.log(SERVICE, e);
+ console.error(SERVICE, e);
}
}
@@ -81,7 +81,7 @@ class ChesService {
return { data, status };
}
} catch (e) {
- console.log(SERVICE, e);
+ console.error(SERVICE, e);
}
}
@@ -100,7 +100,8 @@ class ChesService {
);
return { data, status };
} catch (e) {
- console.log(SERVICE, e?.config?.data?.errors);
+ console.error(e);
+ console.error(SERVICE, e?.config?.data?.errors);
}
}
@@ -119,7 +120,7 @@ class ChesService {
);
return { data, status };
} catch (e) {
- console.log(SERVICE, e);
+ console.error(SERVICE, e);
}
}
@@ -138,7 +139,7 @@ class ChesService {
);
return { data, status };
} catch (e) {
- console.log(SERVICE, e);
+ console.error(SERVICE, e);
}
}
@@ -167,7 +168,7 @@ class ChesService {
return { data, status };
}
} catch (e) {
- console.log(SERVICE, e);
+ console.error(SERVICE, e);
}
}
diff --git a/api/src/routes/pubcode-router.js b/api/src/routes/pubcode-router.js
index c57b242..192160b 100644
--- a/api/src/routes/pubcode-router.js
+++ b/api/src/routes/pubcode-router.js
@@ -1,6 +1,6 @@
const express = require("express");
const router = express.Router();
-const { bulkLoad, readAll, findById, health } = require("../services/pub-code-service");
+const { bulkLoad, readAll, findById, health, softDeleteRepo } = require("../services/pub-code-service");
router.get("/ip/trace", (request, response) => response.send(request.ip));
router.get("/health", health);
@@ -11,8 +11,16 @@ router.post("/bulk-load", (req, res, next) => {
res.status(401).json({ message: "Unauthorized" });
}
}, bulkLoad);
-
+/**
+ * This method allows for patching the objects with soft
+ */
+router.delete("/:repo_name", (req, res, next) => {
+ if (req.header("X-API-KEY") && req.header("X-API-KEY") === process.env.API_KEY) {
+ next();
+ } else {
+ res.status(401).json({ message: "Unauthorized" });
+ }
+}, softDeleteRepo);
router.get("/", readAll);
-router.get("/:id", findById);
module.exports = router;
diff --git a/api/src/services/pub-code-service.js b/api/src/services/pub-code-service.js
index 236b90a..fcae3e8 100644
--- a/api/src/services/pub-code-service.js
+++ b/api/src/services/pub-code-service.js
@@ -115,10 +115,26 @@ const health = async (req, res) => {
res.status(500).json(error);
}
};
+const softDeleteRepo = async (req, res) => {
+ try {
+ let pubcodeEntityFromDB = await pubcodeEntity.findOne({ repo_name: req.params.repo_name }).exec();
+ if (!pubcodeEntityFromDB) {
+ res.status(404).json({ message: "Repo Not Found" });
+ } else {
+ await pubcodeEntity.updateOne({ _id: pubcodeEntityFromDB["_id"] }, { is_deleted: true }).exec();
+ pubcodeEntityFromDB = await pubcodeEntity.findOne({ repo_name: req.params.repo_name }).exec();
+ console.info(pubcodeEntityFromDB);
+ res.status(200).json({ message: "Repo Marked as soft deleted." });
+ }
+ } catch (e) {
+ console.error(e);
+ }
+};
module.exports = {
bulkLoad,
readAll,
findById,
- health
+ health,
+ softDeleteRepo
};
diff --git a/charts/pubcode/Chart.yaml b/charts/pubcode/Chart.yaml
index ecef98f..d499a99 100644
--- a/charts/pubcode/Chart.yaml
+++ b/charts/pubcode/Chart.yaml
@@ -27,18 +27,18 @@ dependencies:
- name: component
condition: api.enabled
- version: 0.0.11
+ version: 0.0.14
repository: https://bcgov.github.io/helm-service/
alias: api
- name: component
condition: frontend.enabled
- version: 0.0.11
+ version: 0.0.14
repository: https://bcgov.github.io/helm-service/
alias: frontend
- name: component
condition: database.enabled
- version: 0.0.11
+ version: 0.0.14
repository: https://bcgov.github.io/helm-service/
alias: database
diff --git a/charts/pubcode/values-pr.yaml b/charts/pubcode/values-pr.yaml
deleted file mode 100644
index ca939db..0000000
--- a/charts/pubcode/values-pr.yaml
+++ /dev/null
@@ -1,251 +0,0 @@
-# This is a YAML-formatted file.
-# Declare variables to be passed into your templates.
-global:
- repository: ~ # the repository where the images are stored.
- registry: ghcr.io # the registry where the images are stored. override during runtime for other registry at global level or individual level.
- env:
- LOG_LEVEL: "info"
- VITE_SCHEMA_BRANCH: "main"
- secrets:
- enabled: true
- databaseHost: '{{ .Release.Name }}-database'
- databaseAdminPassword: default
- databaseAdminUser: admin
- databaseName: pubcode
- apiKey: default
- emailRecipients: default
- chesTokenURL: default
- chesClientID: default
- chesClientSecret: default
- chesAPIURL: default
- domain: "apps.silver.devops.gov.bc.ca" # it is required, apps.silver.devops.gov.bc.ca for silver cluster
- openshiftImageRegistry: "image-registry.openshift-image-registry.svc:5000"
-
-api:
- enabled: true
- deployment: # can be either a statefulSet or a deployment not both
- enabled: true
-
- containers:
- - name: api
- registry: '{{ .Values.global.registry }}'
- repository: '{{ .Values.global.repository }}' # example, it includes registry and repository
- image: api # the exact component name, be it backend, api-1 etc...
- tag: prod # the tag of the image, it can be latest, 1.0.0 etc..., or the sha256 hash
- envFrom:
- secretRef:
- name: '{{ .Release.Name }}'
- ports:
- - name: http
- containerPort: 3000
- protocol: TCP
- resources: # this is optional
- limits:
- cpu: 150m
- memory: 250Mi
- requests:
- cpu: 100m
- memory: 150Mi
- readinessProbe:
- httpGet:
- path: /api/pub-code/health
- port: 3000
- scheme: HTTP
- initialDelaySeconds: 5
- periodSeconds: 2
- timeoutSeconds: 2
- successThreshold: 1
- failureThreshold: 30
- livenessProbe:
- successThreshold: 1
- failureThreshold: 3
- httpGet:
- path: /api/pub-code/health
- port: 3000
- scheme: HTTP
- initialDelaySeconds: 15
- periodSeconds: 30
- timeoutSeconds: 5
-
- autoscaling:
- enabled: true
- minReplicas: 1
- maxReplicas: 1
- targetCPUUtilizationPercentage: 80 # this percentage from request cpu
- vault:
- enabled: false
- service:
- enabled: true
- type: ClusterIP
- ports:
- - name: http
- port: 80
- targetPort: 3000 # the container port where the application is listening on
- protocol: TCP
- nodeSelector: { }
- tolerations: [ ]
- affinity: { }
- route:
- enabled: true
- host: "{{ .Release.Name }}-api.{{ .Values.global.domain }}"
- targetPort: http # look at line#164 refer to the name.
-
-frontend:
- enabled: true
- deployment: # can be either a statefulSet or a deployment not both
- enabled: true
- containers:
- - name: frontend
- registry: '{{ .Values.global.registry }}' # example, it includes registry
- repository: '{{ .Values.global.repository }}' # example, it includes repository
- image: frontend # the exact component name, be it backend, api-1 etc...
- tag: prod # the tag of the image, it can be latest, 1.0.0 etc..., or the sha256 hash
- securityContext:
- capabilities:
- add: [ "NET_BIND_SERVICE" ]
- env:
- fromValues:
- - name: VITE_SCHEMA_BRANCH
- value: '{{ .Values.global.env.VITE_SCHEMA_BRANCH }}'
- - name: LOG_LEVEL
- value: '{{ .Values.global.env.LOG_LEVEL }}'
- ports:
- - name: http
- containerPort: 3000
- protocol: TCP
- - name: http2
- containerPort: 3001
- protocol: TCP
- resources: # this is optional
- limits:
- cpu: 100m
- memory: 150Mi
- requests:
- cpu: 50m
- memory: 50Mi
- readinessProbe:
- httpGet:
- path: /health
- port: 3001
- scheme: HTTP
- initialDelaySeconds: 5
- periodSeconds: 2
- timeoutSeconds: 2
- successThreshold: 1
- failureThreshold: 30
- livenessProbe:
- successThreshold: 1
- failureThreshold: 3
- httpGet:
- path: /health
- port: 3001
- scheme: HTTP
- initialDelaySeconds: 15
- periodSeconds: 30
- timeoutSeconds: 5
- autoscaling:
- enabled: true
- minReplicas: 1
- maxReplicas: 1
- targetCPUUtilizationPercentage: 80 # this percentage from request cpu
- service:
- enabled: true
- type: ClusterIP
- ports:
- - name: http
- port: 80
- targetPort: 3000 # the container port where the application is listening on
- protocol: TCP
- route:
- enabled: true
- host: "{{ .Release.Name }}.{{ .Values.global.domain }}"
- targetPort: http # look at line#164 refer to the name.
-
-database:
- enabled: true
- deployment: # can be either a statefulSet or a deployment not both
- enabled: true
- deploymentStrategy:
- type: Recreate
- volumes:
- - name: '{{ .Release.Name }}-database'
- persistentVolumeClaim:
- claimName: '{{ .Release.Name }}-database'
- - name: '{{ include "component.fullname" . }}-config'
- configMap:
- name: '{{ include "component.fullname" . }}'
- initContainers:
- - name: database-init
- registry: 'ghcr.io' # example, it includes registry
- repository: 'bcgov/nr-containers' # example, it includes repository
- image: mongo # the exact component name, be it backend, api-1 etc...
- tag: 7.0.2 # the tag of the image, it can be latest, 1.0.0 etc..., or the sha256 hash
- command:
- - "sh"
- - "-c"
- - "mkdir -p /data/db"
- resources: # this is optional
- limits:
- cpu: 500m
- memory: 600Mi
- requests:
- cpu: 150m
- memory: 250Mi
- volumeMounts:
- - name: '{{ .Release.Name }}-database'
- mountPath: /data/db
- containers:
- - name: database
- registry: 'ghcr.io' # example, it includes registry
- repository: 'bcgov/nr-containers' # example, it includes repository
- image: mongo # the exact component name, be it backend, api-1 etc...
- tag: 7.0.2 # the tag of the image, it can be latest, 1.0.0 etc..., or the sha256 hash
- envFrom:
- secretRef:
- name: '{{ .Release.Name }}'
- ports:
- - name: http
- containerPort: 27017
- protocol: TCP
- resources: # this is optional
- limits:
- cpu: 350m
- memory: 600Mi
- requests:
- cpu: 150m
- memory: 250Mi
- readinessProbe:
- tcpSocket:
- port: 27017
- initialDelaySeconds: 10
- periodSeconds: 15
- timeoutSeconds: 5
- failureThreshold: 30
- livenessProbe:
- failureThreshold: 20
- initialDelaySeconds: 60
- periodSeconds: 15
- tcpSocket:
- port: 27017
- timeoutSeconds: 5
- volumeMounts:
- - name: '{{ .Release.Name }}-database'
- mountPath: /data/db
- autoscaling:
- enabled: false
- minReplicas: 1
- maxReplicas: 1
- targetCPUUtilizationPercentage: 80 # this percentage from request cpu
- service:
- enabled: true
- type: ClusterIP
- ports:
- - name: http
- port: 27017
- targetPort: 27017 # the container port where the application is listening on
- protocol: TCP
- pvc:
- enabled: true
- size: 512Mi
- storageClassName: netapp-file-standard
- accessModes: ReadWriteMany
diff --git a/utilities/remove-deleted-pubcode/index.js b/utilities/remove-deleted-pubcode/index.js
index e0a6539..f56ad16 100644
--- a/utilities/remove-deleted-pubcode/index.js
+++ b/utilities/remove-deleted-pubcode/index.js
@@ -28,13 +28,13 @@ async function doProcess() {
item.is_deleted = true;
}
}
- results.push(item);
+ results.push(repoName);
} catch (error) {
console.error(`Failed to fetch data for ${item.repo_name}:`, error);
process.exit(1);
}
}
- await bulkLoadPubCodes(results);
+ await markSoftDeleted(results);
} catch (error) {
console.error('Failed to fetch data:', error);
@@ -52,23 +52,25 @@ async function getYamlFromRepo(repoName, branchName) {
return yamlResponse;
}
-async function bulkLoadPubCodes(yamlArrayAsJson) {
- if (yamlArrayAsJson.length > 0) {
- console.debug(`Found ${yamlArrayAsJson.length} yaml files to load into database.`);
+async function markSoftDeleted(repoNames) {
+ if (repoNames.length > 0) {
+ console.info(`Found ${repoNames.length} yaml files to mark as soft delete.`);
+ console.info(repoNames);
//send to backend api bulk load endpoint
- try {
- await axios.post(`${API_URL}/api/pub-code/bulk-load`, yamlArrayAsJson, {
- headers: {
- "X-API-KEY": API_KEY
- }
- });
- console.debug(`Successfully loaded ${yamlArrayAsJson.length} yaml files into database.`);
- } catch (e) {
- console.error(e.response?.status);
- console.error(e.response?.config?.url);
+ for (const repoName of repoNames) {
+ try {
+ await axios.delete(`${API_URL}/api/pub-code/${repoName}`, {
+ headers: {
+ "X-API-KEY": API_KEY
+ }
+ });
+ } catch (e) {
+ console.error(e.response?.status);
+ console.error(e.response?.config?.url);
+ }
}
} else {
- console.debug(`No yaml files found at the root of repositories under bcgov.`);
+ console.info(`No yaml files to mark as soft delete.`);
}
}
try{