Skip to content
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

Created officer data workflow #186

Merged
merged 37 commits into from
Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
9242f20
Does this work in prod?? 👀
EthanThatOneKid Oct 20, 2021
0483a94
Created script for updating officer data using a GitHub issue form
EthanThatOneKid Nov 2, 2021
0c6fa27
Merge branch 'main' into fix/54
EthanThatOneKid Nov 8, 2021
8be4716
Updated the update-officer.js script
EthanThatOneKid Nov 8, 2021
a10bef1
Update officer_form.yaml
EthanThatOneKid Nov 8, 2021
1403a55
Added label tags
EthanThatOneKid Nov 8, 2021
44b6f53
Update officer_form.yaml
EthanThatOneKid Nov 8, 2021
7df8881
Replica of fix/54
EthanThatOneKid Nov 8, 2021
8040670
Update officer_form.yaml
EthanThatOneKid Nov 8, 2021
8776ce7
Update update_officer.yaml
EthanThatOneKid Nov 8, 2021
6cae15f
Chaining <https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df88…
EthanThatOneKid Nov 8, 2021
10032f4
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df888…
EthanThatOneKid Nov 8, 2021
b37d767
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df888…
EthanThatOneKid Nov 8, 2021
ea15b7d
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df888…
EthanThatOneKid Nov 9, 2021
bdcb70e
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df888…
EthanThatOneKid Nov 9, 2021
fd070d1
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df888…
EthanThatOneKid Nov 9, 2021
1853c61
Chain https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df888109…
EthanThatOneKid Nov 9, 2021
5976550
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df888…
EthanThatOneKid Nov 9, 2021
2319689
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df888…
EthanThatOneKid Nov 9, 2021
612ffc0
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df888…
EthanThatOneKid Nov 9, 2021
491938f
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/blob/612ffc0c…
EthanThatOneKid Nov 9, 2021
e7f778b
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/blob/612ffc0c…
EthanThatOneKid Nov 9, 2021
22b99b4
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df888…
EthanThatOneKid Nov 9, 2021
cee746d
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df888…
EthanThatOneKid Nov 9, 2021
708cb71
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df888…
EthanThatOneKid Nov 9, 2021
9a51260
Chaining https://github.com/EthanThatOneKid/acmcsuf.com/commit/7df888…
EthanThatOneKid Nov 9, 2021
880afbb
Updated officer update request form
EthanThatOneKid Nov 9, 2021
a3c3071
Merge branch 'main' into fix/54
EthanThatOneKid Nov 9, 2021
ffd30ce
Removed useless console log
EthanThatOneKid Nov 9, 2021
bdd8c32
Delete officer_form.yaml
EthanThatOneKid Nov 9, 2021
cae7abd
Update update_officer.yaml
EthanThatOneKid Nov 9, 2021
7bb8107
Update check_website.yaml
EthanThatOneKid Nov 9, 2021
fd5339c
Merge branch 'main' into fix/54
EthanThatOneKid Nov 9, 2021
55a5b72
Update check_website.yaml
EthanThatOneKid Nov 9, 2021
7e5c455
Improved officer update logic
EthanThatOneKid Nov 9, 2021
fa0f57b
Update update-officer.js
EthanThatOneKid Nov 9, 2021
921b593
Merge branch 'main' into fix/54
EthanThatOneKid Nov 10, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/ISSUE_TEMPLATE/officer_update_request.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Officer Update Request
description: Here is where you can update an acmCSUF officer's information.
title: '[OFFICER_AUTOMATION]'
labels: ['automation:officer']

body:
- type: markdown
attributes:
value: |
### About this form
When you submit this form, an automation is triggered that creates a PR updating the user data on <https://acmcsuf.com/about/>.
This form only triggers a workflow if you are an authorized contributor.
![banner](https://raw.githubusercontent.com/EthanThatOneKid/acmcsuf.com/main/static/assets/about-illustration.svg)
**Note**: Above banner not included in your published bug report.

- type: input
id: officer_name
attributes:
label: '>>Officer Name<<'
description: Please enter the name of the officer as seen on https://acmcsuf.com/about/.
validations:
required: true

- type: dropdown
id: officer_term
attributes:
label: '>>Overwrite Officer Position<<'
options:
- Spring 2021
- Fall 2021
- Spring 2022
- Fall 2022
validations:
required: false

- type: input
id: officer_position
attributes:
label: '>>Overwrite Officer Position Title<<'
description: Please enter the new title of the officer's position during the term selected above.
validations:
required: false

- type: textarea
id: officer_image
attributes:
label: '>>Overwrite Officer Picture<<'
description: |
If an image is detected inside of this textarea, it will be used to update the officer's image on the website.
placeholder: You can attach images by clicking this area to highlight it and then dragging files in.
validations:
required: false
60 changes: 60 additions & 0 deletions .github/workflows/update_officer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Update Officer Data

on:
issues:
types: [opened, reopened]

jobs:
update_officer:
runs-on: ubuntu-latest
if: github.event.label.name == 'automation:officer'
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Parse Issue Form
id: parse
uses: peter-murray/[email protected]
with:
issue_id: ${{ github.event.issue.number }}
separator: '###'
label_marker_start: '>>'
label_marker_end: '<<'
- name: Setup Node
uses: actions/setup-node@v2
with:
node-version: '16'

- name: Run Update Officer Script
run: npm ci
run: node scripts/update-officer.js "${{ steps.parse.outputs.payload }}"

- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
commit-message: Updated officer data
title: '[OFFICER_AUTOMATION]'
body: This change was automated by officer update request \#${{ github.event.issue.number }} ✨

- name: Install Dependencies
run: npm ci

- run: node scripts/update-officer.js
env:
FORM_DATA: ${{ steps.parse.outputs.payload }}

- name: Create Pull Request
id: pull_request
uses: peter-evans/create-pull-request@v3
with:
commit-message: Update officer
title: Update officer
body: Process automated by \#${{ github.event.issue.number }}
branch: update-officers

- name: Close Issue
id: close_successfully
uses: peter-evans/close-issue@v1
with:
issue-number: ${{ github.event.issue.number }}
comment: Closed by \#${{ steps.pull_request.outputs.pull-request-number }} ✨
45 changes: 45 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@sveltejs/kit": "next",
"@typescript-eslint/eslint-plugin": "^4.31.1",
"@typescript-eslint/parser": "^4.31.1",
"axios": "^0.24.0",
"discord.js": "^13.2.0",
"dotenv": "^10.0.0",
"eslint": "^7.32.0",
Expand Down
103 changes: 103 additions & 0 deletions scripts/update-officer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import axios from 'axios';
import { config } from 'dotenv';
import { readFileSync, writeFileSync, createWriteStream } from 'fs';

/**
* Example officer data:
* ```json
* {
* "name": "Ethan Davidson",
* "positions": {
* "F20": "Competition Manager",
* "S21": "Webmaster",
* "F21": "Webmaster"
* },
* "picture": "ethan-davidson.png"
* }
*```
*/
const OFFICERS_FILENAME = './src/lib/constants/officers.json';

/**
* Converts 'Fall 2021' to 'F21', 'Spring 2022' to 'S22, etc.
*/
const termAbbr = (term) =>
term === undefined ? null : (term.startsWith('F') ? 'F' : 'S') + term.slice(term.length - 2);

/**
* Parses the first instance of an image URL from a markdown string.
*/
const parseImgSrcFromMd = (markdown) => {
// https://regex101.com/r/cSbfvF/3/
const pattern = /!\[[^\]]*\]\((?<filename>.*?)(?="|\))(?<optionalpart>".*")?\)/i;
const match = pattern.exec(markdown);
if (match === null) return null;
return match.groups.filename;
};

const downloadOfficerImage = async (url, officerName) => {
const cleanOfficerName = officerName.trim().toLowerCase().replace(/\s/g, '-');
const filename = `${encodeURIComponent(cleanOfficerName)}.png`;
const imagePath = `./static/assets/authors/${filename}`;
const response = await axios({ url, responseType: 'stream' });
return await new Promise((resolve, reject) =>
response.data
.pipe(createWriteStream(imagePath))
.on('finish', () => resolve(filename))
.on('error', reject)
);
};

const updateOfficer = async () => {
const result = JSON.parse(readFileSync(OFFICERS_FILENAME));
const {
['Officer Name']: name,
['Term to Overwrite']: term,
['Overwrite Officer Position Title']: title,
['Overwrite Officer Picture']: picture,
} = JSON.parse(process.env.FORM_DATA);
const isValidName = name?.trim().length > 0 ?? false;
if (!isValidName) {
console.error(`received invalid officer name, ${name}`);
return false;
}
const abbreviatedTerm = termAbbr(term);
if (abbreviatedTerm === null) {
console.error(`received invalid term, '${term}'`);
return false;
}
let officerIndex = result.findIndex((officer) => officer.name === name);
if (officerIndex === -1) {
// officer name not found, so let's create a new officer
result.push({ name });
officerIndex = result.length - 1;
}
const titleNeedsUpdate = title !== undefined && title.trim().length > 0;
if (titleNeedsUpdate) {
if (title === 'DELETE') delete result[officerIndex].positions[abbreviatedTerm];
else result[officerIndex].positions[abbreviatedTerm] = title.trim();
}
const pictureNeedsUpdate = picture !== undefined && picture.trim().length > 0;
if (pictureNeedsUpdate) {
const imgSrc = parseImgSrcFromMd(picture);
if (imgSrc === null) {
console.error(`received invalid officer picture '${picture}'`);
return false;
}
const relativeImgSrc = await downloadOfficerImage(imgSrc, name);
if (typeof relativeImgSrc === 'string') result[officerIndex].picture = relativeImgSrc;
}
console.log(`${name.trim()}'s updated officer data: `, result[officerIndex]);
writeFileSync(OFFICERS_FILENAME, JSON.stringify(result, null, 2));
return true;
};

try {
config();
const success = await updateOfficer();
if (success) process.exit(0);
} catch (error) {
console.error(error);
}

process.exit(1);
Loading