Skip to content

Commit

Permalink
Add Prettier, set up CI (#85)
Browse files Browse the repository at this point in the history
Fixes #54. ESLint is already configured with create-react-app, so this
just adds a script for running Prettier and sets up CI for Prettier,
ESLint, and Black.
  • Loading branch information
psvenk authored Nov 30, 2024
1 parent 8c3c0df commit c062692
Show file tree
Hide file tree
Showing 31 changed files with 302 additions and 185 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ Scripts in this directory are processed by Github's CI service.

## autodeploy.yml
This script automatically deploys a build of Hydrant to Scripts when it receives the `push` Git hook.

## ci.yml
This script runs Black (for backend formatting), Prettier (for frontend formatting), and ESLint (for frontend linting) for any pull request or push to the `main` branch.
46 changes: 46 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

env:
node-version: 16.x

jobs:
black:
name: Black
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: psf/black@stable
eslint:
name: ESLint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ env.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ env.node-version }}
cache: 'npm'
- name: Install node dependencies
run: npm install
- name: Run ESLint
run: npm run ci-eslint
prettier:
name: Prettier
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ env.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ env.node-version }}
cache: 'npm'
- name: Install node dependencies
run: npm install
- name: Run Prettier
run: npm run ci-prettier
1 change: 1 addition & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ Install:

- Python 3, at least Python 3.6.
- Node.js 16, at least Node 16.16.
- Careful, the latest version is 18!
- Careful, the latest version is 21!
- One way manage Node versions is using [nvm](https://github.com/nvm-sh/nvm).
- [Black](https://black.readthedocs.io/en/stable/index.html), if you plan on contributing changes to the Python backend.

In the root directory, run:

Expand All @@ -30,6 +31,8 @@ If this is the **first time** you're spinning up the website, the two steps have

After the first time, the step order doesn't matter to bring up the site; in fact, backend step (1) can even be skipped -- since you'd already have locally cached data. Though backend commands are still necessary if you'd like to keep the data updated.

Before making commits, run `black .` (for the backend) and `npm run format` (for the frontend) to ensure that your changes comply with the project's code style. (This will also get checked by CI when you open a pull request.) Both [Black](https://black.readthedocs.io/en/stable/integrations/editors.html) and [Prettier](https://prettier.io/docs/en/editors) have editor integrations as well.

### Changing semesters

Let's say you're updating from e.g. Spring 2023 to Fall 2023.
Expand Down
8 changes: 7 additions & 1 deletion deploy/web_scripts/notify_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,13 @@ def main():
zfh.extractall(OUTPUT_DIR)
success = True
break
return "Fetched artifact successfully" if success else "Could not find artifact among {}: {}".format(len(artifacts), ", ".join(a.get("name") for a in artifacts))
return (
"Fetched artifact successfully"
if success
else "Could not find artifact among {}: {}".format(
len(artifacts), ", ".join(a.get("name") for a in artifacts)
)
)


if __name__ == "__main__":
Expand Down
48 changes: 47 additions & 1 deletion package-lock.json

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

14 changes: 11 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,15 @@
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"format": "prettier --write **/*.{ts,tsx}",
"ci-prettier": "prettier --check **/*.{ts,tsx}",
"ci-eslint": "eslint **/*.{ts,tsx}"
},
"eslintConfig": {
"extends": [
"react-app"
"react-app",
"prettier"
]
},
"eslintIgnore": [
Expand All @@ -50,6 +54,10 @@
"defaults"
],
"engines": {
"node": "^16.16.0"
"node": ">=16.16.0"
},
"devDependencies": {
"eslint-config-prettier": "^9.1.0",
"prettier": "3.4.1"
}
}
9 changes: 2 additions & 7 deletions scrapers/fireroad.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def parse_timeslot(day, slot):
def parse_section(section):
"""Parses a section string.
Example: "32-123/TR/0/11/F/0/2" -> [[[36, 2], [96, 2], [132, 2]], '32-123']
Args:
* section (str): The section given as a string
Expand Down Expand Up @@ -89,12 +89,7 @@ def parse_schedule(course):

# Kinds of sections that exist.
result["s"] = []
section_kinds = (
"Lecture",
"Recitation",
"Lab",
"Design"
)
section_kinds = ("Lecture", "Recitation", "Lab", "Design")

for chunk in schedule.split(";"):
name, *sections = chunk.split(",")
Expand Down
9 changes: 7 additions & 2 deletions scrapers/math_dept.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
course_list = soup.find("ul", {"class": "course-list"})
rows = course_list.findAll("li", recursive=False)


def parse_when(when):
"""
Parses when the class happens.
Expand All @@ -46,10 +47,12 @@ def parse_when(when):
times = times.replace(":", ".")
return days, times


assert parse_when("F10:30-12") == ("F", "10.30-12")
assert parse_when("MW1") == ("MW", "1")
assert parse_when("MWF11") == ("MWF", "11")


def parse_many_timeslots(days, times):
"""
Parses many timeslots
Expand Down Expand Up @@ -79,6 +82,7 @@ def make_raw_sections(days, times, room):
"""
return f"{room}/{days}/0/{times}"


def make_section_override(timeslots, room):
"""
Makes a section override
Expand All @@ -92,7 +96,8 @@ def make_section_override(timeslots, room):
"""
return [[timeslots, room]]
# lol this is wrong
#return [[section, room] for section in timeslots]
# return [[section, room] for section in timeslots]


overrides = {}

Expand Down Expand Up @@ -124,7 +129,7 @@ def make_section_override(timeslots, room):
lecture_sections = make_section_override(timeslots, where)
overrides[subject] = {
"lectureRawSections": lecture_raw_sections,
"lectureSections": lecture_sections
"lectureSections": lecture_sections,
}
# Make sure the raw thing that I do not comprehend is actually correct
assert parse_section(lecture_raw_sections) == lecture_sections[0]
Expand Down
3 changes: 1 addition & 2 deletions scrapers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
* get_term_info()
"""


import itertools
import json

Expand Down Expand Up @@ -122,7 +121,7 @@ def zip_strict(*iterables):
sentinel = object()
for tuple in itertools.zip_longest(*iterables, fillvalue=sentinel):
if any(sentinel is t for t in tuple):
raise ValueError('Iterables have different lengths')
raise ValueError("Iterables have different lengths")
yield tuple


Expand Down
45 changes: 27 additions & 18 deletions src/components/ActivityButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function ToggleButton(
props: ComponentProps<"button"> & {
active: boolean;
handleClick: () => void;
}
},
) {
const { children, active, handleClick, ...otherProps } = props;
return (
Expand Down Expand Up @@ -83,15 +83,27 @@ function OverrideLocations(props: { state: State; secs: Sections }) {
const onCancel = () => {
setIsOverriding(false);
};
return isOverriding
? <Flex gap={1} mr = {1} mt = {2}><Input
return isOverriding ? (
<Flex gap={1} mr={1} mt={2}>
<Input
value={room}
onChange={e => setRoom(e.target.value)}
placeholder="26-100" />
<Button onClick={onConfirm}><CheckIcon/></Button>
<Button onClick={onCancel} ><CloseIcon/></Button></Flex>
: (<Flex mt = {2}><Button onClick={onRelocate}>{secs.roomOverride ? "Change" : "Add"} custom location</Button></Flex>);

onChange={(e) => setRoom(e.target.value)}
placeholder="26-100"
/>
<Button onClick={onConfirm}>
<CheckIcon />
</Button>
<Button onClick={onCancel}>
<CloseIcon />
</Button>
</Flex>
) : (
<Flex mt={2}>
<Button onClick={onRelocate}>
{secs.roomOverride ? "Change" : "Add"} custom location
</Button>
</Flex>
);
}

/** Div containing section manual selection interface. */
Expand Down Expand Up @@ -157,16 +169,13 @@ function ActivityColor(props: {
setColor(canon);
setInput("");
}
}
};

return (
<Flex gap={2}>
<HexColorPicker color={color} onChange={setColor} />
<Flex direction="column" gap={2}>
<form
onSubmit={handleSubmit}
onBlur={handleSubmit}
>
<form onSubmit={handleSubmit} onBlur={handleSubmit}>
<Input
// Wide enough to hold everything, but keeps buttons below small
width={"12ch"}
Expand Down Expand Up @@ -247,7 +256,7 @@ export function ClassButtons(props: { cls: Class; state: State }) {
function NonClassAddTime(props: { activity: NonClass; state: State }) {
const { activity, state } = props;
const [days, setDays] = useState(
Object.fromEntries(WEEKDAY_STRINGS.map((day) => [day, false]))
Object.fromEntries(WEEKDAY_STRINGS.map((day) => [day, false])),
);
const [times, setTimes] = useState({ start: "10:00 AM", end: "1:00 PM" });

Expand All @@ -259,8 +268,8 @@ function NonClassAddTime(props: { activity: NonClass; state: State }) {
activity,
Timeslot.fromStartEnd(
Slot.fromDayString(day, times.start),
Slot.fromDayString(day, times.end)
)
Slot.fromDayString(day, times.end),
),
);
}
};
Expand Down Expand Up @@ -344,7 +353,7 @@ export function NonClassButtons(props: { activity: NonClass; state: State }) {
</>
);
return [renderHeading, renderButtons];
} else if(isRelocating) {
} else if (isRelocating) {
const renderHeading = () => (
<Input
value={room}
Expand Down
Loading

0 comments on commit c062692

Please sign in to comment.