1
- name : Send reminders to join the OCWM
1
+ name : Send Office Hours Reminders
2
2
3
3
on :
4
4
schedule :
5
- - cron : ' 0 15 1-7 * 5' # Runs at 15:00, between day 1 and 7 of the month on Friday
6
- - cron : ' 0 15 1-7 * 2' # Runs at 15:00, between day 1 and 7 of the month on Tuesday
5
+ # Europe/Americas: Last Friday of previous month, first Friday (if before Tuesday), and day of (first Tuesday), even months
6
+ - cron : ' 0 9 25-31 5,7,9,11,1,3 5' # Last Friday of odd months at 9 UTC
7
+ - cron : ' 0 9 1-7 6,8,10,12,2,4 5' # First Friday at 9 UTC in even months
8
+ - cron : ' 0 9 1-7 6,8,10,12,2,4 2' # First Tuesday at 9 UTC in even months
9
+ # APAC/Americas: Last Friday of previous month, first Friday (if before Tuesday), and day of (first Tuesday), odd months
10
+ - cron : ' 0 17 25-31 4,6,8,10,12,2 5' # Last Friday of even months at 17 UTC
11
+ - cron : ' 0 17 1-7 7,9,11,1,3,5 5' # First Friday at 17 UTC in odd months
12
+ - cron : ' 0 17 1-7 7,9,11,1,3,5 2' # First Tuesday at 17 UTC in odd months
7
13
8
14
jobs :
9
- ocwm -reminders :
15
+ send -reminders :
10
16
runs-on : ubuntu-latest
11
17
steps :
12
18
- name : Checkout Repository
13
19
uses : actions/checkout@v4
14
- - name : Set up Node 20
20
+
21
+ - name : Set up Node.js
15
22
uses : actions/setup-node@v4
16
23
with :
17
24
node-version : ' 20'
18
25
19
- - name : Get Token
26
+ - name : Get GitHub App Token
20
27
uses : actions/create-github-app-token@v1
21
28
id : get_workflow_token
22
29
with :
@@ -29,57 +36,126 @@ jobs:
29
36
- name : Send reminders
30
37
uses : actions/github-script@v7
31
38
env :
32
- MY_TOKEN : ${{ steps.get_workflow_token.outputs.token }}
39
+ GITHUB_TOKEN : ${{ steps.get_workflow_token.outputs.token }}
33
40
OWNER : ${{ vars.ORGANISATION }}
34
41
REPO : ' community'
35
42
OCWM_LABEL : ${{ vars.OCWM_LABEL }}
36
- SLACK_WEBHOOK : ${{ vars.SLACK_WEBHOOK_REMINDER }}
43
+ SLACK_WEBHOOK : ${{ secrets.SLACK_WEBHOOK_OFFICEHOURS }}
37
44
with :
38
45
script : |
39
-
40
- const octokit = require('@octokit/core').Octokit;
41
- const mygithub = new octokit({
42
- request: { fetch: fetch,},
43
- auth: process.env.MY_TOKEN
44
- });
45
-
46
- let targetLabel = encodeURIComponent(process.env.OCWM_LABEL);
47
-
48
- const { data: workMeetings } = await mygithub.request(`GET /repos/${process.env.OWNER}/${process.env.REPO}/issues?labels=${targetLabel}&per_page=1`, {
49
- })
50
-
51
- const issueNumber = workMeetings[0].number
52
- const newTitle = workMeetings[0].title;
53
- const issueDate = newTitle.replace(/Open Community Working Meeting /g, "");
54
-
55
- //Date of the next meeting
56
- const nextMeetingDate = new Date();
57
- nextMeetingDate.setDate(nextMeetingDate.getDate() + (2 + 7 - nextMeetingDate.getDay()) % 7);
58
-
59
- const formattedDate = nextMeetingDate.toISOString().split('T')[0];
60
-
61
- const reminderText = (new Date().getDay() === 2) ? "today" : formattedDate;
62
-
63
- // Checking if the reminder should be sent
64
- const today = new Date();
65
- const firstTuesday = new Date(today.getFullYear(), today.getMonth(), 1);
66
- firstTuesday.setDate(firstTuesday.getDate() + (2 + 7 - firstTuesday.getDay()) % 7);
67
- const firstFriday = new Date(today.getFullYear(), today.getMonth(), 1);
68
- firstFriday.setDate(firstFriday.getDate() + (5 + 7 - firstFriday.getDay()) % 7);
69
-
70
- if ((today.getDay() === 2 && today.getDate() === firstTuesday.getDate()) || (today.getDay() === 5 && today.getDate() === firstFriday.getDate() && firstFriday < firstTuesday)) {
71
- // Notify Slack
72
- const SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK;
73
- const SLACK_MESSAGE = `{
74
- "issue": "https://github.com/${process.env.OWNER}/${process.env.REPO}/issues/${issueNumber}",
75
- "date": "${reminderText}"
76
- }`;
77
-
78
- await fetch(SLACK_WEBHOOK_URL, {
46
+ const { Octokit } = require("@octokit/core");
47
+ const github = new Octokit({ auth: process.env.GITHUB_TOKEN });
48
+
49
+ function getFirstTuesdayOfMonth(year, month) {
50
+ let date = new Date(Date.UTC(year, month, 1));
51
+ while (date.getUTCDay() !== 2) {
52
+ date.setUTCDate(date.getUTCDate() + 1);
53
+ }
54
+ return date;
55
+ }
56
+
57
+ function getLastTuesdayOfMonth(year, month) {
58
+ let date = new Date(Date.UTC(year, month + 1, 0)); // Last day of the month
59
+ while (date.getUTCDay() !== 2) {
60
+ date.setUTCDate(date.getUTCDate() - 1);
61
+ }
62
+ return date;
63
+ }
64
+
65
+ function isLastFridayOfMonth(date) {
66
+ const lastDayOfMonth = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0));
67
+ const lastFriday = new Date(lastDayOfMonth);
68
+ lastFriday.setUTCDate(lastFriday.getUTCDate() - (lastFriday.getUTCDay() + 2) % 7);
69
+ return date.getUTCDate() === lastFriday.getUTCDate();
70
+ }
71
+
72
+ function isFirstFridayOfMonth(date) {
73
+ return date.getUTCDay() === 5 && date.getUTCDate() <= 7;
74
+ }
75
+
76
+ try {
77
+ const today = new Date();
78
+ const currentMonth = today.getUTCMonth();
79
+ const isEuropeAmericas = [5, 7, 9, 11, 1, 3].includes(currentMonth+1);
80
+ const isFriday = today.getUTCDay() === 5;
81
+ const isTuesday = today.getUTCDay() === 2;
82
+ const isLastFriday = isLastFridayOfMonth(today);
83
+ const isFirstFriday = isFirstFridayOfMonth(today);
84
+
85
+ console.log(`Current date: ${today.toISOString()}, Month: ${currentMonth + 1}, Is Europe/Americas: ${isEuropeAmericas}, Is Friday: ${isFriday}, Is Tuesday: ${isTuesday}, Is Last Friday: ${isLastFriday}, Is First Friday: ${isFirstFriday}`);
86
+
87
+ let timezone, time, date;
88
+ if (isEuropeAmericas) {
89
+ timezone = "Europe/Americas friendly";
90
+ time = "10:00 BST";
91
+ } else {
92
+ timezone = "APAC/Americas friendly";
93
+ time = "10:00 PT";
94
+ }
95
+
96
+ const firstTuesdayThisMonth = getFirstTuesdayOfMonth(today.getUTCFullYear(), currentMonth);
97
+ const lastTuesdayLastMonth = getLastTuesdayOfMonth(today.getUTCFullYear(), currentMonth);
98
+
99
+ let shouldSendReminder = false;
100
+
101
+ if (isFriday) {
102
+ if(isLastFriday && today > lastTuesdayLastMonth){
103
+ shouldSendReminder = true;
104
+ const firstTuesdayNextMonth = getFirstTuesdayOfMonth(today.getUTCFullYear(), currentMonth + 1);
105
+ date = firstTuesdayNextMonth.toISOString().split('T')[0];
106
+ } else if (isFirstFriday && today < firstTuesdayThisMonth) {
107
+ shouldSendReminder = true;
108
+ date = firstTuesdayThisMonth.toISOString().split('T')[0];
109
+ }
110
+ } else if (isTuesday) {
111
+ shouldSendReminder = true;
112
+ date = "today";
113
+ }
114
+
115
+ if (!shouldSendReminder) {
116
+ console.log("Not the correct day for sending a reminder");
117
+ return;
118
+ }
119
+
120
+ console.log(`Calculated date for reminder: ${date}`);
121
+
122
+ // Fetch the latest open Office Hours issue
123
+ const targetLabel = encodeURIComponent(process.env.OCWM_LABEL);
124
+ const { data: workMeetings } = await github.request(`GET /repos/${process.env.OWNER}/${process.env.REPO}/issues?labels=${targetLabel}&per_page=1&state=open`);
125
+
126
+ if (workMeetings.length === 0) {
127
+ console.log("No open Office Hours issue found");
128
+ return;
129
+ }
130
+
131
+ const issueNumber = workMeetings[0].number;
132
+ const issueLink = `https://github.com/${process.env.OWNER}/${process.env.REPO}/issues/${issueNumber}`;
133
+
134
+ console.log(`Found issue: ${issueLink}`);
135
+
136
+ // Prepare the message for Slack
137
+ const message = {
138
+ issue: issueLink,
139
+ date: date,
140
+ timezone: timezone,
141
+ time: time
142
+ };
143
+
144
+ console.log(`Sending message to Slack: ${JSON.stringify(message)}`);
145
+
146
+ // Send the message to Slack
147
+ const response = await fetch(process.env.SLACK_WEBHOOK, {
79
148
method: 'POST',
80
- headers: {
81
- 'Content-Type': 'application/json',
82
- },
83
- body: SLACK_MESSAGE,
149
+ headers: { 'Content-Type': 'application/json' },
150
+ body: JSON.stringify(message)
84
151
});
152
+
153
+ if (!response.ok) {
154
+ throw new Error(`Failed to send Slack message: ${response.statusText}`);
155
+ }
156
+
157
+ console.log(`Reminder sent for ${timezone} session on ${date}`);
158
+ } catch (error) {
159
+ console.error(`An error occurred: ${error.message}`);
160
+ core.setFailed(error.message);
85
161
}
0 commit comments