Skip to content

Commit 48d32cc

Browse files
Merge branch 'medic:master' into duplicate-prevention
2 parents 9526730 + 32bd626 commit 48d32cc

16 files changed

+2636
-145
lines changed

scripts/deploy/package-lock.json

+1,965
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/deploy/src/certificate.js

+12-9
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ const CERT_SOURCES = {
1313
const cert = config.CERT_FILE;
1414
const key = config.KEY_FILE;
1515

16-
const obtainCertificateAndKey = async function(values) {
16+
const obtainCertificateAndKey = async (values) => {
1717
console.log('Obtaining certificate...');
18-
const certSource = values.cert_source || '';
18+
const certSource = values?.cert_source || '';
1919

2020
const handlers = {
2121
[CERT_SOURCES.FILE]: () => handleFileSource(values),
@@ -31,7 +31,7 @@ const obtainCertificateAndKey = async function(values) {
3131
await handler();
3232
};
3333

34-
const handleFileSource = function({ certificate_crt_file_path, certificate_key_file_path }) {
34+
const handleFileSource = ({ certificate_crt_file_path, certificate_key_file_path }) => {
3535
if (!certificate_crt_file_path || !certificate_key_file_path) {
3636
throw new CertificateError('certificate_crt_file_path and certificate_key_file_path must be set for file source');
3737
}
@@ -40,7 +40,7 @@ const handleFileSource = function({ certificate_crt_file_path, certificate_key_f
4040
copyFile(certificate_key_file_path, key);
4141
};
4242

43-
const handleMyIpSource = async function() {
43+
const handleMyIpSource = async () => {
4444
const [crtData, keyData] = await Promise.all([
4545
fetchData(`${config.CERT_API_URL}/fullchain`),
4646
fetchData(`${config.CERT_API_URL}/key`)
@@ -50,27 +50,30 @@ const handleMyIpSource = async function() {
5050
writeFile(key, keyData);
5151
};
5252

53-
const copyFile = function(src, dest) {
53+
const copyFile = (src, dest) => {
5454
try {
5555
fs.copyFileSync(src, dest);
5656
} catch (error) {
5757
throw new CertificateError(`Failed to copy file from ${src} to ${dest}: ${error.message}`);
5858
}
5959
};
6060

61-
const writeFile = function(filename, data) {
61+
const writeFile = (filename, data) => {
6262
try {
6363
fs.writeFileSync(filename, data);
6464
} catch (error) {
6565
throw new CertificateError(`Failed to write file ${filename}: ${error.message}`);
6666
}
6767
};
6868

69-
const fetchData = async function(url) {
69+
const fetchData = async (url) => {
7070
try {
7171
const controller = new AbortController();
7272
const timeoutId = setTimeout(() => controller.abort(), config.FETCH_TIMEOUT);
7373
const response = await fetch(url, { signal: controller.signal });
74+
if (!response.ok) {
75+
throw response;
76+
}
7477
clearTimeout(timeoutId);
7578
return await response.text();
7679
} catch (error) {
@@ -104,12 +107,12 @@ const createSecret = async function (namespace, values) {
104107
cleanupFiles();
105108
};
106109

107-
const cleanupFiles = function() {
110+
const cleanupFiles = () => {
108111
deleteFile(cert);
109112
deleteFile(key);
110113
};
111114

112-
const deleteFile = function(filename) {
115+
const deleteFile = (filename) => {
113116
try {
114117
if (fs.existsSync(filename)) {
115118
fs.unlinkSync(filename);

scripts/deploy/src/config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export default {
22
MEDIC_REPO_NAME: process.env.MEDIC_REPO_NAME || 'medic',
33
MEDIC_REPO_URL: process.env.MEDIC_REPO_URL || 'https://docs.communityhealthtoolkit.org/helm-charts',
44
CHT_CHART_NAME: process.env.CHT_CHART_NAME || 'medic/cht-chart-4x',
5-
DEFAULT_CHART_VERSION: process.env.DEFAULT_CHART_VERSION || '1.0.*',
5+
DEFAULT_CHART_VERSION: process.env.DEFAULT_CHART_VERSION || '1.*.*',
66
IMAGE_TAG_API_URL: process.env.IMAGE_TAG_API_URL || 'https://staging.dev.medicmobile.org/_couch/builds_4',
77
CERT_FILE: process.env.CERT_FILE || 'certificate.crt',
88
KEY_FILE: process.env.KEY_FILE || 'private.key',

scripts/deploy/src/install.js

+38-32
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ import fetch from 'node-fetch';
44
import yaml from 'js-yaml';
55
import path from 'path';
66

7-
const MEDIC_REPO_NAME = 'medic';
8-
const MEDIC_REPO_URL = 'https://docs.communityhealthtoolkit.org/helm-charts';
9-
const CHT_CHART_NAME = `${MEDIC_REPO_NAME}/cht-chart-4x`;
10-
const DEFAULT_CHART_VERSION = '1.1.*';
7+
import config from './config.js';
8+
const { MEDIC_REPO_NAME, MEDIC_REPO_URL, CHT_CHART_NAME, DEFAULT_CHART_VERSION, IMAGE_TAG_API_URL } = config;
119

1210
import { fileURLToPath } from 'url';
1311
import { obtainCertificateAndKey, createSecret } from './certificate.js';
@@ -16,7 +14,7 @@ import { UserRuntimeError } from './error.js';
1614
const __filename = fileURLToPath(import.meta.url);
1715
const __dirname = path.dirname(__filename);
1816

19-
const readFile = function(f) {
17+
const readFile = (f) => {
2018
try {
2119
return yaml.load(fs.readFileSync(f, 'utf8'));
2220
} catch (err) {
@@ -25,22 +23,22 @@ const readFile = function(f) {
2523
}
2624
};
2725

28-
const prepare = function(f) {
26+
const prepare = (f) => {
2927
const values = readFile(f);
3028
const environment = values.environment || '';
3129
const scriptPath = path.join(__dirname, 'prepare.sh');
3230
child_process.execSync(`${scriptPath} ${environment}`, { stdio: 'inherit' }); //NoSONAR
3331
};
3432

35-
const loadValues = function(f) {
33+
const loadValues = (f) => {
3634
if (!f) {
3735
console.error('No values file provided. Please specify a values file using -f <file>');
3836
process.exit(1);
3937
}
4038
return readFile(f);
4139
};
4240

43-
const determineNamespace = function(values) {
41+
const determineNamespace = (values) => {
4442
const namespace = values.namespace || '';
4543
if (!namespace) {
4644
console.error('Namespace is not specified.');
@@ -49,43 +47,48 @@ const determineNamespace = function(values) {
4947
return namespace;
5048
};
5149

52-
const getImageTag = async function(chtversion) {
53-
const response = await fetch(`https://staging.dev.medicmobile.org/_couch/builds_4/medic:medic:${chtversion}`);
50+
const getImageTag = async (chtVersion) => {
51+
const response = await fetch(`${IMAGE_TAG_API_URL}/medic:medic:${chtVersion}`);
5452
const data = await response.json();
55-
const tag = data.tags && data.tags[0];
53+
const tag = data.tags?.[0];
5654
if (!tag) {
5755
return Promise.reject(new UserRuntimeError('cht image tag not found'));
5856
}
5957
return tag.image.split(':').pop();
6058
};
6159

62-
const getChartVersion = function(values) {
60+
const getChartVersion = (values) => {
6361
return values.cht_chart_version || DEFAULT_CHART_VERSION;
6462
};
6563

6664
const helmCmd = (action, positionalArgs, params) => {
67-
const flagsArray = Object.entries(params).map(([key, value]) => {
68-
if (value === true) {
69-
return `--${key}`;
70-
}
71-
if (value) {
72-
return `--${key} ${value}`;
73-
}
74-
return ''; //If value is falsy, don't include the flag
75-
}).filter(Boolean);
65+
const flagsArray = Object
66+
.entries(params)
67+
.map(([key, value]) => {
68+
if (value === true) {
69+
return `--${key}`;
70+
}
71+
if (value) {
72+
return `--${key} ${value}`;
73+
}
74+
return ''; //If value is falsy, don't include the flag
75+
})
76+
.filter(Boolean);
7677

7778
const command = `helm ${action} ${positionalArgs.join(' ')} ${flagsArray.join(' ')}`;
78-
return child_process.execSync(command, { stdio: 'inherit' }); //NoSONAR
79+
return child_process.execSync(command, { stdio: 'inherit' });
7980
};
8081

81-
const helmInstallOrUpdate = function(valuesFile, namespace, values, imageTag) {
82+
const helmInstallOrUpdate = (valuesFile, namespace, values, imageTag) => {
8283
const chartVersion = getChartVersion(values);
8384
ensureMedicHelmRepo();
8485
const projectName = values.project_name || '';
8586
const namespaceExists = checkNamespaceExists(namespace);
8687

8788
try {
88-
const releaseExists = child_process.execSync(`helm list -n ${namespace}`).toString() //NoSONAR
89+
const releaseExists = child_process
90+
.execSync(`helm list -n ${namespace}`)
91+
.toString()
8992
.includes(projectName);
9093

9194
const commonOpts = {
@@ -121,29 +124,32 @@ const helmInstallOrUpdate = function(valuesFile, namespace, values, imageTag) {
121124
}
122125
};
123126

124-
const checkNamespaceExists = function(namespace) {
127+
const checkNamespaceExists = (namespace) => {
125128
try {
126-
const result = child_process.execSync(`kubectl get namespace ${namespace}`).toString(); //NoSONAR
127-
return result.includes(namespace); //NoSONAR
129+
const result = child_process.execSync(`kubectl get namespace ${namespace}`).toString();
130+
return result.includes(namespace);
128131
} catch (err) {
129132
return false;
130133
}
131134
};
132135

133-
const ensureMedicHelmRepo = function() {
136+
const ensureMedicHelmRepo = () => {
134137
try {
135138
const repoList = child_process.execSync(`helm repo list -o json`).toString();
136139
const repos = JSON.parse(repoList);
137140
const medicRepo = repos.find(repo => repo.name === MEDIC_REPO_NAME);
141+
138142
if (!medicRepo) {
139143
console.log(`Helm repo ${MEDIC_REPO_NAME} not found, adding..`);
140-
child_process.execSync(`helm repo add ${MEDIC_REPO_NAME} ${MEDIC_REPO_URL}`, { stdio: 'inherit' }); //NoSONAR
144+
child_process.execSync(`helm repo add ${MEDIC_REPO_NAME} ${MEDIC_REPO_URL}`, { stdio: 'inherit' });
141145
return;
142-
} else if (medicRepo.url.replace(/\/$/, '') !== MEDIC_REPO_URL) {
146+
}
147+
148+
if (medicRepo.url.replace(/\/$/, '') !== MEDIC_REPO_URL) {
143149
throw new UserRuntimeError(`Medic repo found but url not matching '${MEDIC_REPO_URL}', see: helm repo list`);
144150
}
145151
// Get the latest
146-
child_process.execSync(`helm repo update ${MEDIC_REPO_NAME}`, { stdio: 'inherit' }); //NoSONAR
152+
child_process.execSync(`helm repo update ${MEDIC_REPO_NAME}`, { stdio: 'inherit' });
147153
} catch (err) {
148154
console.error(err.message);
149155
if (err.stack) {
@@ -153,7 +159,7 @@ const ensureMedicHelmRepo = function() {
153159
}
154160
};
155161

156-
const install = async function(f) {
162+
const install = async (f) => {
157163
prepare(f);
158164
const values = loadValues(f);
159165
const namespace = determineNamespace(values);

shared-libs/search/src/generate-search-requests.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ const sortByLastVisitedDate = () => {
191191
const makeCombinedParams = (freetextRequest, typeKey) => {
192192
const type = typeKey[0];
193193
const params = {};
194-
if (freetextRequest.key) {
194+
if (freetextRequest.params.key) {
195195
params.key = [ type, freetextRequest.params.key[0] ];
196196
} else {
197197
params.startkey = [ type, freetextRequest.params.startkey[0] ];

tests/e2e/default/enketo/pregnancy-danger-sign-follow-up.wdio-spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ describe('Pregnancy danger sign follow-up form', () => {
1111
const person = personFactory.build();
1212

1313
const fillPregnancyDangerSignFollowUpForm = async (attendToVisit, hasDangerSigns) => {
14-
await genericForm.selectContact(person.name);
14+
await genericForm.selectContact(person.name, 'What is the patient\'s name?');
1515
await genericForm.nextPage();
1616
await commonEnketoPage.selectRadioButton('Did the woman visit the health facility as recommended?', attendToVisit);
1717
await commonEnketoPage.selectRadioButton('Is she still experiencing any danger signs?', hasDangerSigns);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0"?>
2+
<h:html xmlns="http://www.w3.org/2002/xforms" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jr="http://openrosa.org/javarosa" xmlns:orx="http://openrosa.org/xforms">
3+
<h:head>
4+
<h:title>Select contact by type and without type</h:title>
5+
<model>
6+
<itext>
7+
<translation lang="en">
8+
<text id="/data/select_contact_by_type:label">
9+
<value>Select the contact by type</value>
10+
</text>
11+
<text id="/data/select_contact_without_type:label">
12+
<value>Select the contact without type</value>
13+
</text>
14+
</translation>
15+
</itext>
16+
<instance>
17+
<data id="select_contact_telemetry" prefix="J1!select_contact_telemetry!" delimiter="#" version="2024-10-30 16-00">
18+
<select_contact_by_type/>
19+
<select_contact_without_type/>
20+
<meta tag="hidden">
21+
<instanceID/>
22+
</meta>
23+
</data>
24+
</instance>
25+
<bind nodeset="/data/select_contact_by_type" type="db:person"/>
26+
<bind nodeset="/data/select_contactselect_contact_without_type"/>
27+
</model>
28+
</h:head>
29+
<h:body class="pages">
30+
<group appearance="field-list" ref="/data">
31+
<input appearance="select-contact" ref="/data/select_contact_by_type">
32+
<label ref="jr:itext('/data/select_contact_by_type:label')"/>
33+
</input>
34+
<input appearance="select-contact" ref="/data/select_contact_without_type">
35+
<label ref="jr:itext('/data/select_contact_without_type:label')"/>
36+
</input>
37+
</group>
38+
</h:body>
39+
</h:html>

0 commit comments

Comments
 (0)