@duckduckgo/autoconsent 10.2.0 → 10.3.1

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.
@@ -0,0 +1,15 @@
1
+ name: 'Setup Release Scripts'
2
+ description: 'Install release script dependencies using correct node version'
3
+ runs:
4
+ using: "composite"
5
+ steps:
6
+ - uses: actions/setup-node@v3
7
+ with:
8
+ node-version: 18.x
9
+ cache: 'npm'
10
+ cache-dependency-path: 'autoconsent/package-lock.json'
11
+ - run: |
12
+ cd autoconsent
13
+ npm ci
14
+ cd ..
15
+ shell: bash
@@ -1,5 +1,6 @@
1
1
  name: 'asana sync'
2
2
  on:
3
+ pull_request_review:
3
4
  pull_request_target:
4
5
  types:
5
6
  - opened
@@ -12,15 +13,12 @@ on:
12
13
  jobs:
13
14
  sync:
14
15
  runs-on: ubuntu-latest
15
- environment: development
16
- concurrency: 'asana-${{ github.repository }}'
17
16
  steps:
18
17
  - uses: actions/checkout@v3
19
- - uses: sammacbeth/action-asana-sync@v4
18
+ - uses: sammacbeth/action-asana-sync@v6
20
19
  with:
21
20
  ASANA_ACCESS_TOKEN: ${{ secrets.ASANA_ACCESS_TOKEN }}
22
21
  ASANA_WORKSPACE_ID: ${{ secrets.ASANA_WORKSPACE_ID }}
23
22
  ASANA_PROJECT_ID: '1203409672862476'
24
23
  move_to_section_id: '1203409672862480'
25
24
  USER_MAP: ${{ vars.USER_MAP }}
26
- NO_AUTOCLOSE_PROJECTS: '1203409672862476'
@@ -0,0 +1,303 @@
1
+ name: Propagate Autoconsent To DDG Apps
2
+
3
+ on:
4
+ release:
5
+ types: [ published ]
6
+
7
+ env:
8
+ VERSION: ${{ github.event.release.tag_name }}
9
+ RELEASE_URL: ${{ github.event.release.html_url }}
10
+ RELEASE_NOTES: ${{ github.event.release.body }}
11
+ PR_TITLE: Update autoconsent to ${{ github.event.release.tag_name }}
12
+
13
+ jobs:
14
+
15
+ # ------------------------------------------------------------------------------
16
+ # Create initial Asana subtasks
17
+ # ------------------------------------------------------------------------------
18
+ create_asana_tasks:
19
+ runs-on: ubuntu-latest
20
+ outputs:
21
+ asana-output: ${{ steps.create-asana-tasks.outputs.ASANA_OUTPUT }}
22
+ steps:
23
+ # --- Setup ---
24
+ - uses: actions/checkout@v3
25
+ with:
26
+ path: autoconsent/
27
+ - uses: ./autoconsent/.github/actions/setup-release-scripts
28
+ # --- Effect ---
29
+ - name: Create Asana Tasks
30
+ id: create-asana-tasks
31
+ env:
32
+ ASANA_ACCESS_TOKEN: ${{ secrets.ASANA_ACCESS_TOKEN }}
33
+ run: |
34
+ JSON_STRING="$(node ./autoconsent/ci/asana-create-tasks.js)"
35
+ echo "ASANA_OUTPUT=$JSON_STRING" >> $GITHUB_OUTPUT
36
+
37
+ # ------------------------------------------------------------------------------
38
+ # Create PR with updated autoconsent on Android
39
+ # ------------------------------------------------------------------------------
40
+
41
+ update_android:
42
+ runs-on: ubuntu-latest
43
+ outputs:
44
+ pull-request-url: ${{ steps.create-pr.outputs.pull-request-url }}
45
+ needs: create_asana_tasks
46
+ steps:
47
+ # --- Setup ---
48
+ - uses: actions/checkout@v3
49
+ with:
50
+ path: autoconsent/
51
+ - uses: ./autoconsent/.github/actions/setup-release-scripts
52
+ # --- Action ---
53
+ - name: Checkout Android
54
+ uses: actions/checkout@v3
55
+ with:
56
+ repository: duckduckgo/android
57
+ path: android/
58
+ token: ${{ secrets.DAX_WEB_AUTOFILL_AUTOMATION }}
59
+ - uses: actions/setup-node@v3
60
+ with:
61
+ node-version: current
62
+ - name: Update Android autoconsent reference
63
+ run: |
64
+ cd android
65
+ npm install @duckduckgo/autoconsent@${{ env.VERSION }}
66
+ npm run rebuild-autoconsent
67
+ cd ..
68
+ - name: Create Android PR Body
69
+ env:
70
+ ASANA_OUTPUT: ${{ needs.create_asana_tasks.outputs.asana-output }}
71
+ run: |
72
+ TEMPLATE="$(node ./autoconsent/ci/create-pr-template.js android)"
73
+ # Creates a randomised delimiter. See https://app.asana.com/0/1199892415909552/1203243297643584/f
74
+ DELIMITER=$(echo $RANDOM | md5sum | head -c 20;)
75
+ echo "PR_BODY_ANDROID<<$DELIMITER" >> $GITHUB_ENV
76
+ echo "$TEMPLATE" >> $GITHUB_ENV
77
+ echo "$DELIMITER" >> $GITHUB_ENV
78
+ # --- Effect ---
79
+ - name: Create PR for Android
80
+ uses: peter-evans/create-pull-request@88bf0de51c7487d91e1abbb4899332e602c58bbf
81
+ id: create-pr
82
+ with:
83
+ path: android/
84
+ add-paths: |
85
+ package.json
86
+ package-lock.json
87
+ autoconsent/
88
+ commit-message: Update autoconsent to ${{ env.VERSION }}
89
+ branch: update-autoconsent-${{ env.VERSION }}
90
+ title: ${{ env.PR_TITLE }}
91
+ body: "${{ env.PR_BODY_ANDROID }}"
92
+ token: ${{ secrets.DAX_WEB_AUTOFILL_AUTOMATION }}
93
+
94
+
95
+ # ------------------------------------------------------------------------------
96
+ # Create PR with updated autoconsent on iOS
97
+ # ------------------------------------------------------------------------------
98
+
99
+ update_ios:
100
+ runs-on: ubuntu-latest
101
+ outputs:
102
+ pull-request-url: ${{ steps.create-pr.outputs.pull-request-url }}
103
+ needs: create_asana_tasks
104
+ steps:
105
+ # --- Setup ---
106
+ - uses: actions/checkout@v3
107
+ with:
108
+ path: autoconsent/
109
+ - uses: ./autoconsent/.github/actions/setup-release-scripts
110
+ # --- Action ---
111
+ - name: Checkout iOS
112
+ uses: actions/checkout@v3
113
+ with:
114
+ repository: duckduckgo/iOS
115
+ path: ios/
116
+ token: ${{ secrets.DAX_WEB_AUTOFILL_AUTOMATION }}
117
+ - uses: actions/setup-node@v3
118
+ with:
119
+ node-version: current
120
+ - name: Update iOS autoconsent reference
121
+ run: |
122
+ cd ios
123
+ npm install @duckduckgo/autoconsent@${{ env.VERSION }}
124
+ npm run rebuild-autoconsent
125
+ cd ..
126
+ - name: Create iOS PR Body
127
+ env:
128
+ ASANA_OUTPUT: ${{ needs.create_asana_tasks.outputs.asana-output }}
129
+ run: |
130
+ TEMPLATE="$(node ./autoconsent/ci/create-pr-template.js ios)"
131
+ # Creates a randomised delimiter. See https://app.asana.com/0/1199892415909552/1203243297643584/f
132
+ DELIMITER=$(echo $RANDOM | md5sum | head -c 20;)
133
+ echo "PR_BODY_IOS<<$DELIMITER" >> $GITHUB_ENV
134
+ echo "$TEMPLATE" >> $GITHUB_ENV
135
+ echo "$DELIMITER" >> $GITHUB_ENV
136
+ # --- Effect ---
137
+ - name: Create PR for iOS
138
+ uses: peter-evans/create-pull-request@88bf0de51c7487d91e1abbb4899332e602c58bbf
139
+ id: create-pr
140
+ with:
141
+ path: ios/
142
+ add-paths: |
143
+ package.json
144
+ package-lock.json
145
+ DuckDuckGo/Autoconsent/
146
+ commit-message: Update autoconsent to ${{ env.VERSION }}
147
+ branch: update-autoconsent-${{ env.VERSION }}
148
+ title: ${{ env.PR_TITLE }}
149
+ body: "${{ env.PR_BODY_IOS }}"
150
+ token: ${{ secrets.DAX_WEB_AUTOFILL_AUTOMATION }}
151
+
152
+ # ------------------------------------------------------------------------------
153
+ # Create PR with updated autoconsent on macOS
154
+ # ------------------------------------------------------------------------------
155
+
156
+ update_macos:
157
+ runs-on: ubuntu-latest
158
+ outputs:
159
+ pull-request-url: ${{ steps.create-pr.outputs.pull-request-url }}
160
+ needs: create_asana_tasks
161
+ steps:
162
+ # --- Setup ---
163
+ - uses: actions/checkout@v3
164
+ with:
165
+ path: autoconsent/
166
+ - uses: ./autoconsent/.github/actions/setup-release-scripts
167
+ # --- Action ---
168
+ - name: Checkout macOS
169
+ uses: actions/checkout@v3
170
+ with:
171
+ repository: duckduckgo/macos-browser
172
+ path: macos/
173
+ token: ${{ secrets.DAX_WEB_AUTOFILL_AUTOMATION }}
174
+ - uses: actions/setup-node@v3
175
+ with:
176
+ node-version: current
177
+ - name: Update macOS autoconsent reference
178
+ run: |
179
+ cd macos
180
+ npm install @duckduckgo/autoconsent@${{ env.VERSION }}
181
+ npm run rebuild-autoconsent
182
+ cd ..
183
+ - name: Create macOS PR Body
184
+ env:
185
+ ASANA_OUTPUT: ${{ needs.create_asana_tasks.outputs.asana-output }}
186
+ run: |
187
+ TEMPLATE="$(node ./autoconsent/ci/create-pr-template.js macos)"
188
+ # Creates a randomised delimiter. See https://app.asana.com/0/1199892415909552/1203243297643584/f
189
+ DELIMITER=$(echo $RANDOM | md5sum | head -c 20;)
190
+ echo "PR_BODY_MACOS<<$DELIMITER" >> $GITHUB_ENV
191
+ echo "$TEMPLATE" >> $GITHUB_ENV
192
+ echo "$DELIMITER" >> $GITHUB_ENV
193
+ # --- Effect ---
194
+ - name: Create PR for macOS
195
+ uses: peter-evans/create-pull-request@88bf0de51c7487d91e1abbb4899332e602c58bbf
196
+ id: create-pr
197
+ with:
198
+ path: macos/
199
+ add-paths: |
200
+ package.json
201
+ package-lock.json
202
+ DuckDuckGo/Autoconsent/
203
+ commit-message: Update autoconsent to ${{ env.VERSION }}
204
+ branch: update-autoconsent-${{ env.VERSION }}
205
+ title: ${{ env.PR_TITLE }}
206
+ body: "${{ env.PR_BODY_MACOS }}"
207
+ token: ${{ secrets.DAX_WEB_AUTOFILL_AUTOMATION }}
208
+
209
+ # ------------------------------------------------------------------------------
210
+ # Create PR with updated autofill on Windows
211
+ # ------------------------------------------------------------------------------
212
+
213
+ update_windows:
214
+ runs-on: ubuntu-latest
215
+ outputs:
216
+ pull-request-url: ${{ steps.create-pr.outputs.pull-request-url }}
217
+ needs: create_asana_tasks
218
+ steps:
219
+ # --- Setup ---
220
+ - uses: actions/checkout@v3
221
+ with:
222
+ path: autoconsent/
223
+ - uses: ./autoconsent/.github/actions/setup-release-scripts
224
+ # --- Action ---
225
+ - name: Checkout Windows
226
+ uses: actions/checkout@v3
227
+ with:
228
+ repository: duckduckgo/windows-browser
229
+ path: windows/
230
+ token: ${{ secrets.DAX_WEB_AUTOFILL_AUTOMATION }}
231
+ - uses: actions/setup-node@v3
232
+ with:
233
+ node-version: current
234
+ - name: Update Windows autoconsent reference
235
+ run: |
236
+ cd windows/WindowsBrowser/Application/Autoconsent/External
237
+ npm install @duckduckgo/autoconsent@${{ env.VERSION }}
238
+ npm run rebuild-autoconsent
239
+ cd ../../../../../
240
+ - name: Create Windows PR Body
241
+ env:
242
+ ASANA_OUTPUT: ${{ needs.create_asana_tasks.outputs.asana-output }}
243
+ run: |
244
+ TEMPLATE="$(node ./autoconsent/ci/create-pr-template.js windows)"
245
+ # Creates a randomised delimiter. See https://app.asana.com/0/1199892415909552/1203243297643584/f
246
+ DELIMITER=$(echo $RANDOM | md5sum | head -c 20;)
247
+ echo "PR_BODY_WINDOWS<<$DELIMITER" >> $GITHUB_ENV
248
+ echo "$TEMPLATE" >> $GITHUB_ENV
249
+ echo "$DELIMITER" >> $GITHUB_ENV
250
+ # --- Effect ---
251
+ - name: Create PR for Windows
252
+ uses: peter-evans/create-pull-request@88bf0de51c7487d91e1abbb4899332e602c58bbf
253
+ id: create-pr
254
+ with:
255
+ path: windows/
256
+ add-paths: |
257
+ WindowsBrowser/Application/Autoconsent/
258
+ commit-message: Update autoconsent to ${{ env.VERSION }}
259
+ branch: update-autoconsent-${{ env.VERSION }}
260
+ title: ${{ env.PR_TITLE }}
261
+ body: "${{ env.PR_BODY_WINDOWS }}"
262
+ token: ${{ secrets.DAX_WEB_AUTOFILL_AUTOMATION }}
263
+
264
+ # ------------------------------------------------------------------------------
265
+ # Update Asana subtasks with PR URLs
266
+ # ------------------------------------------------------------------------------
267
+
268
+ update_asana_tasks:
269
+ runs-on: ubuntu-latest
270
+ # Always run this final step, even if any of the updates have failed
271
+ # unless the previous jobs were cancelled
272
+ if: ${{ always() && !contains(needs.*.result, 'cancelled') }}
273
+ needs: [create_asana_tasks, update_android, update_ios, update_macos, update_windows]
274
+ steps:
275
+ # --- Setup ---
276
+ - uses: actions/checkout@v3
277
+ with:
278
+ path: autoconsent/
279
+ - uses: ./autoconsent/.github/actions/setup-release-scripts
280
+ # --- Effect ---
281
+ - name: Update Asana tasks
282
+ env:
283
+ ASANA_ACCESS_TOKEN: ${{ secrets.ASANA_ACCESS_TOKEN }}
284
+ ASANA_OUTPUT: ${{ needs.create_asana_tasks.outputs.asana-output }}
285
+ IOS_PR_URL: ${{ needs.update_ios.outputs.pull-request-url }}
286
+ MACOS_PR_URL: ${{ needs.update_macos.outputs.pull-request-url }}
287
+ WINDOWS_PR_URL: ${{ needs.update_windows.outputs.pull-request-url }}
288
+ ANDROID_PR_URL: ${{ needs.update_android.outputs.pull-request-url }}
289
+ run: |
290
+ node ./autoconsent/ci/asana-update-tasks.js
291
+
292
+ - name: Ouput workflow summary
293
+ # Show failure message if any of the jobs report failed
294
+ if: ${{ contains(needs.*.result, 'failure') }}
295
+ run: |
296
+ echo "Release process completed but with failures reported." >> $GITHUB_STEP_SUMMARY
297
+ echo "Please review the job output to see which steps require manual intervention." >> $GITHUB_STEP_SUMMARY
298
+ - name: Ouput workflow summary
299
+ # Show success message as long as none of the jobs report failed
300
+ if: ${{ !contains(needs.*.result, 'failure') }}
301
+ run: |
302
+ echo "Release process completed successfully." >> $GITHUB_STEP_SUMMARY
303
+ echo "All PRs and Asana tasks created! :rocket:" >> $GITHUB_STEP_SUMMARY
package/CHANGELOG.md CHANGED
@@ -1,3 +1,36 @@
1
+ # v10.3.1 (Fri Mar 15 2024)
2
+
3
+ #### 🐛 Bug Fix
4
+
5
+ - Fix the trigger event for the CI automation [#394](https://github.com/duckduckgo/autoconsent/pull/394) ([@muodov](https://github.com/muodov))
6
+
7
+ #### Authors: 1
8
+
9
+ - Maxim Tsoy ([@muodov](https://github.com/muodov))
10
+
11
+ ---
12
+
13
+ # v10.3.0 (Fri Mar 15 2024)
14
+
15
+ #### 🚀 Enhancement
16
+
17
+ - DDG release automation [#389](https://github.com/duckduckgo/autoconsent/pull/389) ([@muodov](https://github.com/muodov))
18
+ - Bump the dev-dependencies group with 4 updates [#390](https://github.com/duckduckgo/autoconsent/pull/390) ([@dependabot[bot]](https://github.com/dependabot[bot]))
19
+
20
+ #### 🐛 Bug Fix
21
+
22
+ - Fix infinite reload for OneTrust sites [#393](https://github.com/duckduckgo/autoconsent/pull/393) ([@muodov](https://github.com/muodov))
23
+ - Script to crawl page text content in multiple languages. [#386](https://github.com/duckduckgo/autoconsent/pull/386) ([@sammacbeth](https://github.com/sammacbeth))
24
+ - Update Asana sync action [#388](https://github.com/duckduckgo/autoconsent/pull/388) ([@sammacbeth](https://github.com/sammacbeth))
25
+
26
+ #### Authors: 3
27
+
28
+ - [@dependabot[bot]](https://github.com/dependabot[bot])
29
+ - Maxim Tsoy ([@muodov](https://github.com/muodov))
30
+ - Sam Macbeth ([@sammacbeth](https://github.com/sammacbeth))
31
+
32
+ ---
33
+
1
34
  # v10.2.0 (Tue Mar 05 2024)
2
35
 
3
36
  #### 🚀 Enhancement
@@ -0,0 +1,174 @@
1
+ /* eslint-disable no-undef */
2
+ /* eslint-disable camelcase */
3
+ const timersPromises = require('node:timers/promises')
4
+ const Asana = require('asana')
5
+ const MarkdownIt = require('markdown-it')
6
+ const {getLink} = require('./release-utils.js')
7
+ const md = new MarkdownIt()
8
+
9
+ const ASANA_ACCESS_TOKEN = process.env.ASANA_ACCESS_TOKEN
10
+ const commit = process.env.GITHUB_SHA
11
+ const version = process.env.VERSION
12
+ const releaseUrl = process.env.RELEASE_URL || 'https://example.com/'
13
+ const releaseNotesRaw = process.env.RELEASE_NOTES || '<EMPTY RELEASE NOTES>'
14
+ const releaseNotes = md.render(releaseNotesRaw)
15
+
16
+ const templateTaskGid = '1206774921409831'
17
+ const autoconsentProjectGid = '1201844467387842'
18
+ const releaseSectionGid = '1202253736774466'
19
+ const projectExtractorRegex = /\[\[project_gids=(.+)]]\s/
20
+
21
+ /**
22
+ * @typedef {{taskGid: string, taskUrl: string, displayName: string}} platformData
23
+ *
24
+ * @typedef {{
25
+ * android: platformData,
26
+ * windows: platformData
27
+ * }} AsanaOutput
28
+ */
29
+
30
+ /** @type {AsanaOutput} */
31
+ const platforms = {
32
+ android: {
33
+ displayName: 'Android',
34
+ taskGid: '',
35
+ taskUrl: ''
36
+ },
37
+ windows: {
38
+ displayName: 'Windows',
39
+ taskGid: '',
40
+ taskUrl: ''
41
+ },
42
+ ios: {
43
+ displayName: 'iOS',
44
+ taskGid: '',
45
+ taskUrl: ''
46
+ },
47
+ macos: {
48
+ displayName: 'macOS',
49
+ taskGid: '',
50
+ taskUrl: ''
51
+ }
52
+ }
53
+
54
+ let asana
55
+
56
+ const setupAsana = () => {
57
+ asana = Asana.Client.create({
58
+ 'defaultHeaders': {
59
+ 'Asana-Enable': 'new_project_templates,new_user_task_lists,new_goal_memberships'
60
+ }
61
+ }).useAccessToken(ASANA_ACCESS_TOKEN)
62
+ }
63
+
64
+ const duplicateTemplateTask = (templateTaskGid) => {
65
+ const duplicateOption = {
66
+ include: ['notes', 'assignee', 'subtasks', 'projects'],
67
+ name: `Autoconsent release ${version}`,
68
+ opt_fields: 'html_notes'
69
+ }
70
+
71
+ return asana.tasks.duplicateTask(templateTaskGid, duplicateOption)
72
+ }
73
+
74
+ const waitForJobSuccess = async (job_gid, attempts = 1) => {
75
+ const interval = 500
76
+ const maxAttempts = 20
77
+
78
+ return new Promise(async (resolve, reject) => {
79
+ const { status } = await asana.jobs.getJob(job_gid)
80
+ if (status === 'succeeded') {
81
+ return resolve(status)
82
+ }
83
+ attempts += 1
84
+
85
+ if (attempts > maxAttempts) {
86
+ return reject(new Error(`The job ${job_gid} took too long to execute`))
87
+ }
88
+
89
+ await timersPromises.setTimeout(interval)
90
+ return waitForJobSuccess(job_gid, attempts)
91
+ })
92
+ }
93
+
94
+ const asanaCreateTasks = async () => {
95
+ setupAsana()
96
+
97
+ // Duplicating template task...
98
+ const { new_task, gid: duplicateTaskJobGid } = await duplicateTemplateTask(templateTaskGid)
99
+
100
+ const { html_notes: notes } = await asana.tasks.getTask(new_task.gid, { opt_fields: 'html_notes' })
101
+
102
+ const updatedNotes =
103
+ notes.replace('[[version]]', version)
104
+ .replace('[[commit]]', commit)
105
+ .replace('[[release_url]]', getLink(releaseUrl, 'Autoconsent Release'))
106
+ .replace('[[notes]]', releaseNotes)
107
+ .replace(/<\/?p>/ig, '\n')
108
+ // Asana supports only h1 and h2
109
+ .replace(/<(h3|h4)>/ig, '<h2>').replace(/<\/(h3|h4)>/ig, '</h2>')
110
+
111
+ // Updating task and moving to Release section...
112
+ console.error(JSON.stringify(updatedNotes))
113
+ await asana.tasks.updateTask(new_task.gid, {html_notes: updatedNotes})
114
+
115
+ await asana.tasks.addProjectForTask(new_task.gid, { project: autoconsentProjectGid, section: releaseSectionGid })
116
+
117
+ // The duplicateTask job returns when the task itself has been duplicated, ignoring the subtasks.
118
+ // We want to wait that the job completes so that we can fetch all the subtasks correctly.
119
+ await waitForJobSuccess(duplicateTaskJobGid)
120
+
121
+ // Getting subtasks...
122
+ const { data: subtasks } = await asana.tasks.getSubtasksForTask(new_task.gid, {opt_fields: 'name,html_notes,permalink_url'})
123
+
124
+ // Updating subtasks and moving to appropriate projects...
125
+ for (const subtask of subtasks) {
126
+ const {gid, name, html_notes, permalink_url} = subtask
127
+
128
+ const platform = Object.keys(platforms).find(
129
+ (key) => name.includes(platforms[key].displayName)
130
+ )
131
+ if (!platform) throw new Error('Unexpected platform name: ' + name)
132
+
133
+ platforms[platform].taskGid = gid
134
+ platforms[platform].taskUrl = permalink_url
135
+
136
+ const newName = name.replace('[[version]]', version)
137
+ const extractedProjects = html_notes.match(projectExtractorRegex)?.[1]
138
+
139
+ const subtaskNotes =
140
+ html_notes.replace(projectExtractorRegex, '')
141
+ .replace('[[notes]]', updatedNotes)
142
+
143
+ await asana.tasks.updateTask(gid, { name: newName, html_notes: subtaskNotes })
144
+
145
+ if (extractedProjects) {
146
+ for (const projectGid of extractedProjects.split(',')) {
147
+ await asana.tasks.addProjectForTask(gid, { project: projectGid, insert_after: null })
148
+ }
149
+ }
150
+ }
151
+
152
+ const finalNotes =
153
+ updatedNotes
154
+ .replace('<li>[[pr_url]]</li>', version)
155
+ .replace('<li>[[extra_content]]</li>', version)
156
+
157
+ await asana.tasks.updateTask(new_task.gid, {html_notes: finalNotes})
158
+
159
+ const jsonString = JSON.stringify(platforms)
160
+ return {stdout: jsonString}
161
+ }
162
+
163
+ asanaCreateTasks()
164
+ .then((result) => {
165
+ // The log is needed to read the value from the bash context
166
+ console.log(result.stdout)
167
+ })
168
+ .catch((e) => {
169
+ // The Asana API returns errors in e.value.errors. If that's undefined log whatever else we got
170
+ console.error(e.value?.errors || e)
171
+ process.exit(1)
172
+ })
173
+
174
+ module.exports = {asanaCreateTasks}
@@ -0,0 +1,57 @@
1
+ const Asana = require('asana')
2
+ const {replaceAllInString, getLink} = require('./release-utils.js')
3
+
4
+ const ASANA_ACCESS_TOKEN = process.env.ASANA_ACCESS_TOKEN
5
+ const prUrls = {
6
+ android: process.env.ANDROID_PR_URL || 'https://example.com/',
7
+ ios: process.env.IOS_PR_URL || 'https://example.com/',
8
+ macos: process.env.MACOS_PR_URL || 'https://example.com/',
9
+ windows: process.env.WINDOWS_PR_URL || 'https://example.com/',
10
+ }
11
+ const asanaOutputRaw = process.env.ASANA_OUTPUT
12
+
13
+ let asana
14
+
15
+ const setupAsana = () => {
16
+ asana = Asana.Client.create({
17
+ 'defaultHeaders': {
18
+ 'Asana-Enable': 'new_project_templates,new_user_task_lists,new_goal_memberships'
19
+ }
20
+ }).useAccessToken(ASANA_ACCESS_TOKEN)
21
+ }
22
+
23
+ const asanaUpdateTasks = async () => {
24
+ let asanaOutput
25
+ try {
26
+ asanaOutput = JSON.parse(asanaOutputRaw || '')
27
+ } catch (e) {
28
+ throw new Error('Unable to parse Asana output JSON')
29
+ }
30
+
31
+ setupAsana()
32
+
33
+ const platformEntries = Object.entries(asanaOutput)
34
+ for (const [platformName, platformObj] of platformEntries) {
35
+ // If we're missing required data, either we haven't implemented automation for that platform yet,
36
+ // or something went wrong in a previous job
37
+ if (!platformObj.taskGid || !prUrls[platformName]) continue
38
+
39
+ const { html_notes: notes } = await asana.tasks.getTask(platformObj.taskGid, { opt_fields: 'html_notes' })
40
+
41
+ const prLink = getLink(prUrls[platformName], `${platformObj.displayName} PR`)
42
+ /** @type {[[RegExp, string]]} */
43
+ const taskDescriptionSubstitutions = [
44
+ [/\[\[pr_url]]/, prLink]
45
+ ]
46
+
47
+ const updatedNotes = replaceAllInString(notes, taskDescriptionSubstitutions)
48
+
49
+ await asana.tasks.updateTask(platformObj.taskGid, { html_notes: updatedNotes })
50
+ }
51
+ }
52
+
53
+ asanaUpdateTasks().catch((e) => {
54
+ // The Asana API returns errors in e.value.errors. If that's undefined log whatever else we got
55
+ console.error(e.value?.errors || e)
56
+ process.exit(1)
57
+ })
@@ -0,0 +1,12 @@
1
+ Task/Issue URL: [[asana_url]]
2
+ Autoconsent Release: [[autoconsent_release_url]]
3
+ [[extra_content]]
4
+
5
+ ## Description
6
+ Updates Autoconsent to version [[[version]]]([[autoconsent_release_url]]).
7
+
8
+ ### Autoconsent [[version]] release notes
9
+ [[description]]
10
+
11
+ ## Steps to test
12
+ This release has been tested during Autoconsent development. You can check the release notes for more information.
@@ -0,0 +1,61 @@
1
+ const {readFileSync} = require('fs')
2
+ const {join} = require('path')
3
+ const {replaceAllInString} = require('./release-utils.js')
4
+ const cwd = join(__dirname, '..')
5
+ const filepath = (...path) => join(cwd, ...path)
6
+
7
+ /**
8
+ * @typedef {{
9
+ * releaseNotesRaw: string,
10
+ * asanaOutputRaw: string,
11
+ * releaseUrl: string,
12
+ * version: string
13
+ * }} CreatePRTemplateData
14
+ * @typedef {'android' | 'extensions' | 'bsk' | 'ios' | 'macos' | 'windows'} ReleasePlatform
15
+ */
16
+
17
+ const platform = /** @type {ReleasePlatform} */ (process.argv[2])
18
+
19
+ /** @type {CreatePRTemplateData} */
20
+ const data = {
21
+ version: process.env.VERSION || '',
22
+ releaseUrl: process.env.RELEASE_URL || '',
23
+ releaseNotesRaw: process.env.RELEASE_NOTES || '',
24
+ asanaOutputRaw: process.env.ASANA_OUTPUT || '{}'
25
+ }
26
+
27
+ /**
28
+ * Outputs the PR template populated with data
29
+ * @param {ReleasePlatform} platform
30
+ * @param {CreatePRTemplateData} data
31
+ * @returns {string}
32
+ */
33
+ function createPRTemplate (platform, data) {
34
+ const asanaOutput = JSON.parse(data.asanaOutputRaw)
35
+ const templatePath = filepath(`./ci/clients_pr_template.md`)
36
+ const template = readFileSync(templatePath, 'utf8')
37
+
38
+ const asanaUrlRegex = /\[\[asana_url]]/
39
+ const autoconsentReleaseUrlRegex = /\[\[autoconsent_release_url]]/
40
+ const extraContentRegex = /\[\[extra_content]]/
41
+ const versionRegex = /\[\[version]]/
42
+ const descriptionRegex = /\[\[description]]/
43
+
44
+ let extraContent = ''
45
+
46
+ let asanaUrl = asanaOutput[platform]?.taskUrl
47
+
48
+ const updatedTemplate = replaceAllInString(template, [
49
+ [asanaUrlRegex, asanaUrl],
50
+ [autoconsentReleaseUrlRegex, data.releaseUrl],
51
+ [extraContentRegex, extraContent],
52
+ [versionRegex, data.version],
53
+ [descriptionRegex, data.releaseNotesRaw]
54
+ ])
55
+ return updatedTemplate
56
+ }
57
+
58
+ // The log is needed to read the value from the bash context
59
+ console.log(createPRTemplate(platform, data))
60
+
61
+ module.exports = {createPRTemplate}