cht-conf 3.9.0 → 3.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/Dockerfile +2 -2
- package/README.md +28 -13
- package/package.json +5 -3
- package/src/fn/move-contacts.js +34 -10
- package/src/lib/api.js +13 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## [3.9.4](https://github.com/medic/cht-conf/compare/v3.9.3...v3.9.4) (2022-01-05)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **#460:** log useful error messages when api connection fails ([#461](https://github.com/medic/cht-conf/issues/461)) ([095a55c](https://github.com/medic/cht-conf/commit/095a55c9254c6872696cbee2fe42f244fc1fc4a8)), closes [#460](https://github.com/medic/cht-conf/issues/460) [#460](https://github.com/medic/cht-conf/issues/460)
|
|
7
|
+
|
|
8
|
+
## [3.9.3](https://github.com/medic/cht-conf/compare/v3.9.2...v3.9.3) (2021-12-16)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **#455:** allow empty translation constants ([ac170d7](https://github.com/medic/cht-conf/commit/ac170d7cce13a6a500d89884d4ca63801f06a969)), closes [#455](https://github.com/medic/cht-conf/issues/455)
|
|
14
|
+
|
|
15
|
+
## [3.9.2](https://github.com/medic/cht-conf/compare/v3.9.1...v3.9.2) (2021-12-08)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Performance Improvements
|
|
19
|
+
|
|
20
|
+
* **#432:** refactor the moving of reports to use a recursive function to improve performance ([c17b43b](https://github.com/medic/cht-conf/commit/c17b43b4d89b29b813db4be6e0f2d2c0a1e6c94d)), closes [#432](https://github.com/medic/cht-conf/issues/432)
|
|
21
|
+
|
|
22
|
+
## [3.9.1](https://github.com/medic/cht-conf/compare/v3.9.0...v3.9.1) (2021-11-16)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Bug Fixes
|
|
26
|
+
|
|
27
|
+
* **#448:** Bump Ubuntu version and Node version in container to fix docker usage. Updates to readme ([25cb955](https://github.com/medic/cht-conf/commit/25cb955377eea6c6a0a7cb3953d889b57c93884b))
|
|
28
|
+
|
|
1
29
|
# [3.9.0](https://github.com/medic/cht-conf/compare/v3.8.0...v3.9.0) (2021-11-01)
|
|
2
30
|
|
|
3
31
|
|
package/Dockerfile
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
FROM ubuntu:
|
|
1
|
+
FROM ubuntu:18.04
|
|
2
2
|
MAINTAINER DevOps "devops@medicmobile.org"
|
|
3
3
|
|
|
4
4
|
|
|
@@ -14,7 +14,7 @@ RUN echo "==> Installing Python dependencies" && \
|
|
|
14
14
|
RUN echo "====> Installing cht-conf python stuff" &&\
|
|
15
15
|
python -m pip install git+https://github.com/medic/pyxform.git@medic-conf-1.17#egg=pyxform-medic
|
|
16
16
|
|
|
17
|
-
RUN curl -sL https://deb.nodesource.com/
|
|
17
|
+
RUN curl -sL https://deb.nodesource.com/setup_12.x -o nodesource_setup.sh
|
|
18
18
|
RUN bash nodesource_setup.sh
|
|
19
19
|
RUN apt-get install -y nodejs
|
|
20
20
|
|
package/README.md
CHANGED
|
@@ -11,29 +11,44 @@ CHT Conf is a command-line interface tool to manage and configure your apps buil
|
|
|
11
11
|
|
|
12
12
|
# Installation
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Operating System Specific
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
docker run cht-conf:v0
|
|
18
|
-
docker exec -it <container_name> /bin/bash
|
|
19
|
-
|
|
20
|
-
## Ubuntu
|
|
16
|
+
### Ubuntu
|
|
21
17
|
|
|
22
18
|
npm install -g cht-conf
|
|
23
19
|
sudo python -m pip install git+https://github.com/medic/pyxform.git@medic-conf-1.17#egg=pyxform-medic
|
|
24
20
|
|
|
25
|
-
|
|
21
|
+
### OSX
|
|
26
22
|
|
|
27
23
|
npm install -g cht-conf
|
|
28
24
|
pip install git+https://github.com/medic/pyxform.git@medic-conf-1.17#egg=pyxform-medic
|
|
29
25
|
|
|
30
|
-
|
|
26
|
+
### Windows
|
|
31
27
|
|
|
32
28
|
As Administrator:
|
|
33
29
|
|
|
34
30
|
npm install -g cht-conf
|
|
35
31
|
python -m pip install git+https://github.com/medic/pyxform.git@medic-conf-1.17#egg=pyxform-medic --upgrade
|
|
36
32
|
|
|
33
|
+
### Docker
|
|
34
|
+
|
|
35
|
+
**NB** - `cht-conf` in a Docker container should only be used if you're familiar with running containers. You will have to copy or mount your config files into the container in order to be able to use the `cht` call to interact with a remote CHT instance.
|
|
36
|
+
|
|
37
|
+
Build and then run the `cht-conf` container:
|
|
38
|
+
|
|
39
|
+
docker build -t cht-conf:v0 .
|
|
40
|
+
docker run -d --name cht-conf cht-conf:v0
|
|
41
|
+
|
|
42
|
+
You now have a container running in the background called `cht-conf`. You can get a shell on this container with:
|
|
43
|
+
|
|
44
|
+
docker exec -it cht-conf /bin/bash
|
|
45
|
+
|
|
46
|
+
And then you can run the utility with `cht`.
|
|
47
|
+
|
|
48
|
+
When you are done with the container, you can stop it with:
|
|
49
|
+
|
|
50
|
+
docker stop cht-conf
|
|
51
|
+
|
|
37
52
|
## Bash completion
|
|
38
53
|
|
|
39
54
|
To enable tab completion in bash, add the following to your `.bashrc`/`.bash_profile`:
|
|
@@ -46,7 +61,7 @@ To upgrade to the latest version
|
|
|
46
61
|
|
|
47
62
|
npm install -g cht-conf
|
|
48
63
|
|
|
49
|
-
|
|
64
|
+
## Usage
|
|
50
65
|
|
|
51
66
|
`cht` will upload the configuration **from your current directory**.
|
|
52
67
|
|
|
@@ -60,9 +75,9 @@ For developers, this is the instance defined in your `COUCH_URL` environment var
|
|
|
60
75
|
|
|
61
76
|
cht --local
|
|
62
77
|
|
|
63
|
-
### A specific Medic
|
|
78
|
+
### A specific Medic-hosted instance
|
|
64
79
|
|
|
65
|
-
For configuring
|
|
80
|
+
For configuring Medic-hosted instances.
|
|
66
81
|
|
|
67
82
|
cht --instance=instance-name.dev
|
|
68
83
|
|
|
@@ -80,7 +95,7 @@ If a different username is required, add the `--user` switch:
|
|
|
80
95
|
|
|
81
96
|
cht --archive
|
|
82
97
|
|
|
83
|
-
The resulting archive is consumable by
|
|
98
|
+
The resulting archive is consumable by CHT API >v3.7 to create default configurations.
|
|
84
99
|
|
|
85
100
|
## Perform specific action(s)
|
|
86
101
|
|
|
@@ -267,7 +282,7 @@ To develop a new action or improve an existing one, check the ["Actions" doc](sr
|
|
|
267
282
|
|
|
268
283
|
## Testing
|
|
269
284
|
|
|
270
|
-
Execute `npm test` to run static analysis checks and the test suite.
|
|
285
|
+
Execute `npm test` to run static analysis checks and the test suite. Requires Docker to run integration tests against a CouchDB instance.
|
|
271
286
|
|
|
272
287
|
## Executing your local branch
|
|
273
288
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cht-conf",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.4",
|
|
4
4
|
"description": "Configure CHT deployments",
|
|
5
5
|
"main": "./src/lib/main.js",
|
|
6
6
|
"engines": {
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"clean": "rm -rf ./build/",
|
|
11
11
|
"eslint": "eslint src/**/*.js test/*.js test/**/*.js",
|
|
12
|
-
"
|
|
12
|
+
"docker-start-couchdb": "npm run docker-stop-couchdb && docker run -d -p 6984:5984 --rm --name cht-conf-couchdb couchdb:2.3.1 && sh test/scripts/wait_for_response_code.sh 6984 200 CouchDB",
|
|
13
|
+
"docker-stop-couchdb": "docker stop cht-conf-couchdb || true",
|
|
14
|
+
"test": "npm run eslint && npm run docker-start-couchdb && npm run clean && mkdir -p build/test && cp -r test/data build/test/data && cd build/test && nyc --reporter=html mocha --forbid-only ../../test/**/*.spec.js && cd ../.. && npm run docker-stop-couchdb",
|
|
13
15
|
"semantic-release": "semantic-release"
|
|
14
16
|
},
|
|
15
17
|
"bin": {
|
|
@@ -34,7 +36,7 @@
|
|
|
34
36
|
"homepage": "https://github.com/medic/cht-conf#readme",
|
|
35
37
|
"dependencies": {
|
|
36
38
|
"@hapi/joi": "^16.1.8",
|
|
37
|
-
"@medic/translation-checker": "1.0.
|
|
39
|
+
"@medic/translation-checker": "^1.0.1",
|
|
38
40
|
"canonical-json": "0.0.4",
|
|
39
41
|
"csv-parse": "^4.16.0",
|
|
40
42
|
"dom-compare": "^0.6.0",
|
package/src/fn/move-contacts.js
CHANGED
|
@@ -10,6 +10,7 @@ const pouch = require('../lib/db');
|
|
|
10
10
|
const { warn, trace, info, error } = require('../lib/log');
|
|
11
11
|
|
|
12
12
|
const HIERARCHY_ROOT = 'root';
|
|
13
|
+
const BATCH_SIZE = 10000;
|
|
13
14
|
|
|
14
15
|
module.exports = {
|
|
15
16
|
requiresInstance: true,
|
|
@@ -49,19 +50,15 @@ const updateLineagesAndStage = async (options, db) => {
|
|
|
49
50
|
trace(`Considering primary contact updates to ${ancestors.length} ancestor(s) of contact ${prettyPrintDocument(contactDoc)}.`);
|
|
50
51
|
const updatedAncestors = replaceLineageInAncestors(descendantsAndSelf, ancestors);
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
trace(`${reportsCreatedByDescendants.length} report(s) created by these affected contact(s) will update`);
|
|
54
|
-
const updatedReports = replaceLineageInReports(reportsCreatedByDescendants, replacementLineage, contactId);
|
|
53
|
+
minifyLineageAndWriteToDisk([...updatedDescendants, ...updatedAncestors], options);
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
writeDocumentToDisk(options, updatedDoc);
|
|
59
|
-
});
|
|
55
|
+
const movedReportsCount = await moveReports(db, descendantsAndSelf, options, replacementLineage, contactId);
|
|
56
|
+
trace(`${movedReportsCount} report(s) created by these affected contact(s) will be updated`);
|
|
60
57
|
|
|
61
58
|
affectedContactCount += updatedDescendants.length + updatedAncestors.length;
|
|
62
|
-
affectedReportCount +=
|
|
59
|
+
affectedReportCount += movedReportsCount;
|
|
63
60
|
|
|
64
|
-
info(`Staged updates to ${prettyPrintDocument(contactDoc)}. ${updatedDescendants.length} contact(s) and ${
|
|
61
|
+
info(`Staged updates to ${prettyPrintDocument(contactDoc)}. ${updatedDescendants.length} contact(s) and ${movedReportsCount} report(s).`);
|
|
65
62
|
}
|
|
66
63
|
|
|
67
64
|
info(`Staged changes to lineage information for ${affectedContactCount} contact(s) and ${affectedReportCount} report(s).`);
|
|
@@ -155,6 +152,31 @@ ${bold('OPTIONS')}
|
|
|
155
152
|
`);
|
|
156
153
|
};
|
|
157
154
|
|
|
155
|
+
const moveReports = async (db, descendantsAndSelf, writeOptions, replacementLineage, contactId) => {
|
|
156
|
+
const contactIds = descendantsAndSelf.map(contact => contact._id);
|
|
157
|
+
|
|
158
|
+
let skip = 0;
|
|
159
|
+
let reportDocsBatch;
|
|
160
|
+
do {
|
|
161
|
+
info(`Processing ${skip} to ${skip + BATCH_SIZE} report docs`);
|
|
162
|
+
reportDocsBatch = await fetch.reportsCreatedBy(db, contactIds, skip);
|
|
163
|
+
|
|
164
|
+
const updatedReports = replaceLineageInReports(reportDocsBatch, replacementLineage, contactId);
|
|
165
|
+
minifyLineageAndWriteToDisk(updatedReports, writeOptions);
|
|
166
|
+
|
|
167
|
+
skip += reportDocsBatch.length;
|
|
168
|
+
} while (reportDocsBatch.length >= BATCH_SIZE);
|
|
169
|
+
|
|
170
|
+
return skip;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const minifyLineageAndWriteToDisk = (docs, parsedArgs) => {
|
|
174
|
+
docs.forEach(doc => {
|
|
175
|
+
lineageManipulation.minifyLineagesInDoc(doc);
|
|
176
|
+
writeDocumentToDisk(parsedArgs, doc);
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
|
|
158
180
|
const writeDocumentToDisk = ({ docDirectoryPath }, doc) => {
|
|
159
181
|
const destinationPath = path.join(docDirectoryPath, `${doc._id}.doc.json`);
|
|
160
182
|
if (fs.exists(destinationPath)) {
|
|
@@ -214,10 +236,12 @@ const fetch = {
|
|
|
214
236
|
.filter(doc => doc && doc.type !== 'tombstone');
|
|
215
237
|
},
|
|
216
238
|
|
|
217
|
-
reportsCreatedBy: async (db, contactIds) => {
|
|
239
|
+
reportsCreatedBy: async (db, contactIds, skip) => {
|
|
218
240
|
const reports = await db.query('medic-client/reports_by_freetext', {
|
|
219
241
|
keys: contactIds.map(id => [`contact:${id}`]),
|
|
220
242
|
include_docs: true,
|
|
243
|
+
limit: BATCH_SIZE,
|
|
244
|
+
skip: skip,
|
|
221
245
|
});
|
|
222
246
|
|
|
223
247
|
return reports.rows.map(row => row.doc);
|
package/src/lib/api.js
CHANGED
|
@@ -99,8 +99,19 @@ const api = {
|
|
|
99
99
|
await request.get(url);
|
|
100
100
|
return true;
|
|
101
101
|
} catch (err) {
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
if (err.statusCode === 401) {
|
|
103
|
+
log.error(`Authentication failed connecting to ${url}. `
|
|
104
|
+
+ 'Check the supplied username and password and try again.');
|
|
105
|
+
} else if (err.statusCode === 403) {
|
|
106
|
+
log.error(`Insufficient permissions connecting to ${url}. `
|
|
107
|
+
+ 'You need to use admin permissions to execute this command.');
|
|
108
|
+
} else if (err.statusCode) {
|
|
109
|
+
log.error(`Received error code ${err.statusCode} connecting to ${url}. `
|
|
110
|
+
+ 'Check the server and and try again.');
|
|
111
|
+
} else {
|
|
112
|
+
log.error(`Failed to get a response from ${url}. Maybe you entered the wrong URL, `
|
|
113
|
+
+ 'wrong port or the instance is not started. Please check and try again.');
|
|
114
|
+
}
|
|
104
115
|
return false;
|
|
105
116
|
}
|
|
106
117
|
},
|