lazylead 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|