lazylead 0.2.0 → 0.3.0
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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +12 -4
- data/.docker/Dockerfile +5 -4
- data/.docker/vcs.dockerfile +10 -0
- data/.docs/duedate_expired.md +92 -0
- data/.docs/propagate_down.md +89 -0
- data/.rubocop.yml +1 -1
- data/.rultor.yml +2 -2
- data/.simplecov +0 -6
- data/bin/lazylead +4 -2
- data/lazylead.gemspec +2 -14
- data/lib/lazylead/cc.rb +174 -0
- data/lib/lazylead/exchange.rb +14 -1
- data/lib/lazylead/home.rb +38 -0
- data/lib/lazylead/model.rb +23 -11
- data/lib/lazylead/postman.rb +14 -14
- data/lib/lazylead/system/fake.rb +1 -1
- data/lib/lazylead/system/jira.rb +42 -5
- data/lib/lazylead/task/propagate_down.rb +118 -0
- data/lib/lazylead/task/savepoint.rb +58 -0
- data/lib/lazylead/version.rb +1 -1
- data/lib/messages/due_date_expired.erb +8 -7
- data/lib/messages/illegal_fixversion_change.erb +9 -8
- data/lib/messages/missing_comment.erb +10 -9
- data/lib/messages/savepoint.erb +43 -0
- data/readme.md +18 -16
- data/test/lazylead/cc_test.rb +133 -0
- data/test/lazylead/cli/app_test.rb +1 -2
- data/test/lazylead/exchange_test.rb +20 -0
- data/test/lazylead/model_test.rb +11 -0
- data/test/lazylead/postman_test.rb +57 -0
- data/test/lazylead/task/duedate_test.rb +16 -0
- data/test/lazylead/task/propagate_down_test.rb +86 -0
- data/test/lazylead/task/savepoint_test.rb +51 -0
- data/upgrades/sqlite/001-install-main-lazylead-tables.sql +0 -1
- data/upgrades/sqlite/999.testdata.sql +4 -1
- metadata +19 -171
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1515ec779095fe067759c774a8f81a7f563d55e7f7c9dc9f8cb96644688d1a7e
|
4
|
+
data.tar.gz: dfe37f6ed725f609ea1c685c85d17581a87dea40ff1bc3be7967cb15d5c81405
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24246a8ef909f298256a358e6c59778b5e9440aeb8dadfd32dbae21a079832ef3ee6e8126949803784aa2543866626ee3e71a0ee1ef5a102d725b0269aef155c
|
7
|
+
data.tar.gz: 445720af7f02f9497b9baf42b2657ea4c428fd2f088d72b1db03b9679f617fc45f049ba6af22dc9e05669c41c0d262fc63d76be06df051ab7e0cbf7f79a03923
|
data/.circleci/config.yml
CHANGED
@@ -16,9 +16,8 @@ jobs:
|
|
16
16
|
machine: true
|
17
17
|
steps:
|
18
18
|
- checkout
|
19
|
-
# build the application image
|
20
19
|
- run:
|
21
|
-
name: "Build
|
20
|
+
name: "Build LL image"
|
22
21
|
command: |
|
23
22
|
set -e
|
24
23
|
COMMIT_URL="https://github.com/dgroup/lazylead/commit/${CIRCLE_SHA1}"
|
@@ -32,12 +31,21 @@ jobs:
|
|
32
31
|
expected="No tasks found"
|
33
32
|
echo "Ensure that app prints the line '${expected}'."
|
34
33
|
grep --color "${expected}" trace.log
|
35
|
-
# publish the image
|
36
34
|
- run:
|
37
|
-
name: "
|
35
|
+
name: "Push LL image"
|
38
36
|
command: |
|
39
37
|
chmod +x .circleci/release_image.sh
|
40
38
|
.circleci/release_image.sh
|
39
|
+
- run:
|
40
|
+
name: "Build & push LL VCS image"
|
41
|
+
command: |
|
42
|
+
sed -i "s/0\.0\.0/${DOCKER_RELEASE_TAGS}/g" .docker/vcs.dockerfile
|
43
|
+
docker build -t dgroup/lazylead:${DOCKER_RELEASE_TAGS}-vcs . -f .docker/vcs.dockerfile
|
44
|
+
docker push dgroup/lazylead:${DOCKER_RELEASE_TAGS}-vcs
|
45
|
+
- run:
|
46
|
+
name: "Reset tag to master"
|
47
|
+
command: |
|
48
|
+
curl -s -X POST -u ${CI_TOKEN}:"" --url "https://circleci.com/api/v2/project/gh/dgroup/lazylead/envvar" -H "accept: application/json" -H "content-type: application/json" -d "{ \"name\": \"DOCKER_RELEASE_TAGS\", \"value\": \"master\" }"
|
41
49
|
workflows:
|
42
50
|
version: 2
|
43
51
|
build_and_test:
|
data/.docker/Dockerfile
CHANGED
@@ -12,15 +12,16 @@ ENV APP_HOME=/lazylead
|
|
12
12
|
|
13
13
|
WORKDIR $APP_HOME
|
14
14
|
|
15
|
-
# @todo #/DEV
|
15
|
+
# @todo #/DEV Original size of lazylead was 350 MB.
|
16
|
+
# After removing of unnecessary libraries it took 250 MB.
|
16
17
|
# The original alpine image is ~20MB.
|
17
18
|
# Image cleanup is required.
|
18
19
|
RUN echo "Install 3rd-party libraries." \
|
19
|
-
&& apk add libc-dev gcc make
|
20
|
+
&& apk add --no-cache libc-dev gcc git make sqlite sqlite-dev sqlite-libs tree
|
20
21
|
|
21
22
|
COPY Gemfile lazylead.gemspec ./
|
22
23
|
|
23
|
-
RUN bundler install
|
24
|
+
RUN bundler install --without development
|
24
25
|
|
25
26
|
COPY bin/lazylead ./bin/lazylead
|
26
27
|
COPY lib ./lib
|
@@ -28,4 +29,4 @@ COPY upgrades ./upgrades
|
|
28
29
|
|
29
30
|
RUN sed -i "s/0\.0\.0/${version}/g" lib/lazylead/version.rb
|
30
31
|
|
31
|
-
CMD ["bin/lazylead", "--trace", "--verbose"
|
32
|
+
CMD ["bin/lazylead", "--trace", "--verbose"]
|
@@ -0,0 +1,10 @@
|
|
1
|
+
FROM dgroup/lazylead:0.0.0
|
2
|
+
|
3
|
+
LABEL about="https://github.com/dgroup/lazylead" \
|
4
|
+
ci.contact="yurii.dubinka@gmail.com" \
|
5
|
+
ci.release.tag="${release_tags}" \
|
6
|
+
ll.docker.issues="https://github.com/dgroup/lazylead/issues?utf8=✓&q=label%3Adocker"
|
7
|
+
|
8
|
+
RUN apk add --no-cache subversion git mercurial
|
9
|
+
|
10
|
+
CMD ["bin/lazylead", "--trace", "--verbose"]
|
@@ -0,0 +1,92 @@
|
|
1
|
+
## Notify Jira ticket assignee about expired(ing) due date
|
2
|
+
#### Why?
|
3
|
+
Why do we need this if Jira has `Filter Subscription` feature:
|
4
|
+
- https://confluence.atlassian.com/jira064/receiving-search-results-via-email-720416706.html
|
5
|
+
- https://confluence.atlassian.com/jiracorecloud/advanced-searching-765593707.html
|
6
|
+
|
7
|
+
As far as I know, filter subscription feature doesn't allow(for now) to group tickets by assignee and send to each of them personal message with missing due dates.
|
8
|
+
Right now its just send whole list of tickets to you or specified group.
|
9
|
+
In worst cases, shared responsibility leads to irresponsibility each individual.
|
10
|
+
|
11
|
+
#### How to use lazylead for this
|
12
|
+
Let's assume that
|
13
|
+
1. JQL for tickets with expired due dates: `project = PRJ and resolution = unresolved and duedate < startOfDay()`
|
14
|
+
2. you've saved this JQL as jira filter with id `222`
|
15
|
+
3. you want to sent an email notification to each assignee about his/her missing due dates over `MS Exchange server`
|
16
|
+
|
17
|
+
For simplicity, we are using [docker-compose](https://docs.docker.com/compose/):
|
18
|
+
1. Define yml file with `docker-compose` configuration in `lazylead.yml`
|
19
|
+
```yml
|
20
|
+
version: '2.3'
|
21
|
+
services:
|
22
|
+
lazylead:
|
23
|
+
image: dgroup/lazylead:latest
|
24
|
+
container_name: lazylead
|
25
|
+
mem_limit: 128m
|
26
|
+
environment:
|
27
|
+
# The jira server details.
|
28
|
+
# Please ensure that your jira filter(s) grants this user to see issues.
|
29
|
+
# Sometimes jira filter(s) may be created with restricted visibility, thus
|
30
|
+
# lazylead can't find the issues.
|
31
|
+
jira_url: https://your.jira.com
|
32
|
+
jira_user: theuser
|
33
|
+
jira_password: thepass
|
34
|
+
# The MS Exchange server details, please ensure that '/ews/Exchange.asm`
|
35
|
+
# will be after your server url. Just change the url to your server.
|
36
|
+
exchange_url: https://your.ms.exchange.server/ews/Exchange.asmx
|
37
|
+
exchange_user: theuser
|
38
|
+
exchange_password: the password
|
39
|
+
volumes:
|
40
|
+
- ./:/lazylead/db
|
41
|
+
# db/ll.db is sqlite file with jira related annoying tasks
|
42
|
+
entrypoint: bin/lazylead --sqlite db/ll.db --trace --verbose
|
43
|
+
```
|
44
|
+
|
45
|
+
2. Create a container, using `docker-compose -f lazylead.yml up`
|
46
|
+
The container will stop as there were no tasks provided:
|
47
|
+
```bash
|
48
|
+
ll > docker-compose -f lazylead.yml up
|
49
|
+
Creating lazylead ... done
|
50
|
+
Attaching to lazylead
|
51
|
+
lazylead | [2020-06-06T10:35:13] DEBUG Memory footprint at start is 52MB
|
52
|
+
lazylead | [2020-06-06T10:35:13] DEBUG Database: '/lazylead/db/ll.db', sql migration dir: '/lazylead/upgrades/sqlite'
|
53
|
+
lazylead | [2020-06-06T10:35:13] DEBUG Migration applied to /lazylead/db/ll.db from /lazylead/upgrades/sqlite
|
54
|
+
lazylead | [2020-06-06T10:35:13] DEBUG Database connection established
|
55
|
+
lazylead | [2020-06-06T10:35:13] WARN SMTP connection enabled in test mode.
|
56
|
+
lazylead | [2020-06-06T10:35:13] WARN ll-001: No tasks found.
|
57
|
+
lazylead | [2020-06-06T10:35:13] DEBUG Memory footprint at the end is 66MB
|
58
|
+
lazylead exited with code 0
|
59
|
+
ll >
|
60
|
+
```
|
61
|
+
|
62
|
+
3. Define your team and tasks in database.
|
63
|
+
The tables structure defined [here](../upgrades/sqlite/001-install-main-lazylead-tables.sql).
|
64
|
+
Modify you [sqlite](https://sqlite.com/index.html) file(`ll.db`) using [DB Browser](https://sqlitebrowser.org/) or any similar tool.
|
65
|
+
You may add your email into tasks.properties `"cc":"your@email.com"` in order to be aware that developer got the message, but i don't recommend you as you'll get a dozen of messages in a few days :) .
|
66
|
+
```sql
|
67
|
+
insert into teams (id, name, properties)
|
68
|
+
values (1, 'Dream team with lazylead', '{}');
|
69
|
+
insert into systems(id, properties)
|
70
|
+
values (1,'{"type":"Lazylead::Jira", "username":"${jira_user}", "password":"${jira_password}", "site":"${jira_url}", "context_path":""}');
|
71
|
+
insert into tasks (name, cron, enabled, id, system, team_id, action, properties)
|
72
|
+
values ('Expired due dates',
|
73
|
+
'0 8 * * 1-5',
|
74
|
+
'true',
|
75
|
+
1, 1, 1,
|
76
|
+
'Lazylead::Task::AssigneeAlert',
|
77
|
+
'{"sql":"filter=222", "cc":"<youremail.com>", "subject":"[LL] Expired due dates", "template":"lib/messages/due_date_expired.erb", "postman":"Lazylead::Exchange"}');
|
78
|
+
|
79
|
+
```
|
80
|
+
Yes, for task scheduling we are using [cron](https://crontab.guru).
|
81
|
+
|
82
|
+
4. Once you changed `./ll.db`, please restart the container using `docker-compose -f .github/tasks.yml restart`
|
83
|
+
```bash
|
84
|
+
ll > docker-compose -f .github/tasks.yml restart
|
85
|
+
Restarting lazylead ... done
|
86
|
+
```
|
87
|
+
|
88
|
+
|
89
|
+
#### Where is the code?
|
90
|
+
| Logic | Tests | Email Template |
|
91
|
+
| :-----: | :------: | :-----: |
|
92
|
+
| AssigneeAlert in [alert.rb](../lib/lazylead/task/alert.rb)| [duedate_test.rb](../test/lazylead/task/duedate_test.rb) | [due_date_expired.erb](../lib/messages/due_date_expired.erb) |
|
@@ -0,0 +1,89 @@
|
|
1
|
+
## Propagate fields from parent Jira ticket to sub-tasks
|
2
|
+
#### Why?
|
3
|
+
Why do we need this if Jira has automation already?
|
4
|
+
|
5
|
+
Could you able use this feature right now? Just right now, without requests to some admin/jira owner/submitting some tickets to someone/etc... I doubt.
|
6
|
+
In a huge company that's almost impossible to change something special for you in short terms.
|
7
|
+
|
8
|
+
#### How to use lazylead for this
|
9
|
+
Let's assume that
|
10
|
+
1. JQL for parent tickets for the propagation: `issue in parentsOf("project='PRJ' and 'External ID' is empty") and "External ID" is not empty and updated >-1d`.
|
11
|
+
2. you've saved this JQL as jira filter with id `222`.
|
12
|
+
|
13
|
+
For simplicity, we are using [docker-compose](https://docs.docker.com/compose/):
|
14
|
+
1. Define yml file with `docker-compose` configuration in `lazylead.yml`
|
15
|
+
```yml
|
16
|
+
version: '2.3'
|
17
|
+
services:
|
18
|
+
lazylead:
|
19
|
+
image: dgroup/lazylead:latest
|
20
|
+
container_name: lazylead
|
21
|
+
mem_limit: 128m
|
22
|
+
environment:
|
23
|
+
# The jira server details.
|
24
|
+
# Please ensure that your jira filter(s) grants this user to see issues.
|
25
|
+
# Sometimes jira filter(s) may be created with restricted visibility, thus
|
26
|
+
# lazylead can't find the issues.
|
27
|
+
jira_url: https://your.jira.com
|
28
|
+
jira_user: theuser
|
29
|
+
jira_password: thepass
|
30
|
+
volumes:
|
31
|
+
- ./:/lazylead/db
|
32
|
+
# db/ll.db is sqlite file with jira related annoying tasks
|
33
|
+
entrypoint: bin/lazylead --sqlite db/ll.db --trace --verbose
|
34
|
+
```
|
35
|
+
|
36
|
+
2. Create a container, using `docker-compose -f lazylead.yml up`
|
37
|
+
The container will stop as there were no tasks provided:
|
38
|
+
```bash
|
39
|
+
ll > docker-compose -f lazylead.yml up
|
40
|
+
Creating lazylead ... done
|
41
|
+
Attaching to lazylead
|
42
|
+
lazylead | [2020-06-06T10:35:13] DEBUG Memory footprint at start is 52MB
|
43
|
+
lazylead | [2020-06-06T10:35:13] DEBUG Database: '/lazylead/db/ll.db', sql migration dir: '/lazylead/upgrades/sqlite'
|
44
|
+
lazylead | [2020-06-06T10:35:13] DEBUG Migration applied to /lazylead/db/ll.db from /lazylead/upgrades/sqlite
|
45
|
+
lazylead | [2020-06-06T10:35:13] DEBUG Database connection established
|
46
|
+
lazylead | [2020-06-06T10:35:13] WARN SMTP connection enabled in test mode.
|
47
|
+
lazylead | [2020-06-06T10:35:13] WARN ll-001: No tasks found.
|
48
|
+
lazylead | [2020-06-06T10:35:13] DEBUG Memory footprint at the end is 66MB
|
49
|
+
lazylead exited with code 0
|
50
|
+
ll >
|
51
|
+
```
|
52
|
+
|
53
|
+
3. Define your team and tasks in database.
|
54
|
+
The tables structure defined [here](../upgrades/sqlite/001-install-main-lazylead-tables.sql).
|
55
|
+
Modify you [sqlite](https://sqlite.com/index.html) file(`ll.db`) using [DB Browser](https://sqlitebrowser.org/) or any similar tool.
|
56
|
+
```sql
|
57
|
+
insert into teams (id, name, properties)
|
58
|
+
values (1, 'Dream team with lazylead', '{}');
|
59
|
+
insert into systems(id, properties)
|
60
|
+
values (1,'{"type":"Lazylead::Jira", "username":"${jira_user}", "password":"${jira_password}", "site":"${jira_url}", "context_path":""}');
|
61
|
+
insert into tasks (name, cron, enabled, id, system, team_id, action, properties)
|
62
|
+
values ('Propagate customfield_1 (External ID) to sub-tasks',
|
63
|
+
'0 8 * * 1-5',
|
64
|
+
'true',
|
65
|
+
1, 1, 1,
|
66
|
+
'Lazylead::Task::PropagateDown',
|
67
|
+
'{"jql":"filter=222", "fields":"customfield_1"}');
|
68
|
+
|
69
|
+
```
|
70
|
+
Yes, for task scheduling we are using [cron](https://crontab.guru).
|
71
|
+
|
72
|
+
4. Once you changed `./ll.db`, please restart the container using `docker-compose -f .github/tasks.yml restart`
|
73
|
+
```bash
|
74
|
+
ll > docker-compose -f .github/tasks.yml restart
|
75
|
+
Restarting lazylead ... done
|
76
|
+
```
|
77
|
+
|
78
|
+
5. Once task completed, please check your sub-tasks, they should have `customfield_1` and comment like
|
79
|
+
```text
|
80
|
+
The following fields were propagated from <parent-ticket-key>:
|
81
|
+
||Field||Value||
|
82
|
+
|customfield_1|<parent-field-value>|
|
83
|
+
Posted by [lazylead v0.0.0|https://bit.ly/2NjdndS]]
|
84
|
+
```
|
85
|
+
|
86
|
+
#### Where is the code?
|
87
|
+
| Logic | Tests |
|
88
|
+
| :-----: | :------: |
|
89
|
+
| [propagate_down.rb](../lib/lazylead/task/propagate_down.rb)| [propagate_down_test.rb](../test/lazylead/task/propagate_down_test.rb) |
|
data/.rubocop.yml
CHANGED
data/.rultor.yml
CHANGED
@@ -16,13 +16,13 @@ release:
|
|
16
16
|
sed -i "s/0\.0\.0/${tag}/g" lib/lazylead/version.rb
|
17
17
|
sed -i "s/0\.0\.0/${tag}/g" lazylead.gemspec
|
18
18
|
bundle install --no-color
|
19
|
-
bundle exec rake test rubocop sqlint xcop
|
19
|
+
bundle exec rake --trace test rubocop sqlint xcop
|
20
20
|
git add lib/lazylead/version.rb lazylead.gemspec
|
21
21
|
git commit -m "version set to ${tag}"
|
22
22
|
gem build lazylead.gemspec
|
23
23
|
chmod 0600 ../rubygems.yml
|
24
24
|
gem push *.gem --config-file ../rubygems.yml
|
25
|
-
curl -s -X POST --url "https://circleci.com/api/v2/project/gh/dgroup/lazylead/envvar" -H @../circleci.header -H "accept: application/json" -H "content-type: application/json" -d "{ \"name\": \"DOCKER_RELEASE_TAGS\", \"value\": \"
|
25
|
+
curl -s -X POST --url "https://circleci.com/api/v2/project/gh/dgroup/lazylead/envvar" -H @../circleci.header -H "accept: application/json" -H "content-type: application/json" -d "{ \"name\": \"DOCKER_RELEASE_TAGS\", \"value\": \"${tag}\" }" -o /dev/null
|
26
26
|
curl -s -X POST --url https://circleci.com/api/v2/project/gh/dgroup/lazylead/pipeline -H @../circleci.header -H 'accept: application/json' -H 'content-type: application/json' -H 'x-attribution-login: dgroup' -o /dev/null
|
27
27
|
merge:
|
28
28
|
script: |-
|
data/.simplecov
CHANGED
@@ -1,11 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
# @todo #/DEV Increase code coverage from 75% to 80%+.
|
4
|
-
# Right now it was decreased to 75% due to long manual setup of
|
5
|
-
# dev. instances of Atlassian Jira and Confluence.
|
6
|
-
# It was configured locally and there is no automation for now how
|
7
|
-
# it can be included quickly into CI process. This need to be done later.
|
8
|
-
|
9
3
|
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
|
10
4
|
[SimpleCov::Formatter::HTMLFormatter]
|
11
5
|
)
|
data/bin/lazylead
CHANGED
@@ -34,6 +34,7 @@ require "logging"
|
|
34
34
|
require "backtrace"
|
35
35
|
require "memory_profiler"
|
36
36
|
require_relative "../lib/lazylead/log"
|
37
|
+
require_relative "../lib/lazylead/home"
|
37
38
|
require_relative "../lib/lazylead/schedule"
|
38
39
|
require_relative "../lib/lazylead/allocated"
|
39
40
|
require_relative "../lib/lazylead/cli/app"
|
@@ -51,8 +52,8 @@ Available options:"
|
|
51
52
|
o.bool "--memory-dump", "Dump memory snapshot afterwards, to the console",
|
52
53
|
default: false
|
53
54
|
o.string "--home",
|
54
|
-
"Home directory (default
|
55
|
-
default:
|
55
|
+
"Home directory (default #{Lazylead::Home.new.dir})",
|
56
|
+
default: Lazylead::Home.new.dir
|
56
57
|
o.string "--sqlite",
|
57
58
|
"SQLite database file name",
|
58
59
|
default: "lazylead.db"
|
@@ -70,6 +71,7 @@ Available options:"
|
|
70
71
|
exit
|
71
72
|
end
|
72
73
|
end
|
74
|
+
log.debug("Version: #{Lazylead::VERSION}")
|
73
75
|
log.debug("Memory footprint at start is #{Lazylead::Allocated.new}")
|
74
76
|
cmd = lambda do
|
75
77
|
Lazylead::CLI::App.new(
|
data/lazylead.gemspec
CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
|
|
32
32
|
s.rubygems_version = "2.2"
|
33
33
|
s.required_ruby_version = ">=2.6.5"
|
34
34
|
s.name = "lazylead"
|
35
|
-
s.version = "0.
|
35
|
+
s.version = "0.3.0"
|
36
36
|
s.license = "MIT"
|
37
37
|
s.summary = "Eliminate the annoying work within bug-trackers."
|
38
38
|
s.description = "Ticketing systems (Github, Jira, etc.) are strongly
|
@@ -45,7 +45,7 @@ tasks instead of solving technical problems."
|
|
45
45
|
s.authors = ["Yurii Dubinka"]
|
46
46
|
s.email = "yurii.dubinka@gmail.com"
|
47
47
|
s.homepage = "http://github.com/dgroup/lazylead"
|
48
|
-
s.post_install_message = "Thanks for installing Lazylead v0.
|
48
|
+
s.post_install_message = "Thanks for installing Lazylead v0.3.0!
|
49
49
|
Read our blog posts: https://lazylead.org
|
50
50
|
Stay in touch with the community in Telegram: https://t.me/lazylead
|
51
51
|
Follow us on Twitter: https://twitter.com/lazylead
|
@@ -57,12 +57,8 @@ tasks instead of solving technical problems."
|
|
57
57
|
s.extra_rdoc_files = %w[readme.md license.txt]
|
58
58
|
s.add_runtime_dependency "activerecord", "6.0.3"
|
59
59
|
s.add_runtime_dependency "backtrace", "0.3"
|
60
|
-
s.add_runtime_dependency "concurrent-ruby", "1.1.5"
|
61
|
-
s.add_runtime_dependency "diffy", "3.3.0"
|
62
60
|
s.add_runtime_dependency "faraday", "1.0.1"
|
63
|
-
s.add_runtime_dependency "futex", "0.8.5"
|
64
61
|
s.add_runtime_dependency "get_process_mem", "0.2.5"
|
65
|
-
s.add_runtime_dependency "haml", "5.0.4"
|
66
62
|
s.add_runtime_dependency "jira-ruby", "1.7.1"
|
67
63
|
s.add_runtime_dependency "json", "2.2.0"
|
68
64
|
s.add_runtime_dependency "logging", "2.2.2"
|
@@ -72,21 +68,13 @@ tasks instead of solving technical problems."
|
|
72
68
|
s.add_runtime_dependency "rainbow", "3.0.0"
|
73
69
|
s.add_runtime_dependency "require_all", "3.0.0"
|
74
70
|
s.add_runtime_dependency "rufus-scheduler", "3.6.0"
|
75
|
-
s.add_runtime_dependency "semantic", "1.6.1"
|
76
|
-
s.add_runtime_dependency "sinatra", "2.0.5"
|
77
71
|
s.add_runtime_dependency "slop", "4.4"
|
78
72
|
s.add_runtime_dependency "sqlite3", "1.4.2"
|
79
|
-
s.add_runtime_dependency "sys-proctable", "1.2.1"
|
80
|
-
s.add_runtime_dependency "threads", "0.3"
|
81
73
|
s.add_runtime_dependency "tilt", "2.0.10"
|
82
|
-
s.add_runtime_dependency "total", "0.3"
|
83
|
-
s.add_runtime_dependency "typhoeus", "1.3.1"
|
84
74
|
s.add_runtime_dependency "tzinfo", "1.1"
|
85
75
|
s.add_runtime_dependency "tzinfo-data", "1.2019.3"
|
86
|
-
s.add_runtime_dependency "usagewatch_ext", "0.2.1"
|
87
76
|
s.add_runtime_dependency "vcs4sql", "0.1.0"
|
88
77
|
s.add_runtime_dependency "viewpoint", "1.1.0"
|
89
|
-
s.add_runtime_dependency "zache", "0.12"
|
90
78
|
s.add_development_dependency "codecov", "0.1.14"
|
91
79
|
s.add_development_dependency "guard", "2.15.0"
|
92
80
|
s.add_development_dependency "guard-minitest", "2.4.6"
|
data/lib/lazylead/cc.rb
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# The MIT License
|
4
|
+
#
|
5
|
+
# Copyright (c) 2019-2020 Yurii Dubinka
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"),
|
9
|
+
# to deal in the Software without restriction, including without limitation
|
10
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
11
|
+
# and/or sell copies of the Software, and to permit persons to whom
|
12
|
+
# the Software is furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included
|
15
|
+
# in all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
22
|
+
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
23
|
+
# OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
require "forwardable"
|
25
|
+
|
26
|
+
module Lazylead
|
27
|
+
# Entry point for email CC detection.
|
28
|
+
# The email may need CC email addresses, thus, there are various strategies
|
29
|
+
# how it can be done.
|
30
|
+
class CC
|
31
|
+
# Build an CC in order to detect email addresses by different conditions.
|
32
|
+
#
|
33
|
+
# Supported conditions(types):
|
34
|
+
# - PlainCC
|
35
|
+
# - PredefinedCC
|
36
|
+
# - ComponentCC
|
37
|
+
# - Empty
|
38
|
+
#
|
39
|
+
def detect(emails, sys)
|
40
|
+
return PlainCC.new(emails) if plain?(emails)
|
41
|
+
return EmptyCC unless emails.key? "type"
|
42
|
+
return EmptyCC if emails["type"].blank? || emails["type"].nil?
|
43
|
+
type = emails["type"].constantize
|
44
|
+
return ComponentCC.new(emails["project"], sys) if type.is_a? ComponentCC
|
45
|
+
type.new(emails["opts"])
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# Detect that raw CC is a string which may has plain email addresses
|
51
|
+
def plain?(text)
|
52
|
+
(text.is_a? String) &&
|
53
|
+
(text.to_s.include?(",") || text.to_s.include?("@"))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Array of CC addresses from text for email notification.
|
58
|
+
#
|
59
|
+
# PlainCC.new("a@f.com, , -,b@f.com").cc # ==> ["a@f.com", "b@f.com"]
|
60
|
+
#
|
61
|
+
# Author:: Yurii Dubinka (yurii.dubinka@gmail.com)
|
62
|
+
# Copyright:: Copyright (c) 2019-2020 Yurii Dubinka
|
63
|
+
# License:: MIT
|
64
|
+
class PlainCC
|
65
|
+
include Enumerable
|
66
|
+
extend Forwardable
|
67
|
+
def_delegators :@cc, :each
|
68
|
+
|
69
|
+
# The regexp expression for email notification is very simple, here is the
|
70
|
+
# reason why https://bit.ly/38iLKeo
|
71
|
+
def initialize(text, regxp = /[^\s]@[^\s]/)
|
72
|
+
@text = text
|
73
|
+
@regxp = regxp
|
74
|
+
end
|
75
|
+
|
76
|
+
def cc
|
77
|
+
@cc ||= begin
|
78
|
+
if @text.include? ","
|
79
|
+
@text.split(",").map(&:strip).select { |e| e[@regxp] }
|
80
|
+
elsif @text[@regxp]
|
81
|
+
[@text.strip]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def each(&block)
|
87
|
+
cc.each(&block)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Empty CC email addresses.
|
92
|
+
class EmptyCC
|
93
|
+
def cc
|
94
|
+
[]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Predefined CC addresses for email notification.
|
99
|
+
# You may define a hash where
|
100
|
+
# - key is Jira ticket component
|
101
|
+
# - value is CC email address(es)
|
102
|
+
#
|
103
|
+
# Author:: Yurii Dubinka (yurii.dubinka@gmail.com)
|
104
|
+
# Copyright:: Copyright (c) 2019-2020 Yurii Dubinka
|
105
|
+
# License:: MIT
|
106
|
+
class PredefinedCC
|
107
|
+
def initialize(orig)
|
108
|
+
@orig = orig
|
109
|
+
end
|
110
|
+
|
111
|
+
def [](key)
|
112
|
+
to_h[key]
|
113
|
+
end
|
114
|
+
|
115
|
+
def cc(*names)
|
116
|
+
return to_h.values.flatten.uniq.compact if names.count.zero?
|
117
|
+
return self[names.first] if names.count == 1
|
118
|
+
to_h.values_at(names.first, *names.drop(1)).flatten.uniq.compact
|
119
|
+
end
|
120
|
+
|
121
|
+
def to_h
|
122
|
+
@to_h ||= begin
|
123
|
+
if @orig.is_a? Hash
|
124
|
+
@orig.each_with_object({}) do |i, o|
|
125
|
+
o[i.first] = Lazylead::PlainCC.new(i.last).cc
|
126
|
+
end
|
127
|
+
else
|
128
|
+
{}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# CC addresses based on Jira component owners for email notification.
|
135
|
+
# Allows to detect the CC for particular ticket based on its component.
|
136
|
+
#
|
137
|
+
# Author:: Yurii Dubinka (yurii.dubinka@gmail.com)
|
138
|
+
# Copyright:: Copyright (c) 2019-2020 Yurii Dubinka
|
139
|
+
# License:: MIT
|
140
|
+
class ComponentCC < Lazylead::PredefinedCC
|
141
|
+
def initialize(prj, jira)
|
142
|
+
@prj = prj
|
143
|
+
@jira = jira
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_h
|
147
|
+
@to_h ||= begin
|
148
|
+
components.each_with_object({}) do |c, h|
|
149
|
+
email = lead(c.attrs["id"])
|
150
|
+
next if email.nil? || email.blank?
|
151
|
+
h[c.attrs["name"]] = email
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def lead(component_id)
|
159
|
+
@jira.raw do |j|
|
160
|
+
lead = j.Component
|
161
|
+
.find(component_id, expand: "", fields: "")
|
162
|
+
.attrs["lead"]
|
163
|
+
next if lead.nil? || lead.empty?
|
164
|
+
j.User.find(lead["key"]).attrs["emailAddress"]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def components
|
169
|
+
@jira.raw do |j|
|
170
|
+
j.Project.find(@prj, expand: "components", fields: "").components
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|