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

Packet 3.5.4 #287

Merged
merged 26 commits into from
Aug 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f6d9a13
Automate deployments when new releases are made
mxmeinhold Mar 21, 2021
7d73349
Actually count the number of upper sigs
mxmeinhold Mar 24, 2021
30643c5
Sort requirements.txt
mxmeinhold Mar 27, 2021
bff8fb9
Update flask-pyoidc requirement from ~=2.2.0 to ~=3.7.0
dependabot[bot] Dec 25, 2020
49c9b4e
Update sentry-sdk requirement from ~=0.19.5 to ~=1.0.0
dependabot[bot] Mar 8, 2021
94642cd
Update pylint requirement from ~=2.6.0 to ~=2.7.2
dependabot[bot] Mar 1, 2021
5169fee
Update onesignal-sdk requirement from ~=1.0.0 to ~=2.0.0
dependabot[bot] Mar 27, 2021
ac6c154
Update flask-migrate requirement from ~=2.5.3 to ~=2.7.0
dependabot[bot] Feb 22, 2021
c6af913
Merge pull request #255 from ComputerScienceHouse/upper-sigs-counts-p…
mxmeinhold Mar 27, 2021
c10fd58
Add simple readiness check
mxmeinhold Mar 28, 2021
a981349
Bump gulp-rename from 1.4.0 to 2.0.0 (#222)
dependabot[bot] Mar 28, 2021
d3b7568
Remove duplicate 'v' in logs
mxmeinhold Mar 27, 2021
c36fa69
Merge pull request #256 from mxmeinhold/ready
mxmeinhold Mar 30, 2021
11058d1
Merge pull request #254 from mxmeinhold/cd
mxmeinhold Mar 30, 2021
73e55ac
Add type hints and mypy
mxmeinhold Mar 28, 2021
2c25b06
Merge pull request #257 from mxmeinhold/type-hints
mxmeinhold Apr 2, 2021
6244114
Bump y18n from 3.2.1 to 3.2.2 (#260)
dependabot[bot] May 6, 2021
f32fac3
Update flask-sqlalchemy requirement from ~=2.4.4 to ~=2.5.1 (#259)
dependabot[bot] May 6, 2021
7f7ad70
Ignore abstract-class-instantiated for sentry init
mxmeinhold Aug 17, 2021
fe708ca
Add `packet/routes` to pylint in ci
mxmeinhold Aug 17, 2021
7082ce1
Merge pull request #285 from mxmeinhold/pylint-fixes
mxmeinhold Aug 17, 2021
e5a5cc4
Make report button readable
mxmeinhold Aug 17, 2021
f6e0300
Merge pull request #286 from mxmeinhold/readable-report
mxmeinhold Aug 17, 2021
61bef0d
Hide sigs from frosh and sort by names by default
mxmeinhold Aug 16, 2021
dcfe27b
Merge pull request #283 from ComputerScienceHouse/hide-stuff
mxmeinhold Aug 20, 2021
3648b10
Bump to 3.5.4
mxmeinhold Aug 20, 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
78 changes: 78 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Trigger Builds on Release
# Trigger builds on okd only on new releases
# Assumes the branch is "master"
# Uses secrets.OKD_BUILD_HOOK to know where to send the event to
# OKD_BUILD_HOOK should be a generic build hook

on:
release:
types:
- released

jobs:
trigger_build:
name: trigger build
runs-on: ubuntu-latest
steps:
# Grab committer and author information from the commit
- name: get commit
id: commit
run: |
commit_url=$(
jq -r '.repository.git_commits_url' $GITHUB_EVENT_PATH |
sed 's/{.*}/\/${{ github.sha }}/'
)
curl --request GET \
--silent \
--show-error \
--url "$commit_url" \
--header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \
--fail > commit-out
jq -C '.' commit-out
echo "::set-output name=committer::$(jq -c '.committer' commit-out)"
echo "::set-output name=author::$(jq -c '.author' commit-out)"

# Construct the json blob as per okd's webhook requirements
- name: format payload
run: |
cat $GITHUB_EVENT_PATH | \
jq '{
git: {
uri: .repository.html_url,
ref: "master",
commit: "${{ github.sha }}",
author: ${{ steps.commit.outputs.author }},
committer: ${{ steps.commit.outputs.committer }}
}
}' | \
tee payload.json | \
jq -C '.'

# send the webhook
- name: trigger build
id: hook
env:
OKD_BUILD_HOOK: ${{ secrets.OKD_BUILD_HOOK }}
run: |
curl \
--insecure \
--silent \
--show-error \
--header "Content-Type: application/json" \
--request POST \
--data @payload.json "$OKD_BUILD_HOOK" > curl-out
jq -C '.' curl-out || (cat curl-out; false)
echo "::set-output name=kind::$(jq '.kind' curl-out)"

# Fail if we recieved a Status response and it doesn't look good
- name: test http code
if: steps.hook.outputs.kind == 'Status'
run: "[ `jq '.code' curl-out` -lt 400 ]"

- name: test status
if: steps.hook.outputs.kind == 'Status'
run: "[ `jq '.status' curl-out` == 'Success' ]"

- name: test if skipped
if: steps.hook.outputs.kind == 'Status'
run: "[[ `jq '.message' curl-out` != *skipping* ]]"
26 changes: 25 additions & 1 deletion .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,28 @@ jobs:
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with pylint
run: |
pylint packet
pylint packet/routes packet

typecheck:
runs-on: ubuntu-latest

strategy:
matrix:
python-version: [3.9]

steps:
- name: Install ldap dependencies
run: sudo apt-get update && sudo apt-get install libldap2-dev libsasl2-dev
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Typecheck with mypy
run: |
# Disabled error codes to discard errors from imports
mypy --disable-error-code import --disable-error-code name-defined --disallow-untyped-defs --exclude routes packet
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,14 @@ All DB commands are from the `Flask-Migrate` library and are used to configure D
docs [here](https://flask-migrate.readthedocs.io/en/latest/) for details.

## Code standards
This project is configured to use Pylint. Commits will be pylinted by GitHub actions and if the score drops your build will
fail blocking you from merging. To make your life easier just run it before making a PR.
This project is configured to use Pylint and mypy. Commits will be pylinted and typechecked by GitHub actions and if the
score drops your build will fail blocking you from merging. To make your life easier just run it before making a PR.

To run pylint use this command:
To run pylint and mypy use these commands:
```bash
pylint packet/routes packet
mypy --disable-error-code import --disable-error-code name-defined --disallow-untyped-defs --exclude routes packet
```

All python files should have a top-level docstring explaining the contents of the file and complex functions should
have docstrings explaining any non-obvious portions.
have docstrings explaining any non-obvious portions. Functions should have type annotations.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"title": "CSH Packet",
"name": "csh-packet",
"version": "3.5.3-1",
"version": "3.5.4",
"description": "A web app implementation of the CSH introductory packet.",
"bugs": {
"url": "https://github.com/ComputerScienceHouse/packet/issues",
Expand All @@ -26,7 +26,7 @@
"gulp-clean-css": "^4.2.0",
"gulp-minify": "^3.1.0",
"gulp-real-favicon": "^0.3.2",
"gulp-rename": "^1.4.0",
"gulp-rename": "^2.0.0",
"gulp-sass": "^4.0.2",
"require-dir": "^1.2.0"
}
Expand Down
11 changes: 6 additions & 5 deletions packet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import os

import csh_ldap
import onesignal
import onesignal_sdk.client as onesignal
from flask import Flask
from flask_gzip import Gzip
from flask_migrate import Migrate
Expand All @@ -21,7 +21,7 @@

from .git import get_version

app = Flask(__name__)
app: Flask = Flask(__name__)
gzip = Gzip(app)

# Load default configuration and any environment variable overrides
Expand All @@ -38,7 +38,7 @@

# Logger configuration
logging.getLogger().setLevel(app.config['LOG_LEVEL'])
app.logger.info('Launching packet v' + app.config['VERSION'])
app.logger.info('Launching packet ' + app.config['VERSION'])
app.logger.info('Using the {} realm'.format(app.config['REALM']))

# Initialize the extensions
Expand All @@ -57,7 +57,7 @@
app.config['ONESIGNAL_CSH_APP_ID']:
csh_onesignal_client = onesignal.Client(
user_auth_key=app.config['ONESIGNAL_USER_AUTH_KEY'],
app_auth_key=app.config['ONESIGNAL_CSH_APP_AUTH_KEY'],
rest_api_key=app.config['ONESIGNAL_CSH_APP_AUTH_KEY'],
app_id=app.config['ONESIGNAL_CSH_APP_ID']
)
app.logger.info('CSH Onesignal configured and notifications enabled')
Expand All @@ -68,7 +68,7 @@
app.config['ONESIGNAL_INTRO_APP_ID']:
intro_onesignal_client = onesignal.Client(
user_auth_key=app.config['ONESIGNAL_USER_AUTH_KEY'],
app_auth_key=app.config['ONESIGNAL_INTRO_APP_AUTH_KEY'],
rest_api_key=app.config['ONESIGNAL_INTRO_APP_AUTH_KEY'],
app_id=app.config['ONESIGNAL_INTRO_APP_ID']
)
app.logger.info('Intro Onesignal configured and notifications enabled')
Expand All @@ -78,6 +78,7 @@
app.logger.info('OIDCAuth configured')

# Sentry
# pylint: disable=abstract-class-instantiated
sentry_sdk.init(
dsn=app.config['SENTRY_DSN'],
integrations=[FlaskIntegration(), SqlalchemyIntegration()]
Expand Down
26 changes: 13 additions & 13 deletions packet/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import sys

from secrets import token_hex
from datetime import datetime, time
from datetime import datetime, time, date
import csv
import click

Expand All @@ -15,7 +15,7 @@


@app.cli.command('create-secret')
def create_secret():
def create_secret() -> None:
"""
Generates a securely random token. Useful for creating a value for use in the "SECRET_KEY" config setting.
"""
Expand All @@ -28,13 +28,13 @@ def create_secret():


class CSVFreshman:
def __init__(self, row):
def __init__(self, row: list[str]) -> None:
self.name = row[0].strip()
self.rit_username = row[3].strip()
self.onfloor = row[1].strip() == 'TRUE'


def parse_csv(freshmen_csv):
def parse_csv(freshmen_csv: str) -> dict[str, CSVFreshman]:
print('Parsing file...')
try:
with open(freshmen_csv, newline='') as freshmen_csv_file:
Expand All @@ -44,7 +44,7 @@ def parse_csv(freshmen_csv):
raise e


def input_date(prompt):
def input_date(prompt: str) -> date:
while True:
try:
date_str = input(prompt + ' (format: MM/DD/YYYY): ')
Expand All @@ -55,7 +55,7 @@ def input_date(prompt):

@app.cli.command('sync-freshmen')
@click.argument('freshmen_csv')
def sync_freshmen(freshmen_csv):
def sync_freshmen(freshmen_csv: str) -> None:
"""
Updates the freshmen entries in the DB to match the given CSV.
"""
Expand All @@ -68,7 +68,7 @@ def sync_freshmen(freshmen_csv):

@app.cli.command('create-packets')
@click.argument('freshmen_csv')
def create_packets(freshmen_csv):
def create_packets(freshmen_csv: str) -> None:
"""
Creates a new packet season for each of the freshmen in the given CSV.
"""
Expand All @@ -84,7 +84,7 @@ def create_packets(freshmen_csv):


@app.cli.command('ldap-sync')
def ldap_sync():
def ldap_sync() -> None:
"""
Updates the upper and misc sigs in the DB to match ldap.
"""
Expand All @@ -97,7 +97,7 @@ def ldap_sync():
help='The file to write to. If no file provided, output is sent to stdout.')
@click.option('--csv/--no-csv', 'use_csv', required=False, default=False, help='Format output as comma separated list.')
@click.option('--date', 'date_str', required=False, default='', help='Packet end date in the format MM/DD/YYYY.')
def fetch_results(file_path, use_csv, date_str):
def fetch_results(file_path: str, use_csv: bool, date_str: str) -> None:
"""
Fetches and prints the results from a given packet season.
"""
Expand Down Expand Up @@ -150,7 +150,7 @@ def fetch_results(file_path, use_csv, date_str):

@app.cli.command('extend-packet')
@click.argument('packet_id')
def extend_packet(packet_id):
def extend_packet(packet_id: int) -> None:
"""
Extends the given packet by setting a new end date.
"""
Expand All @@ -168,7 +168,7 @@ def extend_packet(packet_id):
print('Packet successfully extended')


def remove_sig(packet_id, username, is_member):
def remove_sig(packet_id: int, username: str, is_member: bool) -> None:
packet = Packet.by_id(packet_id)

if not packet.is_open():
Expand Down Expand Up @@ -200,7 +200,7 @@ def remove_sig(packet_id, username, is_member):
@app.cli.command('remove-member-sig')
@click.argument('packet_id')
@click.argument('member')
def remove_member_sig(packet_id, member):
def remove_member_sig(packet_id: int, member: str) -> None:
"""
Removes the given member's signature from the given packet.
:param member: The member's CSH username
Expand All @@ -211,7 +211,7 @@ def remove_member_sig(packet_id, member):
@app.cli.command('remove-freshman-sig')
@click.argument('packet_id')
@click.argument('freshman')
def remove_freshman_sig(packet_id, freshman):
def remove_freshman_sig(packet_id: int, freshman: str) -> None:
"""
Removes the given freshman's signature from the given packet.
:param freshman: The freshman's RIT username
Expand Down
15 changes: 8 additions & 7 deletions packet/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,23 @@
import urllib
from functools import lru_cache
from datetime import datetime
from typing import Callable

from packet.models import Freshman
from packet.models import Freshman, UpperSignature
from packet import app, ldap


# pylint: disable=bare-except
@lru_cache(maxsize=128)
def get_csh_name(username):
def get_csh_name(username: str) -> str:
try:
member = ldap.get_member(username)
return member.cn + ' (' + member.uid + ')'
except:
return username


def get_roles(sig):
def get_roles(sig: UpperSignature) -> dict[str, str]:
"""
Converts a signature's role fields to a dict for ease of access.
:return: A dictionary of role short names to role long names
Expand All @@ -45,7 +46,7 @@ def get_roles(sig):

# pylint: disable=bare-except
@lru_cache(maxsize=256)
def get_rit_name(username):
def get_rit_name(username: str) -> str:
try:
freshman = Freshman.query.filter_by(rit_username=username).first()
return freshman.name + ' (' + username + ')'
Expand All @@ -55,7 +56,7 @@ def get_rit_name(username):

# pylint: disable=bare-except
@lru_cache(maxsize=256)
def get_rit_image(username):
def get_rit_image(username: str) -> str:
if username:
addresses = [username + '@rit.edu', username + '@g.rit.edu']
for addr in addresses:
Expand All @@ -69,15 +70,15 @@ def get_rit_image(username):
return 'https://www.gravatar.com/avatar/freshmen?d=mp&f=y'


def log_time(label):
def log_time(label: str) -> None:
"""
Used during debugging to log timestamps while rendering templates
"""
print(label, datetime.now())


@app.context_processor
def utility_processor():
def utility_processor() -> dict[str, Callable]:
return dict(
get_csh_name=get_csh_name, get_rit_name=get_rit_name, get_rit_image=get_rit_image, log_time=log_time,
get_roles=get_roles
Expand Down
Loading