-
-
Notifications
You must be signed in to change notification settings - Fork 113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add asyncapi events scheduling automation #308
Merged
+2,989
−241
Merged
Changes from 9 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
02ed203
feat: add asyncapi events scheduling automation
derberg 83c524b
fix job id for ad hoc meeting
derberg 485a150
proper date for getting events list
derberg dd3d743
docs
derberg 6f9ecfa
host responsibilities docs
derberg a3c04bd
Merge branch 'master' into meetingsautomation
derberg de0c64a
add newsletter link
derberg d6e47c9
Apply suggestions from code review
derberg 3bda252
Merge branch 'master' into meetingsautomation
quetzalliwrites 4fc8a8b
added info about notes
derberg 977957e
Merge branch 'master' into meetingsautomation
derberg 4d1da88
Merge branch 'master' into meetingsautomation
derberg 3a75fe1
Merge branch 'master' into meetingsautomation
derberg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
name: Cancel event when issue was closed before it took place | ||
|
||
on: | ||
issues: | ||
types: | ||
- closed | ||
|
||
jobs: | ||
|
||
cancel_event: | ||
env: | ||
CALENDAR_ID: ${{ secrets.CALENDAR_ID }} | ||
CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} | ||
name: Remove event from calendar | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v2 | ||
- name: Setup Node.js | ||
uses: actions/setup-node@v2 | ||
with: | ||
node-version: 16 | ||
cache: 'npm' | ||
cache-dependency-path: '**/package-lock.json' | ||
- name: Install deps | ||
run: npm install | ||
working-directory: ./.github/workflows/create-event-helpers | ||
- name: Remove Google Calendar entry | ||
uses: actions/github-script@v4 | ||
with: | ||
script: | | ||
const { deleteEvent } = require('./.github/workflows/create-event-helpers/calendar/index.js'); | ||
deleteEvent('${{ github.event.issue.number }}', '${{ github.event.issue.closed_at }}'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
name: Schedule Ad Hoc Meeting | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
time: | ||
description: 'Info about meeting hour in UTC time zone, like: 08 or 16. No PM or AM versions.' | ||
required: true | ||
date: | ||
description: 'Date in a form like: 2022-04-05 where 04 is a month and 05 is a day number.' | ||
required: true | ||
name: | ||
description: 'Provide short title for the meeting.' | ||
required: true | ||
desc: | ||
description: 'Provide description that explains the purpose of the meeting' | ||
required: true | ||
|
||
jobs: | ||
|
||
setup-ad-hoc: | ||
uses: ./.github/workflows/create-event-workflow-reusable.yml | ||
with: | ||
time: ${{ github.event.inputs.time }} | ||
date: ${{ github.event.inputs.date }} | ||
meeting_name: ${{ github.event.inputs.name }} | ||
meeting_desc: ${{ github.event.inputs.desc }} | ||
host: lpgornicki@gmail.com | ||
alternative_host: fmvilas@gmail.com | ||
issue_template_path: .github/workflows/create-event-helpers/issues_templates/ad-hoc.md | ||
create_zoom: true | ||
secrets: | ||
GH_TOKEN: ${{ secrets.GH_TOKEN }} | ||
ZOOM_API_KEY: ${{ secrets.ZOOM_API_KEY }} | ||
ZOOM_API_SECRET: ${{ secrets.ZOOM_API_SECRET }} | ||
STREAM_URL: ${{ secrets.STREAM_URL }} | ||
STREAM_KEY: ${{ secrets.STREAM_KEY }} | ||
CALENDAR_ID: ${{ secrets.CALENDAR_ID }} | ||
CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
name: Schedule Community Meeting | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
time: | ||
description: 'Info about meeting hour in UTC time zone, like: 08 or 16. No PM or AM versions.' | ||
required: true | ||
date: | ||
description: 'Date in a form like: 2022-04-05 where 04 is a month and 05 is a day number.' | ||
required: true | ||
|
||
jobs: | ||
|
||
setup-community-meeting: | ||
uses: ./.github/workflows/create-event-workflow-reusable.yml | ||
with: | ||
time: ${{ github.event.inputs.time }} | ||
date: ${{ github.event.inputs.date }} | ||
meeting_name: Community Meeting | ||
meeting_desc: This is a community meeting to regularly talk in open about important topics around AsyncAPI Initiative. | ||
host: lpgornicki@gmail.com | ||
alternative_host: fmvilas@gmail.com | ||
issue_template_path: .github/workflows/create-event-helpers/issues_templates/community.md | ||
create_zoom: true | ||
secrets: | ||
GH_TOKEN: ${{ secrets.GH_TOKEN }} | ||
ZOOM_API_KEY: ${{ secrets.ZOOM_API_KEY }} | ||
ZOOM_API_SECRET: ${{ secrets.ZOOM_API_SECRET }} | ||
STREAM_URL: ${{ secrets.STREAM_URL }} | ||
STREAM_KEY: ${{ secrets.STREAM_KEY }} | ||
CALENDAR_ID: ${{ secrets.CALENDAR_ID }} | ||
CALENDAR_SERVICE_ACCOUNT: ${{ secrets.CALENDAR_SERVICE_ACCOUNT }} |
155 changes: 155 additions & 0 deletions
155
.github/workflows/create-event-helpers/calendar/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
const { google } = require('googleapis') | ||
const core = require('@actions/core'); | ||
|
||
module.exports = { addEvent, deleteEvent, listEvents } | ||
|
||
const auth = new google.auth.GoogleAuth({ | ||
scopes: ['https://www.googleapis.com/auth/calendar'], | ||
credentials: JSON.parse(process.env.CALENDAR_SERVICE_ACCOUNT) | ||
}); | ||
|
||
const calendar = google.calendar({ version: 'v3', auth }); | ||
|
||
/** | ||
* Adds new single-occuring event | ||
* All events are being linked to their GitHub issues | ||
* @param {String} zoomUrl Zoom url of the meeting | ||
* @param {String} startDate ex. 2022-04-05 | ||
* @param {String} startTime ex. 08 or 16 | ||
* @param {Number} issueNumber GitHub issue number of the event, to find event later | ||
*/ | ||
async function addEvent(zoomUrl, startDate, startTime, issueNumber) { | ||
|
||
const communityIssuesUrl = 'https://github.com/asyncapi/community/issues/'; | ||
const title = process.env.MEETING_NAME; | ||
const suffix = process.env.MEETING_NAME_SUFFIX; | ||
const description = process.env.MEETING_DESC; | ||
const guest = process.env.GUEST; | ||
const summary = suffix ? `${title} ${suffix}` : title; | ||
|
||
try { | ||
|
||
//helper to create end time which is always 1h later | ||
const getEndTime = (startTime) => { | ||
const time = Number(startTime); | ||
if (time < 10) return '0' + (time + 1) | ||
|
||
return (time + 1) + '' | ||
} | ||
|
||
//helper to build meeting description | ||
//there is a use case that meeting has no connection over zoom available as it is pure live stream | ||
const getDescription = (description, communityIssuesUrl, issueNumber, zoomUrl, guest) => { | ||
|
||
const zoomDetails = zoomUrl && `<b>Zoom</b>: <a href="${zoomUrl}">Meeting Link</a>`; | ||
const agendaDetails = `<b>Agenda and more options to join the meeting</b>: <a href="${communityIssuesUrl}${issueNumber}">GitHub Issue Link.</a>`; | ||
const guestDetails = guest ? `<b>Special guest</b>: ${ guest }` : ''; | ||
return `${ description }<br><br>${ zoomDetails }<br><br>${ agendaDetails }<br><br>${ guestDetails }` | ||
}; | ||
|
||
await calendar.events.insert({ | ||
calendarId: process.env.CALENDAR_ID, | ||
requestBody: { | ||
summary, | ||
description: getDescription(description, communityIssuesUrl, issueNumber, zoomUrl, guest), | ||
start: { | ||
dateTime: `${ startDate }T${ startTime }:00:00Z` | ||
}, | ||
end: { | ||
dateTime: `${ startDate }T${ getEndTime(startTime) }:00:00Z` | ||
}, | ||
location: zoomUrl, | ||
extendedProperties: { | ||
private: { | ||
'ISSUE_ID': `${issueNumber}` | ||
} | ||
} | ||
} | ||
}) | ||
|
||
core.info('Event created') | ||
} catch (error) { | ||
core.setFailed(`Faild creating event in Google Calendar: ${ JSON.stringify(error) }`) | ||
} | ||
} | ||
|
||
/** | ||
* Deletes a single-occuring event from issue number | ||
* @param {Number} issueNumber GitHub issue number of the meeting to delete | ||
* @param {Number} closeDate Date when issue was closed | ||
*/ | ||
async function deleteEvent(issueNumber, closeDate) { | ||
let events | ||
|
||
try { | ||
events = (await calendar.events.list({ | ||
calendarId: process.env.CALENDAR_ID, | ||
privateExtendedProperty: `ISSUE_ID=${issueNumber}` | ||
})).data; | ||
} catch (error) { | ||
return core.setFailed(`Failed to fetch events for issue numer ${ issueNumber }: ${ JSON.stringify(error) }`) | ||
} | ||
|
||
const eventsItems = events.items; | ||
|
||
if (eventsItems.length > 0) { | ||
|
||
const meetingId = eventsItems[0].id; | ||
const eventStartDate = new Date(eventsItems[0].start.dateTime); | ||
const issueCloseDate = new Date(closeDate); | ||
|
||
try { | ||
//in case of issue was closed after the event, we do not remove it from calendar | ||
if (eventStartDate.getTime() < issueCloseDate.getTime()) return core.info('Event not removed as related issue was closed after the event took place.'); | ||
|
||
await calendar.events.delete({ | ||
calendarId: process.env.CALENDAR_ID, | ||
eventId: meetingId | ||
}) | ||
|
||
core.info('Event deleted from calendar') | ||
} catch (error) { | ||
core.setFailed(`Failed to delete event for issue number ${ issueNumber }: ${ JSON.stringify(error) }`) | ||
} | ||
} else { | ||
core.info('Event not found in calendar') | ||
} | ||
} | ||
|
||
/** | ||
* Lists all events including single-occuring and recurring | ||
*/ | ||
async function listEvents() { | ||
|
||
let eventsItems; | ||
|
||
try { | ||
//this runs always on friday midnight | ||
const currentTime = new Date(Date.now()).toISOString(); | ||
//we check moday | ||
const timeIn2Days = new Date(Date.parse(currentTime) + 2 * 24 * 60 * 60 * 1000).toISOString(); | ||
//till friday | ||
const timeIn8Days = new Date(Date.parse(currentTime) + 8 * 24 * 60 * 60 * 1000).toISOString(); | ||
|
||
const eventsList = await calendar.events.list({ | ||
calendarId: process.env.CALENDAR_ID, | ||
timeMax: timeIn8Days, | ||
timeMin: timeIn2Days | ||
}) | ||
|
||
eventsItems = eventsList.data.items.map((e) => { | ||
return { | ||
title: e.summary, | ||
issueId: e.extendedProperties.private.ISSUE_ID, | ||
date: new Date(e.start.dateTime).toUTCString() | ||
} | ||
}) | ||
|
||
core.info(`List of all events: ${ JSON.stringify(eventsList.data, null, 4) }`) | ||
} catch (error) { | ||
return core.setFailed(`Faild fetching events from Google Calendar API: ${ JSON.stringify(error) }`) | ||
} | ||
|
||
return eventsItems; | ||
|
||
} |
75 changes: 75 additions & 0 deletions
75
.github/workflows/create-event-helpers/issues_templates/ad-hoc.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
--- | ||
title: "{{ env.MEETING_NAME }}, {{ env.FULL_DATE | date('H:mm [UTC] dddd MMMM Do YYYY') }}" | ||
--- | ||
|
||
<table> | ||
<tr> | ||
<th>Meeting Info</th> | ||
<th>Details</th> | ||
</tr> | ||
<tr> | ||
<td>Purpose</td> | ||
<td>{{ env.MEETING_DESC }}</td> | ||
</tr> | ||
<tr> | ||
<td>Time</td> | ||
<td><strong>{{ env.FULL_DATE | date('H') }}:00 UTC</strong> | Translate to your time zone with the <a href="https://dateful.com/convert/coordinated-universal-time-utc?t={{ env.FULL_DATE | date('kk') }}&d={{ env.DATE_ONLY }}">time zone converter</a>.</td> | ||
</tr> | ||
<tr> | ||
<th>Meeting Place</th> | ||
<th>Link</th> | ||
</tr> | ||
<tr> | ||
<td>Zoom</td> | ||
<td><a href="{{ env.ZOOM_LINK }}">Join live</a>.</td> | ||
</tr> | ||
<tr> | ||
<td>YouTube</td> | ||
<td><a href="https://www.youtube.com/asyncapi">Watch live and interact through live chat</a>.</td> | ||
</tr> | ||
<tr> | ||
<td>Twitch</td> | ||
<td><a href="https://www.twitch.tv/asyncapi">Watch live</a>.</td> | ||
</tr> | ||
<tr> | ||
<td>Twitter</td> | ||
<td><a href="https://twitter.com/AsyncAPISpec">Watch live</a>.</td> | ||
</tr> | ||
<tr> | ||
<td>LinkedIn</td> | ||
<td><a href="https://www.linkedin.com/company/asyncapi">Watch live</a>.</td> | ||
</tr> | ||
<tr> | ||
<th>More Info</th> | ||
<th>Details</th> | ||
</tr> | ||
<tr> | ||
<td>Meeting Recordings</td> | ||
<td><a href="https://www.youtube.com/asyncapi">YouTube Playlist</a>.</td> | ||
</tr> | ||
<tr> | ||
<td>AsyncAPI Initiative Calendar</td> | ||
<td><a href="https://calendar.google.com/calendar/embed?src=c_q9tseiglomdsj6njuhvbpts11c%40group.calendar.google.com&ctz=UTC">Public URL</a>.</td> | ||
</tr> | ||
<tr> | ||
<td>iCal File</td> | ||
<td><a href="https://calendar.google.com/calendar/ical/c_q9tseiglomdsj6njuhvbpts11c%40group.calendar.google.com/public/basic.ics">Add to your calendar</a>.</td> | ||
</tr> | ||
<tr> | ||
<td>Newsletter</td> | ||
<td><a href="https://www.asyncapi.com/newsletter">Subscribe to get weekly updates on upcoming meetings</a>.</td> | ||
</tr> | ||
</table> | ||
|
||
|
||
## Agenda | ||
|
||
> Don't wait for the meeting to discuss topics that already have issues. Feel free to comment on them earlier. | ||
|
||
1. Q&A | ||
1. _Place for your topic_ | ||
1. Q&A | ||
|
||
## Notes | ||
|
||
tbd | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems odd, like a mistake to have the tbd left in there..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is intentional.
once issue is created, there are no notes, thus
tbd - to be done/delivered
. How can we do it differently? more details sentence like "Notes are provided after the meeting?"There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you feel about writing instead:
Add notes here after the meeting.
(Can they add notes later, or did I completely misunderstand how it works? 😆 )
@derberg
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you understood it right, we never write them real-time but always after meeting, a kind of summary. I updated PR with your suggestion, thanks!!!