Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .pipeline/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
const task = require('./lib/build.js')
const settings = require('./lib/config.js')

task(Object.assign(settings, { phase: 'build'}))
Promise.resolve(task(Object.assign(settings, { phase: 'build' }))).catch((error) => {
console.error(error);
process.exit(1);
})
5 changes: 4 additions & 1 deletion .pipeline/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
const settings = require('./lib/config.js')
const task = require('./lib/deploy.js')

task(Object.assign(settings, { phase: settings.options.env}));
Promise.resolve(task(Object.assign(settings, { phase: settings.options.env }))).catch((error) => {
console.error(error);
process.exit(1);
})
6 changes: 3 additions & 3 deletions .pipeline/lib/build.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"use strict";
const { OpenShiftClientX } = require("@bcgov/pipeline-cli");
const path = require("path");
const { HmcrOpenShiftClientX } = require("./openshift-client");

module.exports = (settings) => {
const phases = settings.phases;
const options = settings.options;
const oc = new OpenShiftClientX(
const oc = new HmcrOpenShiftClientX(
Object.assign({ namespace: phases.build.namespace }, options)
);
const phase = "build";
Expand Down Expand Up @@ -70,5 +70,5 @@ module.exports = (settings) => {
phases[phase].changeId,
phases[phase].instance
);
oc.applyAndBuild(objects);
return oc.applyAndBuild(objects);
};
89 changes: 61 additions & 28 deletions .pipeline/lib/deploy.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,49 @@
"use strict";
const { OpenShiftClientX } = require("@bcgov/pipeline-cli");
const path = require("path");

const buildTask = require("./build");
const { HmcrOpenShiftClientX } = require("./openshift-client");
const util = require("./util");

module.exports = (settings) => {
const imageNames = ["hmcr-api", "hmcr-client", "hmcr-hangfire"];

function missingBuildImages(oc, buildNamespace, version) {
return imageNames.filter((imageName) => {
try {
oc.raw(
"get",
["istag", `${imageName}:${version}`, "-o", "name"],
{ namespace: buildNamespace }
);
return false;
} catch (error) {
return true;
}
});
}

async function ensureBuildImages(settings, oc, version) {
const buildNamespace = settings.phases.build.namespace;
const missingImages = missingBuildImages(oc, buildNamespace, version);

if (missingImages.length === 0) {
return;
}

console.log(
`⚠️ Missing build image tags for ${version}: ${missingImages.join(", ")}. Rebuilding before deploy.`
);
await buildTask(settings);

const remainingMissingImages = missingBuildImages(oc, buildNamespace, version);
if (remainingMissingImages.length > 0) {
throw new Error(
`Build images are still missing after rebuild for ${version}: ${remainingMissingImages.join(", ")}`
);
}
}

module.exports = async (settings) => {
const phases = settings.phases;
const options = settings.options;
const phase = options.env;
Expand All @@ -13,20 +52,32 @@ module.exports = (settings) => {
const version = options.version || `v1.0.${githubRunNumber}`;
console.log(`🚀 Using version: ${version}`);

const oc = new OpenShiftClientX(
const oc = new HmcrOpenShiftClientX(
Object.assign({ namespace: phases[phase].namespace }, options)
);

const templatesLocalBaseUrl = oc.toFileUrl(
path.resolve(__dirname, "../../openshift")
);
var objects = [];
const logDbClaimName = `${phases[phase].name}-logdb${phases[phase].suffix}`;
const logDbSecret = util.getSecret(
oc,
phases[phase].namespace,
`${phases[phase].name}-logdb${phases[phase].suffix}`
logDbClaimName
);
const logDbPersistentVolumeSize = util.getPersistentVolumeClaimSize(
oc,
phases[phase].namespace,
logDbClaimName
);

if (logDbPersistentVolumeSize) {
console.log(
`Reusing existing logDb PVC size for ${logDbClaimName}: ${logDbPersistentVolumeSize}`
);
}

objects.push(
...oc.processDeploymentTemplate(
`${templatesLocalBaseUrl}/client-deploy-config.yaml`,
Expand Down Expand Up @@ -70,6 +121,9 @@ module.exports = (settings) => {
SUFFIX: phases[phase].suffix,
VERSION: version,
ENV: phases[phase].phase,
...(logDbPersistentVolumeSize
? { PERSISTENT_VOLUME_SIZE: logDbPersistentVolumeSize }
: {}),
},
}
)
Expand Down Expand Up @@ -137,37 +191,18 @@ module.exports = (settings) => {
`${changeId}`,
phases[phase].instance
);
await ensureBuildImages(settings, oc, version);
oc.importImageStreams(
objects,
phases[phase].tag,
phases.build.namespace,
version
);

// Ensure image streams are imported before proceeding
const imageNames = ["hmcr-api", "hmcr-client", "hmcr-hangfire"];
imageNames.forEach((imageName) => {
try {
console.log(`🔄 Importing image stream for ${imageName}`);
oc.raw("import-image", [
`${imageName}:${phases.build.tag}`,
`--from=d3d940-tools/${imageName}:${phases.build.tag}`,
"--confirm",
"-n",
phases.build.namespace,
]);
console.log(`✅ Successfully imported image stream for ${imageName}`);
} catch (error) {
console.error(`❌ Failed to import image stream for ${imageName}: ${error.message}`);
}
});

let imageExists = false;

oc.applyAndDeploy(objects, phases[phase].instance)
return oc.applyAndDeploy(objects, phases[phase].instance)
.then(() => {
const imageNames = ["hmcr-api", "hmcr-client", "hmcr-hangfire"];

imageExists = imageNames.every((imageName) => {
try {
const imageSha = oc.raw("get", [
Expand Down Expand Up @@ -209,8 +244,6 @@ module.exports = (settings) => {
console.log("❌ Skipping final tagging because image does not exist.");
return;
}
const imageNames = ["hmcr-api", "hmcr-client", "hmcr-hangfire"];

imageNames.forEach((imageName) => {
const sourceImage = `d3d940-tools/${imageName}:latest`;
const targetImage = `${phases[phase].namespace}/${imageName}`;
Expand All @@ -227,4 +260,4 @@ module.exports = (settings) => {
);
});
});
};
};
32 changes: 32 additions & 0 deletions .pipeline/lib/openshift-client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"use strict";

const { OpenShiftClientX } = require("@bcgov/pipeline-cli");

function normalizeImageStream(resource) {
if (
resource &&
resource.kind === "ImageStream" &&
resource.status &&
Array.isArray(resource.status.tags)
) {
resource.status.tags.forEach((tag) => {
if (!Array.isArray(tag.items)) {
tag.items = [];
}
});
}

return resource;
}

class HmcrOpenShiftClientX extends OpenShiftClientX {
object(name, args) {
return normalizeImageStream(super.object(name, args));
}

objects(names, args) {
return super.objects(names, args).map(normalizeImageStream);
}
}

module.exports = { HmcrOpenShiftClientX };
19 changes: 19 additions & 0 deletions .pipeline/lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,25 @@ function getSecret(oc, namespace, secretId) {
return secret;
}

function getPersistentVolumeClaimSize(oc, namespace, claimName) {
try {
const raw = oc.raw("get", [
"-n",
namespace,
"pvc",
claimName,
"-o",
"json",
]);
const claim = JSON.parse(raw.stdout);

return claim?.spec?.resources?.requests?.storage || null;
} catch (error) {
return null;
}
}

module.exports = {
getSecret,
getPersistentVolumeClaimSize,
};
5 changes: 3 additions & 2 deletions client/src/js/components/fragments/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const Header = ({ currentUser }) => {
const location = useLocation();
const [collapsed, setCollapsed] = useState(true);
const [version, setVersion] = useState(null);
const environmentClass = version || 'unknown';

useEffect(() => {
api.getVersion().then((response) => setVersion(response.data.environment.toLowerCase()));
Expand All @@ -48,7 +49,7 @@ const Header = ({ currentUser }) => {

return (
<header className="mb-3">
<Navbar expand="lg" className="navbar-dark">
<Navbar expand="lg" className={`navbar-dark header-nav ${environmentClass}`}>
<Container>
<NavbarBrand tag={Link} onClick={hideNavbar} to="/">
<img
Expand All @@ -72,7 +73,7 @@ const Header = ({ currentUser }) => {
<Collapse isOpen={!collapsed} navbar />
</Container>
</Navbar>
<Navbar expand="lg" className={`navbar-dark main-nav ${version}`}>
<Navbar expand="lg" className={`navbar-dark main-nav ${environmentClass}`}>
<Container>
<Collapse isOpen={!collapsed} navbar>
<Nav className="navbar-nav">
Expand Down
26 changes: 26 additions & 0 deletions client/src/scss/_nav.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
@import './vendor/bootstrap-theme.scss';

@mixin header-nav-colors($background-color) {
background-color: $background-color;
}

@mixin main-nav-colors($background-color) {
$nav-link-active-bg: lighten($background-color, 10%);

Expand Down Expand Up @@ -45,6 +49,28 @@
}
}

.header-nav {
@include header-nav-colors(#053662);
}

.header-nav.dev,
.header-nav.unknown {
@include header-nav-colors(#448a38);
}

.header-nav.test,
.header-nav.tst {
@include header-nav-colors(#f9a825);
}

.header-nav.prod {
@include header-nav-colors(#053662);
}

.header-nav.uat {
@include header-nav-colors(#744e91);
}

.main-nav {
@include main-nav-colors(#053662);
}
Expand Down
15 changes: 0 additions & 15 deletions openshift/api-build-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,6 @@ metadata:
labels:
template: api-build
objects:
- apiVersion: "v1"
kind: ImageStream
metadata:
name: postgresql-10
spec:
lookupPolicy:
local: false
tags:
- annotations: null
from:
kind: DockerImage
name: registry.redhat.io/rhel8/postgresql-10:1
name: "1"
referencePolicy:
type: Local
- apiVersion: "v1"
kind: ImageStream
metadata:
Expand Down
Loading