1
+ const retry = require ( 'async-retry' ) ;
2
+ const { getProjectByName, getLastBuild, getBuild } = require ( '../helpers/percy' ) ;
3
+ const { HOOK , STATUS , URLS } = require ( '../helpers/constants' ) ;
4
+ const { addExtension } = require ( '../helpers/teams' ) ;
5
+ const { addTextBlock } = require ( '../helpers/slack' ) ;
6
+ const { addTextSection } = require ( '../helpers/chat' ) ;
7
+
8
+ async function run ( { extension, payload, target } ) {
9
+ extension . inputs = Object . assign ( { } , default_inputs , extension . inputs ) ;
10
+ await initialize ( extension . inputs ) ;
11
+ if ( target . name === 'teams' ) {
12
+ extension . inputs = Object . assign ( { } , default_inputs_teams , extension . inputs ) ;
13
+ attachForTeams ( { payload, extension } ) ;
14
+ } else if ( target . name === 'slack' ) {
15
+ extension . inputs = Object . assign ( { } , default_inputs_slack , extension . inputs ) ;
16
+ attachForSlack ( { payload, extension } ) ;
17
+ } else if ( target . name === 'chat' ) {
18
+ extension . inputs = Object . assign ( { } , default_inputs_chat , extension . inputs ) ;
19
+ attachForChat ( { payload, extension } ) ;
20
+ }
21
+ }
22
+
23
+ /**
24
+ * @param {import('../index').PercyAnalysisInputs } inputs
25
+ */
26
+ async function initialize ( inputs ) {
27
+ if ( ! inputs . build_id ) {
28
+ await setBuildByLastRun ( inputs ) ;
29
+ } else {
30
+ await setBuild ( inputs ) ;
31
+ }
32
+ if ( ! inputs . title_link && inputs . title_link_to_build ) {
33
+ inputs . title_link = `https://percy.io/${ inputs . organization_uid } /${ inputs . project_name } /builds/${ inputs . build_id } ` ;
34
+ }
35
+ }
36
+
37
+ /**
38
+ * @param {import('../index').PercyAnalysisInputs } inputs
39
+ */
40
+ async function setBuildByLastRun ( inputs ) {
41
+ if ( ! inputs . project_id ) {
42
+ await setProjectId ( inputs )
43
+ }
44
+ const response = await getLastFinishedBuild ( inputs ) ;
45
+ inputs . build_id = response . data [ 0 ] . id ;
46
+ inputs . _build = response . data [ 0 ] ;
47
+ if ( ! inputs . _project ) {
48
+ inputs . _project = response . included . find ( _item => _item . type === 'projects' ) ;
49
+ }
50
+ if ( ! inputs . project_name ) {
51
+ inputs . project_name = inputs . _project . attributes . name ;
52
+ }
53
+ if ( ! inputs . organization_uid ) {
54
+ inputs . organization_uid = getOrganizationUID ( inputs . _project . attributes [ 'full-slug' ] ) ;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * @param {import('../index').PercyAnalysisInputs } inputs
60
+ */
61
+ function getLastFinishedBuild ( inputs ) {
62
+ return retry ( async ( ) => {
63
+ const response = await getLastBuild ( inputs ) ;
64
+ if ( response . data [ 0 ] . attributes . state !== "finished" ) {
65
+ throw `build is still '${ response . data [ 0 ] . attributes . state } '` ;
66
+ }
67
+ return response ;
68
+ } , { retries : 10 , minTimeout : 5000 } ) ;
69
+ }
70
+
71
+ /**
72
+ * @param {import('../index').PercyAnalysisInputs } inputs
73
+ */
74
+ async function setProjectId ( inputs ) {
75
+ if ( ! inputs . project_name ) {
76
+ throw "mandatory inputs 'build_id' or 'project_id' or 'project_name' are not provided"
77
+ }
78
+ const response = await getProjectByName ( inputs ) ;
79
+ inputs . project_id = response . data . id ;
80
+ inputs . _project = response . data ;
81
+ }
82
+
83
+ /**
84
+ * @param {import('../index').PercyAnalysisInputs } inputs
85
+ */
86
+ async function setBuild ( inputs ) {
87
+ const response = await getBuild ( inputs ) ;
88
+ inputs . _build = response . data ;
89
+ inputs . _project = response . included . find ( _item => _item . type === 'projects' ) ;
90
+ if ( ! inputs . project_id ) {
91
+ inputs . project_id = inputs . _project . id ;
92
+ }
93
+ if ( ! inputs . project_name ) {
94
+ inputs . project_name = inputs . _project . attributes . name ;
95
+ }
96
+ if ( ! inputs . organization_uid ) {
97
+ inputs . organization_uid = getOrganizationUID ( inputs . _project . attributes [ 'full-slug' ] ) ;
98
+ }
99
+ }
100
+
101
+ function getOrganizationUID ( slug ) {
102
+ return slug . split ( '/' ) [ 0 ] ;
103
+ }
104
+
105
+ function attachForTeams ( { payload, extension } ) {
106
+ const text = getResults ( extension . inputs . _build ) . join ( ' | ' ) ;
107
+ addExtension ( { payload, extension, text } ) ;
108
+ }
109
+
110
+ function attachForSlack ( { payload, extension } ) {
111
+ const text = getResults ( extension . inputs . _build ) . join ( ' | ' ) ;
112
+ addTextBlock ( { payload, extension, text } ) ;
113
+ }
114
+
115
+ function attachForChat ( { payload, extension } ) {
116
+ const text = getResults ( extension . inputs . _build ) . join ( ' | ' ) ;
117
+ addTextSection ( { payload, extension, text } ) ;
118
+ }
119
+
120
+ function getResults ( build ) {
121
+ const results = [ ] ;
122
+ const total = build . attributes [ 'total-snapshots' ] ;
123
+ const un_reviewed = build . attributes [ 'total-snapshots-unreviewed' ] ;
124
+ const approved = total - un_reviewed ;
125
+ results . push ( `✅ AP - ${ approved } ` ) ;
126
+ if ( un_reviewed > 0 ) {
127
+ results . push ( `🔎 UR - ${ un_reviewed } ` )
128
+ }
129
+ return results ;
130
+ }
131
+
132
+ const default_options = {
133
+ hook : HOOK . END ,
134
+ condition : STATUS . PASS_OR_FAIL
135
+ }
136
+
137
+ const default_inputs = {
138
+ title : 'Percy Analysis' ,
139
+ url : URLS . PERCY ,
140
+ title_link_to_build : true ,
141
+ build_id : '' ,
142
+ project_id : '' ,
143
+ project_name : '' ,
144
+ organization_uid : ''
145
+ }
146
+
147
+ const default_inputs_teams = {
148
+ separator : true
149
+ }
150
+
151
+ const default_inputs_slack = {
152
+ separator : false
153
+ }
154
+
155
+ const default_inputs_chat = {
156
+ separator : true
157
+ }
158
+
159
+ module . exports = {
160
+ run,
161
+ default_options
162
+ }
0 commit comments