proceger 2.0.4 → 2.0.6

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/lib/app.js CHANGED
@@ -37,7 +37,7 @@ app.get('/task/:name/stop', async (req, res) => {
37
37
  });
38
38
 
39
39
  module.exports = async function() {
40
- await taskManager.loadFromConfig(config);
40
+ taskManager.loadFromConfig(config);
41
41
  app.listen(port);
42
42
  logger.info(`Application started at ${port}`);
43
43
  };
@@ -4,19 +4,19 @@ const Git = require('./git');
4
4
  class TaskManager {
5
5
  #tasks = {};
6
6
 
7
- async loadFromConfig(config) {
7
+ loadFromConfig(config) {
8
8
  const workspace = config.workspace;
9
9
  for (const taskConfig of config.tasks) {
10
- await this.addTask(workspace, taskConfig, config.pollUpdatesInterval);
10
+ this.addTask(workspace, taskConfig, config.pollUpdatesInterval);
11
11
  }
12
12
  }
13
13
 
14
14
  async addTask(workspace, config, pollUpdatesInterval) {
15
15
  const git = new Git(workspace, config.git.url);
16
16
  const task = new Task(config, git, pollUpdatesInterval);
17
+ this.#tasks[task.getName()] = task;
17
18
  await task.start();
18
19
  await task.pollUpdates();
19
- this.#tasks[task.getName()] = task;
20
20
  }
21
21
 
22
22
  getTask(name) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "proceger",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "A process manager with web interface.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -26,7 +26,7 @@
26
26
  "glob-promise": "^3.4.0",
27
27
  "rc": "^1.2.8",
28
28
  "serve-static": "^1.14.1",
29
- "simple-git": "^2.31.0",
29
+ "simple-git": "^3.3.0",
30
30
  "tree-kill": "^1.2.2",
31
31
  "uikit": "^3.6.16",
32
32
  "winston": "^3.3.3",
@@ -38,7 +38,7 @@
38
38
  "chai-as-promised": "^5.3.0",
39
39
  "eslint": "^7.19.0",
40
40
  "eslint-config-google": "^0.14.0",
41
- "mocha": "^8.2.1",
41
+ "mocha": "^10.1.0",
42
42
  "sinon": "^9.2.4"
43
43
  },
44
44
  "bugs": {
package/static/app.js CHANGED
@@ -1,70 +1,66 @@
1
- const $ = function(id, type, attributes = {}, children = []) {
2
- if (type === undefined) {
3
- return document.getElementById(id);
4
- }
5
- const elm = document.createElement(type);
6
- for (const [key, value] of Object.entries(attributes)) {
7
- elm.setAttribute(key, value);
8
- }
9
- if (typeof children === 'string') {
10
- elm.innerHTML = children;
11
- } else {
12
- for (const child of children) {
13
- elm.appendChild(child);
14
- }
15
- }
16
- if (id) {
17
- if (typeof id === 'string') {
18
- $(id).appendChild(elm);
19
- } else {
20
- id.appendChild(elm);
21
- }
22
- }
23
- return elm;
24
- };
25
-
26
- $$ = function(type, attributes, children) {
27
- return $(null, type, attributes, children);
28
- };
1
+ import e from './e.js';
29
2
 
30
3
  window.onload = async function() {
31
4
  const res = await fetch('/task/list');
32
5
  const tasks = await res.json();
33
- for (const task of tasks) {
34
- $('tasks-tab', 'li', {}, [$$('a', {'href': ''}, task.name)]);
35
- $('tasks-content', 'li', {}, [
36
- $$('div', {}, [
37
- $$('ul', {'class': 'uk-list'}, [
38
- $$('li', {}, `PID: ${task.pid}`),
39
- $$('li', {}, `Repository: ${task.git}`),
40
- $$('li', {}, `Revision: ${task.revision}`),
41
- $$('li', {}, `Start time: ${new Date(task.startTime)}`),
42
- ]),
43
- ]),
44
- $$('ul', {
45
- 'id': `task-${task.name}-logs-tab`,
46
- 'class': 'uk-tab',
47
- 'data-uk-tab': `{connect:'#task-${task.name}-logs'}`,
48
- }),
49
- $$('ul', {
50
- 'id': `task-${task.name}-logs`,
51
- 'class': 'uk-switcher uk-margin',
52
- }),
53
- ]);
54
- for (const [filename, logs] of Object.entries(task.logs)) {
55
- $(`task-${task.name}-logs-tab`, 'li', {}, [
56
- $$('a', {'href': ''}, filename),
57
- ]);
58
- $(`task-${task.name}-logs`, 'li', {}, [
59
- $$('div', {'class': 'logs'}, logs.split('\n').map((line) => {
6
+ e('tasks-tab', {}, tasks.map((task) => {
7
+ return ['li', {}, ['a', {'href': ''}, task.name]];
8
+ }));
9
+ e('tasks-content', {}, tasks.map((task) => ['li', {}, [
10
+ ['div', {}, [
11
+ ['ul', {'class': 'uk-list'}, [
12
+ ['li', {}, `PID: ${task.pid}`],
13
+ ['li', {}, `Repository: ${task.git}`],
14
+ ['li', {}, `Revision: ${task.revision}`],
15
+ ['li', {}, `Start time: ${new Date(task.startTime)}`],
16
+ ]],
17
+ ]],
18
+ ['p', {
19
+ 'uk-margin': '',
20
+ }, [
21
+ ['button', {
22
+ 'class': 'uk-button uk-button-default',
23
+ 'onclick': () => {
24
+ fetch(`/task/${task.name}/stop`);
25
+ },
26
+ }, 'Stop'],
27
+ ['span', {}, ' '],
28
+ ['button', {
29
+ 'class': 'uk-button uk-button-default',
30
+ 'onclick': () => {
31
+ fetch(`/task/${task.name}/restart`);
32
+ },
33
+ }, 'Restart'],
34
+ ]],
35
+ ['ul', {
36
+ 'id': `task-${task.name}-logs-tab`,
37
+ 'class': 'uk-tab',
38
+ 'data-uk-tab': `{connect:'#task-${task.name}-logs'}`,
39
+ },
40
+ Object.keys(task.logs).map((filename, index, files) => {
41
+ return ['li', {
42
+ 'class': index === files.length - 1 ? 'uk-active' : '',
43
+ }, [
44
+ ['a', {'href': ''}, filename],
45
+ ]];
46
+ }),
47
+ ],
48
+ ['ul', {
49
+ 'id': `task-${task.name}-logs`,
50
+ 'class': 'uk-switcher uk-margin',
51
+ },
52
+ Object.entries(task.logs).map(([filename, logs]) => {
53
+ return ['li', {}, [[
54
+ 'div', {'class': 'logs'}, logs.split('\n').map((line) => {
60
55
  try {
61
56
  const log = JSON.parse(line);
62
- return $$('p', {}, `${log.timestamp} ${log.message}`);
57
+ return ['p', {}, `${log.timestamp} ${log.message}`];
63
58
  } catch (e) {
64
- return $$('p', {}, '');
59
+ return ['p', {}, line];
65
60
  }
66
- })),
67
- ]);
68
- }
69
- }
61
+ }),
62
+ ]]];
63
+ }),
64
+ ],
65
+ ]]));
70
66
  };
package/static/e.js ADDED
@@ -0,0 +1,94 @@
1
+ /**
2
+ * e is a general purpose function to manipulate HTML DOM elements. In general
3
+ * it will return a DOMElement as a result.
4
+ *
5
+ * If the first argument is a string, it will return the element matching with
6
+ * that ID, or null if not elements is associated with that ID. The subsequce
7
+ * arguments will be used for update its attribute and children. For example,
8
+ *
9
+ * e('div1') is equivalent to document.getElementById('div1').
10
+ * e('div', {'style': 'color: red'}, 'Hello world') is equivalent to the
11
+ * following statements:
12
+ *
13
+ * const div = document.getElementById('div1');
14
+ * div.setAttribute('style', 'color: red');
15
+ * div.innerHTML = 'Hello world';
16
+ *
17
+ * If the param is an array, creates an HTML element based on the items in the
18
+ * array and return the element. The array should be in the form of the
19
+ * following:
20
+ *
21
+ * element := [type, {attributes...}, children]
22
+ * children := [elements...]|text
23
+ *
24
+ * If the children is a list of array, construct the children recursively and
25
+ * append to the current node. If the children is a string, simply set the
26
+ * node's innerHTML.
27
+ *
28
+ * @return {HTMLElement}
29
+ */
30
+ const e = function(...args) {
31
+ const getElement = function(param) {
32
+ return document.getElementById(param);
33
+ };
34
+
35
+ const setAttributes = function(elm, attributes) {
36
+ if (typeof attributes !== 'object') {
37
+ throw new Error(`Attributes must be an object, but got ${attributes}.`);
38
+ }
39
+ for (const [key, value] of Object.entries(attributes)) {
40
+ if (key.startsWith('on')) {
41
+ elm.addEventListener(key.substr(2), value);
42
+ } else {
43
+ elm.setAttribute(key, value);
44
+ }
45
+ }
46
+ };
47
+
48
+ const updateChildren = function(elm, children) {
49
+ if (typeof children === 'string') {
50
+ elm.innerHTML = children;
51
+ } else if (children instanceof Array) {
52
+ elm.innerHTML = '';
53
+ if (children.length > 0 && !(children[0] instanceof Array)) {
54
+ children = [children];
55
+ }
56
+ for (const child of children) {
57
+ const childElm = buildElement(child);
58
+ elm.appendChild(childElm);
59
+ }
60
+ } else {
61
+ throw new Error('Attributes must be an object');
62
+ }
63
+ };
64
+
65
+ const buildElement = function(param) {
66
+ const [type, attributes, children] = param;
67
+ const elm = document.createElement(type);
68
+ if (attributes !== undefined) {
69
+ setAttributes(elm, attributes);
70
+ }
71
+ if (children !== undefined) {
72
+ updateChildren(elm, children);
73
+ }
74
+ return elm;
75
+ };
76
+
77
+ let elm;
78
+ if (typeof args[0] === 'string' || args[0] instanceof String) {
79
+ elm = getElement(args[0]);
80
+ if (args.length >= 2) {
81
+ setAttributes(elm, args[1]);
82
+ }
83
+ if (args.length >= 3) {
84
+ updateChildren(elm, args[2]);
85
+ }
86
+ } else if (args[0] instanceof Array) {
87
+ elm = buildElement(args[0]);
88
+ } else {
89
+ throw new Error(`Unsupported arguments ${args}.`);
90
+ }
91
+ return elm;
92
+ };
93
+
94
+ export {e as default};
package/static/index.html CHANGED
@@ -9,7 +9,7 @@
9
9
  <link rel="stylesheet" href="css/uikit.min.css" />
10
10
  <script src="js/uikit.min.js"></script>
11
11
  <script src="js/uikit-icons.min.js"></script>
12
- <script src="app.js"></script>
12
+ <script type="module" src="app.js"></script>
13
13
  </head>
14
14
  <body>
15
15
  <h1 class="uk-heading-bullet">Proceger</h1>
@@ -0,0 +1,11 @@
1
+ [Unit]
2
+ Description=Proceger
3
+ After=network.target
4
+
5
+ [Service]
6
+ User=proceger
7
+ WorkingDirectory=/home/proceger/proceger-workspace
8
+ ExecStart=/bin/bash -c '. /home/proceger/.nvm/nvm.sh && exec proceger'
9
+
10
+ [Install]
11
+ WantedBy=multi-user.target
package/test/task.js CHANGED
@@ -73,8 +73,8 @@ describe('Task', function() {
73
73
  json.should.deep.equal({
74
74
  'git': 'git@github.com:sarosia/repo1.git',
75
75
  'logs': {
76
- 'stdout.log': 'log1\nlog2\nlog3\n',
77
- 'stderr.log': 'log1\nlog2\nlog3\n',
76
+ 'stdout.log': 'log1\nlog2\nlog3\n',
77
+ 'stderr.log': 'log1\nlog2\nlog3\n',
78
78
  },
79
79
  'name': 'repo1',
80
80
  'path': repo1Path,