Skip to content

Commit bcbf221

Browse files
authored
Merge pull request #19 from jhale1805:dev
Add support for organization projects + multiple saved configs
2 parents fd5e572 + 1390e03 commit bcbf221

File tree

13 files changed

+416
-60
lines changed

13 files changed

+416
-60
lines changed

.gitignore

Lines changed: 143 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,149 @@
1+
# Local config files
12
secrets.json
23
config.json
34

4-
**/venv**
5-
5+
# VS Code Project Files
66
.vscode
77

8-
__pycache__
98

10-
.coverage
9+
############################################################################
10+
# From https://github.com/github/gitignore/blob/master/Python.gitignore
11+
############################################################################
12+
# Byte-compiled / optimized / DLL files
13+
__pycache__/
14+
*.py[cod]
15+
*$py.class
16+
17+
# C extensions
18+
*.so
19+
20+
# Distribution / packaging
21+
.Python
22+
build/
23+
develop-eggs/
24+
dist/
25+
downloads/
26+
eggs/
27+
.eggs/
28+
lib/
29+
lib64/
30+
parts/
31+
sdist/
32+
var/
33+
wheels/
34+
share/python-wheels/
35+
*.egg-info/
36+
.installed.cfg
37+
*.egg
38+
MANIFEST
39+
40+
# PyInstaller
41+
# Usually these files are written by a python script from a template
42+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
43+
*.manifest
44+
*.spec
45+
46+
# Installer logs
47+
pip-log.txt
48+
pip-delete-this-directory.txt
49+
50+
# Unit test / coverage reports
51+
htmlcov/
52+
.tox/
53+
.nox/
54+
.coverage
55+
.coverage.*
56+
.cache
57+
nosetests.xml
58+
coverage.xml
59+
*.cover
60+
*.py,cover
61+
.hypothesis/
62+
.pytest_cache/
63+
cover/
64+
65+
# Translations
66+
*.mo
67+
*.pot
68+
69+
# Django stuff:
70+
*.log
71+
local_settings.py
72+
db.sqlite3
73+
db.sqlite3-journal
74+
75+
# Flask stuff:
76+
instance/
77+
.webassets-cache
78+
79+
# Scrapy stuff:
80+
.scrapy
81+
82+
# Sphinx documentation
83+
docs/_build/
84+
85+
# PyBuilder
86+
.pybuilder/
87+
target/
88+
89+
# Jupyter Notebook
90+
.ipynb_checkpoints
91+
92+
# IPython
93+
profile_default/
94+
ipython_config.py
95+
96+
# pyenv
97+
# For a library or package, you might want to ignore these files since the code is
98+
# intended to run in multiple environments; otherwise, check them in:
99+
# .python-version
100+
101+
# pipenv
102+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
103+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
104+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
105+
# install all needed dependencies.
106+
#Pipfile.lock
107+
108+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
109+
__pypackages__/
110+
111+
# Celery stuff
112+
celerybeat-schedule
113+
celerybeat.pid
114+
115+
# SageMath parsed files
116+
*.sage.py
117+
118+
# Environments
119+
.env
120+
.venv
121+
env/
122+
venv/
123+
ENV/
124+
env.bak/
125+
venv.bak/
126+
127+
# Spyder project settings
128+
.spyderproject
129+
.spyproject
130+
131+
# Rope project settings
132+
.ropeproject
133+
134+
# mkdocs documentation
135+
/site
136+
137+
# mypy
138+
.mypy_cache/
139+
.dmypy.json
140+
dmypy.json
141+
142+
# Pyre type checker
143+
.pyre/
144+
145+
# pytype static type analyzer
146+
.pytype/
147+
148+
# Cython debug symbols
149+
cython_debug/

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ build: instructions
77

88
run: instructions
99
cd ./src/github_projects_burndown_chart \
10-
&& PYTHONPATH=. python main.py
10+
&& PYTHONPATH=. python main.py $(project_type) $(project_name)
1111

1212
test: instructions
1313
coverage run \

README.md

Lines changed: 64 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
# Burndown Chart for GitHub Projects
22
An easy to use [burndown chart](https://www.scrum.org/resources/scrum-glossary#:~:text=B-,burn-down%20chart,-%3A%C2%A0a%20chart%20which) generator for [GitHub Project Boards](https://docs.github.com/en/issues/organizing-your-work-with-project-boards/managing-project-boards/about-project-boards).
33

4+
![Example Burndown Chart](./docs/images/example_burndown_chart.png)
5+
46
## Table of Contents
57
* [Features](#features)
68
* [Installation](#installation)
79
* [Assumptions](#assumptions)
10+
* [Configuration](#configuration)
811
* [Usage](#usage)
912
* [Contributing](#contributing)
1013
* [About](#about)
1114

1215
## Features
1316
* Create a **burndown chart for a GitHub Project Board**.
14-
* Works for **private repositories**.
17+
* Works for projects in **public/private repositories** and **organizations**.
1518
* Includes a **trend line** for the current sprint.
1619
* Supports custom labels for **tracking points for issues**
1720

@@ -20,9 +23,9 @@ This tool, while flexible, makes the following assumptions about your project ma
2023
* You use one and only one [GitHub Project Board](https://docs.github.com/en/issues/organizing-your-work-with-project-boards/managing-project-boards/about-project-boards) for each of your [Sprints](https://scrumguides.org/scrum-guide.html#the-sprint)
2124
* You use one and only one [GitHub Milestone](https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/about-milestones) for each of your [User Stories](https://www.scrum.org/resources/blog/user-story-or-stakeholder-story)
2225
* You use one and only one [GitHub Issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/about-issues) for each of your [Sprint Backlog Items/Tasks](https://scrumguides.org/scrum-guide.html#sprint-backlog)
23-
* Each of your GitHub Issues has a [label](https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/managing-labels) indicating how many [points](https://www.scrum.org/resources/scrum-glossary#:~:text=several%20ways%20such%20as-,user%20story%20points,-or%20task%20hours.%20Work) its corresponding task is worth.
26+
* If you want to track points, each of your GitHub Issues has a [label](https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/managing-labels) indicating how many [points](https://www.scrum.org/resources/scrum-glossary#:~:text=several%20ways%20such%20as-,user%20story%20points,-or%20task%20hours.%20Work) its corresponding task is worth.
2427
- Furthermore, all labels that indicate point values have the format `<prefix><int>`.
25-
- However, multiple labels indicating points on the same Issue are supported.
28+
- Multiple labels indicating points on the same Issue are supported.
2629
* A Sprint Backlog Task is considered [Done](https://www.scrum.org/resources/professional-scrum-developer-glossary#:~:text=D-,definition%20of%20done%3A,-a%20shared%20understanding) if its corresponding GitHub Issue is Closed.
2730

2831
## Installation
@@ -38,7 +41,7 @@ python -m venv ./venv
3841

3942
### 2. Activate the virtual environment
4043

41-
*Linux/Mac OS*
44+
*Linux/macOS*
4245
```
4346
source venv/bin/activate
4447
```
@@ -56,34 +59,64 @@ source venv/bin/activate
5659
pip install -r requirements.txt
5760
```
5861

62+
## Configuration
63+
### 1. Create a [Personal Access Token](https://github.com/settings/tokens) with the `repo` scope.
64+
Do not share this token with anyone! It gives the bearer full control over all private repositories you have access to!
65+
66+
This is required to pull the Project Board data from GitHub's GraphQL API.
67+
### 2. Make a copy of `src/github_projects_burndown_chart/config/secrets.json.dist` without the `.dist` ending.
68+
This allows the `.gitignore` to exclude your `secrets.json` from being accidentally committed.
69+
### 3. Fill out the `github_token` with your newly created Personal Access Token.
70+
### 4. Make a copy of `src/github_projects_burndown_chart/config/config.json.dist` without the `.dist` ending.
71+
This allows the `.gitignore` to exclude your `config.json` from being accidentally committed.
72+
### 5. Fill out all the configuration settings
73+
#### Repository Projects
74+
`project_name`: A memorable name for your project for use with this tool.
75+
76+
`project_name.query_variables`
77+
| Variable | Meaning |
78+
|----------|---------|
79+
| `repo_owner` | The username of the owner of the repo. <br/><br/> Example: `jhale1805` |
80+
| `repo_name` | The name of the repo. <br/><br/> Example: `github-projects-burndown-chart`|
81+
| `project_number` | The ID of the project for which you want to generate a burndown chart. This is found in the URL when looking at the project board on GitHub. <br/><br/> Example: `1` (from [`https://github.com/jhale1805/github-projects-burndown-chart/projects/1`](https://github.com/jhale1805/github-projects-burndown-chart/projects/1)) |
82+
| `column_count` | A number >= the number of columns on the project board. (DEFAULT: 5)<br/><br/> A closer fit improves performance and reduces the chance of rate limiting from GitHub's GraphQL API. |
83+
| `max_cards_per_column_count` | A number >= the maximum number of cards in any column on the project board. (DEFAULT: 50)<br/><br/> A closer fit improves performance and reduces the chance of rate limiting from GitHub's GraphQL API. |
84+
| `labels_per_issue_count` | A number >= the number of labels on any issue on project board. (DEFAULT: 5)<br/><br/> A closer fit improves performance and reduces the chance of rate limiting from GitHub's GraphQL API. |
85+
86+
`project_name.settings`
87+
| Variable | Meaning |
88+
|----------|---------|
89+
| `sprint_start_date` | The first day of the sprint formatted as `YYYY-MM-DD`. <br/><br/> Must be entered here since GitHub Project Boards don't have an assigned start/end date. <br/><br/> Example: `2021-10-08` |
90+
| `sprint_end_date` | The last day of the sprint formatted as `YYYY-MM-DD`. <br/><br/> Must be entered here since GitHub Project Boards don't have an assigned start/end date. <br/><br/> Example: `2021-10-21` |
91+
| `points_label` | (OPTIONAL) The prefix for issue labels containing the point value of the issue. Removing this prefix must leave just an integer. If set to `null`, the burndown chart will count open issues instead of points.<br/><br/> Example: `Points: ` (with the space) |
92+
93+
#### Organization Projects
94+
All settings are the same as for the [Repository Projects](#repository-projects), except `repo_owner` and `repo_name` are replaced with `organization_name` as shown below.
95+
96+
`project_name.query_variables`
97+
| Variable | Meaning |
98+
|----------|---------|
99+
| `organization_name` | The name of the organization on GitHub as it appears in the URL of their organization page. <br/><br/> Example: `golang` (from https://github.com/golang) |
59100
## Usage
60-
### Configuration
61-
1. Create a [Personal Access Token](https://github.com/settings/tokens) with the `repo` scope.
62-
- Do not share this token with anyone! It gives the bearer full control over all private repositories you have access to!
63-
- This is required to pull the Project Board data from GitHub's GraphQL API.
64-
2. Make a copy of `src/github_projects_burndown_chart/config/secrets.json.dist` without the `.dist` ending.
65-
- This allows the `.gitignore` to exclude your `secrets.json` from being accidentally committed.
66-
3. Fill out the `github_token` with your newly created Personal Access Token.
67-
4. Make a copy of `src/github_projects_burndown_chart/config/config.json.dist` without the `.dist` ending.
68-
- This allows the `.gitignore` to exclude your `config.json` from being accidentally committed.
69-
5. Fill out all the configuration settings
70-
- `repository_project_query.repo_owner`: The username of the owner of the repo.
71-
- For example, `jhale1805`
72-
- `repository_project_query.repo_name`: The name of the repo.
73-
- For example, `github-projects-burndown-chart`
74-
- `repository_project_query.project_number`: The id of the project for which you want to generate a burndown chart. This is found in the URL when looking at the project board on GitHub.
75-
- For example, `1` from [`https://github.com/jhale1805/github-projects-burndown-chart/projects/1`](https://github.com/jhale1805/github-projects-burndown-chart/projects/1)
76-
- `settings.sprint_start_date`: The first day of the sprint. Formatted as `YYYY-MM-DD`.
77-
- Must be entered here since GitHub Project Boards don't have an assigned start/end date.
78-
- For example, `2021-10-08`
79-
- `settings.sprint_end_date`: The last day of the sprint. Formatted as `YYYY-MM-DD`.
80-
- Must be entered here since GitHub Project Boards don't have an assigned start/end date.
81-
- For example, `2021-10-22`
82-
- `settings.points_label`: The prefix for issue labels containing the point value of the issue. Removing this prefix must leave just an integer.
83-
- For example: `Points: ` (with the space)
84-
### Generating the Chart
85-
1. Run `make run` to generate the burndown chart.
86-
- This will pop up an interactive window containing the burndown chart, including a button for saving it as a picture.
101+
Given that `PROJECT_TYPE` is one of `[repository, organization]` and `PROJECT_NAME` matches a key in the `config.json` under the chosen `PROJECT_TYPE`, run the following command:
102+
```
103+
make run project_type=PROJECT_TYPE project_name=PROJECT_NAME
104+
```
105+
106+
This will pop up an interactive window containing the burndown chart, including a button for saving it as a picture.
107+
108+
### Example
109+
Make a copy of `example.config.json` without the leading `example.`
110+
111+
To see this repository's example project board:
112+
```
113+
make run project_type=repository project_name=burndown_chart_kickoff
114+
```
115+
116+
To see Golang's progress on their current roadmap:
117+
```
118+
make run project_type=organization project_name=golang_on_deck
119+
```
87120

88121
## Contributing
89122
Contributions are welcome via a [Pull Request](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request).
55.8 KB
Loading

src/github_projects_burndown_chart/chart/burndown.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ def render(self):
4141

4242
# Set titles and labels
4343
plt.title(f"{self.project.name}: Burndown Chart")
44-
plt.ylabel("Outstanding Points")
44+
points_label = config['settings']['points_label']
45+
plt.ylabel(f"Outstanding {'Points' if points_label else 'Issues'}")
4546
plt.xlabel("Date")
4647

4748
# Generate Plot

src/github_projects_burndown_chart/config/__init__.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,51 @@
1515
os.getcwd(),
1616
os.path.dirname(__file__)))
1717

18+
###############################################################################
19+
# Load config.json
20+
###############################################################################
1821
try:
1922
with open(os.path.join(__location__, 'config.json')) as config_json:
20-
config = json.load(config_json)
23+
__config = json.load(config_json)
2124
except FileNotFoundError as err:
2225
__logger.critical(err)
2326
__logger.critical('Please create a config.json file in the config '
24-
'directory; this tool cannot generate a burndown chart without it.')
27+
'directory; this tool cannot generate a burndown chart without it.')
2528
__logger.critical('See the project README.md and config/config.json.dist '
26-
'for details.')
29+
'for details.')
2730
exit(1)
2831

32+
33+
class Config:
34+
35+
def __init__(self, raw_config: dict):
36+
self.raw_config = raw_config
37+
38+
def set_project(self, project_type: str, project_name: str):
39+
self.project_type = project_type
40+
self.project_name = project_name
41+
42+
def __getitem__(self, key: str):
43+
if not hasattr(self, 'project_type'):
44+
raise AttributeError('No project has been set.')
45+
if not hasattr(self, 'project_name'):
46+
raise AttributeError('No project has been set.')
47+
return self.raw_config[self.project_type][self.project_name][key]
48+
49+
50+
config = Config(__config)
51+
52+
53+
###############################################################################
54+
# Load secrets.json
55+
###############################################################################
2956
try:
3057
with open(os.path.join(__location__, 'secrets.json')) as secrets_json:
3158
secrets = json.load(secrets_json)
3259
except FileNotFoundError as err:
3360
__logger.critical(err)
3461
__logger.critical('Please create a secrets.json file in the config '
35-
'directory; this tool cannot generate a burndown chart without it.')
62+
'directory; this tool cannot generate a burndown chart without it.')
3663
__logger.critical('See the project README.md and config/secrets.json.dist '
37-
'for details.')
38-
exit(1)
64+
'for details.')
65+
exit(1)

0 commit comments

Comments
 (0)