Skip to content

Commit 3a0f7f0

Browse files
authored
Merge branch 'main' into 59-chore-mermaid-diagram-for-readme
Signed-off-by: Roger Barker <roger.barker@swirldslabs.com>
2 parents 22d17ff + f22c99b commit 3a0f7f0

9 files changed

Lines changed: 358 additions & 76 deletions

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,4 @@ cython_debug/
178178
**/**.DS_Store
179179
_site/*
180180
!_site/.gitkeep
181-
181+
output.projects.json

README.md

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,36 @@
33
# VersionTwo
44
Hackathon project: CLI tool to generate static planning view of issues for better team planning
55

6-
# Problem we are solving
7-
GitHub projects users are unable to easily associate issues across organizations with a project and particularly find having to manually add issues to the project board itself as a time consuming unnecessarily difficult task.
8-
9-
We propose improving this interface by adding a simple HTTP page with an interactive Kanban which is able to aggregate a user provided selection of repos, projects, organizations and display them in a filterable way.
10-
11-
# Getting Started
12-
## Requirements and Setup
13-
The following items are required to run the program.
6+
# 🚀 Getting Started
7+
## 📦 Requirements
8+
The following dependencies are required to run the program:
149
- Python 3.x
10+
- `brew install python3`
1511
- Python `pyenv` and `pyenv-virtualenv`
1612
- `brew install pyenv pyenv-virtualenv`
1713
- GitHub Command Line Interface (CLI) `gh`
14+
- `brew install gh`
15+
16+
## 💻 Setup
1817
- Authentication through `gh auth login`
19-
- Set the appropriate token permissions: `gh auth refresh --scopes read:project`
18+
- Set the `GITHUB_TOKEN` environment variable: `export GITHUB_TOKEN=$(gh auth token)`
19+
- Set the `GITHUB_UNAME` environment variable: `export GITHUB_UNAME=$(gh auth status | grep "(GITHUB_TOKEN)" | cut -d " " -f9)`
20+
- Set the appropriate token permissions: `gh auth refresh --scopes read:project`
21+
- Note: The team must be a member of the Project Board in order to view the issues on the board.
22+
- Run `make install` inside the repo directory to configure the appropriate versions of dependencies.
23+
24+
## 🛠 Usage
25+
To run the main script, change to the current directory of the script, then run:
2026

21-
Run `make install` inside the repo directory to configure the appropriate versions of dependencies.
27+
`python version2.py --output-file "<filename.json>" --temp-dir "<temp.dir>" --include-team <teamname>`
28+
29+
See the `--help` menu for full list of filter functionality.
30+
31+
# Background
32+
GitHub users have issues assigned to themselves or a team they are a member of. These issues can be viewed on a
33+
Project board, which captures the issues in swim lanes. The Project board can only automate with a single organization,
34+
meaning users who work in more than one org do not have a single location to view all issues. This leads to fragmented
35+
planning and execution.
2236

2337
# How does it work?
2438

@@ -36,3 +50,9 @@ flowchart TD
3650
I --> J[_site/index.html]
3751
classDef api fill:#e3f2fd,stroke:#2196f3;
3852
classDef cli fill:#f1f8e9,stroke:#7cb342;
53+
```
54+
55+
# Our Solution
56+
Our python script will query the GitHub API for all issues associated with the appropriate filters provided to the CLI
57+
tool. The output will be a static HTML page showing all issues in swim lanes. This provides a comprehensive overview
58+
of all issues the team or user has assigned.

current-implemented-CLI.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
- `temp-dir` - The temporary directory to write JSON response files
77

88
- `include-team` - Include a team to the query
9+
- `include-user` - Include a user to the query
910

1011

1112
## To Be Implemented
1213

13-
- `include-user` - Include a specific user to the query
1414
- `include-repository` - Include specific repo to the query
1515
- `include-organization` - Include specific org to a query
1616
- `include-organization-repository` - Include specific org/repo to the query

src/queryFilter.py

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
"""
2+
query_filter.py
3+
4+
This module defines the QueryFilter class, which is used to filter GitHub projects based on various criteria.
5+
It is used in the Version2Query class to filter projects based on user input.
6+
"""
7+
8+
class QueryFilter:
9+
def __init__(
10+
self,
11+
include_teams:list[str]=None,
12+
include_users:list[str]=None,
13+
include_repositories:list[str]=None,
14+
include_organizations:list[str]=None,
15+
include_organization_repositories:list[str]=None,
16+
include_labels:list[str]=None,
17+
exclude_teams:list[str]=None,
18+
exclude_users:list[str]=None,
19+
exclude_repositories:list[str]=None,
20+
exclude_organizations:list[str]=None,
21+
exclude_organization_repositories:list[str]=None,
22+
exclude_label:list[str]=None
23+
):
24+
self.include_teams:list[str] = include_teams
25+
self.include_users:list[str] = include_users
26+
self.include_repositories:list[str] = include_repositories
27+
self.include_organizations:list[str] = include_organizations
28+
self.include_organization_repositories:list[str] = include_organization_repositories
29+
self.include_labels:list[str] = include_labels
30+
self.exclude_teams:list[str] = exclude_teams
31+
self.exclude_users:list[str] = exclude_users
32+
self.exclude_repositories:list[str] = exclude_repositories
33+
self.exclude_organizations:list[str] = exclude_organizations
34+
self.exclude_organization_repositories:list[str] = exclude_organization_repositories
35+
self.exclude_label:list[str] = exclude_label
36+
37+
@property
38+
def include_teams(self) -> list[str]:
39+
return self._include_teams
40+
@include_teams.setter
41+
def include_teams(self, value:list[str]) -> None:
42+
self._include_teams=value
43+
44+
@property
45+
def include_users(self) -> list[str]:
46+
return self._include_users
47+
@include_users.setter
48+
def include_users(self, value:list[str]) -> None:
49+
self._include_users=value
50+
51+
@property
52+
def include_repositories(self) -> list[str]:
53+
return self._include_repositories
54+
@include_repositories.setter
55+
def include_repositories(self, value:list[str]) -> None:
56+
self._include_repositories=value
57+
58+
@property
59+
def include_organizations(self) -> list[str]:
60+
return self._include_organizations
61+
@include_organizations.setter
62+
def include_organizations(self, value:list[str]) -> None:
63+
self._include_organizations=value
64+
65+
@property
66+
def include_organization_repositories(self) -> list[str]:
67+
return self._include_organization_repositories
68+
@include_organization_repositories.setter
69+
def include_organization_repositories(self, value:list[str]) -> None:
70+
self._include_organization_repositories=value
71+
72+
@property
73+
def include_labels(self) -> list[str]:
74+
return self._include_labels
75+
@include_labels.setter
76+
def include_labels(self, value:list[str]) -> None:
77+
self._include_labels=value
78+
79+
@property
80+
def exclude_teams(self) -> list[str]:
81+
return self._exclude_teams
82+
@exclude_teams.setter
83+
def exclude_teams(self, value:list[str]) -> None:
84+
self._exclude_teams=value
85+
86+
@property
87+
def exclude_users(self) -> list[str]:
88+
return self._exclude_users
89+
@exclude_users.setter
90+
def exclude_users(self, value:list[str]) -> None:
91+
self._exclude_users=value
92+
93+
@property
94+
def exclude_repositories(self) -> list[str]:
95+
return self._exclude_repositories
96+
@exclude_repositories.setter
97+
def exclude_repositories(self, value:list[str]) -> None:
98+
self._exclude_repositories=value
99+
100+
@property
101+
def exclude_organizations(self) -> list[str]:
102+
return self._exclude_organizations
103+
@exclude_organizations.setter
104+
def exclude_organizations(self, value:list[str]) -> None:
105+
self._exclude_organizations=value
106+
107+
@property
108+
def exclude_organization_repositories(self) -> list[str]:
109+
return self._exclude_organization_repositories
110+
@exclude_organization_repositories.setter
111+
def exclude_organization_repositories(self, value:list[str]) -> None:
112+
self._exclude_organization_repositories=value
113+
114+
@property
115+
def exclude_label(self) -> list[str]:
116+
return self._exclude_label
117+
@exclude_label.setter
118+
def exclude_label(self, value:list[str]) -> None:
119+
self._exclude_label=value
120+
121+
def print_filters(self) -> None:
122+
"""Print the filters for debugging purposes."""
123+
print(f"[bold green]Filters:[/bold green]")
124+
print(f"Include Teams: {self.include_teams}")
125+
print(f"Include Users: {self.include_users}")
126+
print(f"Include Repositories: {self.include_repositories}")
127+
print(f"Include Organizations: {self.include_organizations}")
128+
print(f"Include Organization Repositories: {self.include_organization_repositories}")
129+
print(f"Include Labels: {self.include_labels}")
130+
print(f"Exclude Teams: {self.exclude_teams}")
131+
print(f"Exclude Users: {self.exclude_users}")
132+
print(f"Exclude Repositories: {self.exclude_repositories}")
133+
print(f"Exclude Organizations: {self.exclude_organizations}")
134+
print(f"Exclude Organization Repositories: {self.exclude_organization_repositories}")
135+
print(f"Exclude Label: {self.exclude_label}")
136+
137+
def get_filters(self) -> dict[str,list[str]]:
138+
"""Get the filters as a dictionary."""
139+
return {
140+
"include_teams": self.include_teams,
141+
"include_users": self.include_users,
142+
"include_repositories": self.include_repositories,
143+
"include_organizations": self.include_organizations,
144+
"include_organization_repositories": self.include_organization_repositories,
145+
"include_labels": self.include_labels,
146+
"exclude_teams": self.exclude_teams,
147+
"exclude_users": self.exclude_users,
148+
"exclude_repositories": self.exclude_repositories,
149+
"exclude_organizations": self.exclude_organizations,
150+
"exclude_organization_repositories": self.exclude_organization_repositories,
151+
"exclude_label": self.exclude_label
152+
}
153+
154+
def set_filters_from_dict(self, filters:dict[str,list[str]]):
155+
"""Set the filters from a dictionary."""
156+
self.include_teams = filters.get("include_teams", [])
157+
self.include_users = filters.get("include_users", [])
158+
self.include_repositories = filters.get("include_repositories", [])
159+
self.include_organizations = filters.get("include_organizations", [])
160+
self.include_organization_repositories = filters.get("include_organization_repositories", [])
161+
self.include_labels = filters.get("include_labels", [])
162+
self.exclude_teams = filters.get("exclude_teams", [])
163+
self.exclude_users = filters.get("exclude_users", [])
164+
self.exclude_repositories = filters.get("exclude_repositories", [])
165+
self.exclude_organizations = filters.get("exclude_organizations", [])
166+
self.exclude_organization_repositories = filters.get("exclude_organization_repositories", [])
167+
self.exclude_label = filters.get("exclude_label", [])

src/static_site_generator.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
from jinja2 import Environment, FileSystemLoader
2-
import logging
2+
import logging
3+
import os
34

45

56
class StaticSiteGenerator():
67

78
def __init__(self):
89
self.GENERATOR_DATA = {
910
'title': 'Version Two',
10-
'github_user': 'octocat',
11-
'team': 'Platform Engineering',
11+
'github_user': "",
12+
'team': "",
1213
'tasks': []
1314
}
1415

15-
def generate_site(self, data=None, output_file='./_site/index.html'):
16+
def generate_site(self, data:list=None, teams:list[str]=None, output_file='./_site/index.html'):
1617
logging.info("Generating Static Site")
1718
env = Environment(loader=FileSystemLoader('templates'))
1819
template = env.get_template('kaban_board.html')
1920

2021
self.GENERATOR_DATA["tasks"] = data if data is not None else []
2122

23+
# Set the github user name
24+
self.github_uname = os.getenv("GITHUB_UNAME") if os.getenv("GITHUB_UNAME") else "Not logged in"
25+
self.GENERATOR_DATA["github_user"] = self.github_uname
26+
27+
# Set the team(s)
28+
self.GENERATOR_DATA["team"] = ' '.join(teams) if teams is not None else ""
29+
2230
# Extract unique statuses from the tasks list
2331
unique_statuses = sorted({task["status"] for task in self.GENERATOR_DATA["tasks"]})
2432

src/version2config.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ def init_parser(self):
5050
dest="include_user",
5151
action="append",
5252
type=str,
53-
nargs="+",
5453
help="Include all issues and PRs for the provided user [Required Parameter]"
5554
)
5655

0 commit comments

Comments
 (0)