diff --git a/CHANGELOG.md b/CHANGELOG.md index fb795db..407e438 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All enhancements and patches to statuspage will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 0.6.0 [2016-07-26] +- Added an option to automate the update process. +- Switch to PyGithub as pygithub-redux is no longer needed +- Added an option to create private repositories +- Beefed up the docs + ## 0.5.1 [2016-07-26] - Updated dependencies: tqdm and pygithub-redux diff --git a/README.md b/README.md index e24c475..a5649a3 100644 --- a/README.md +++ b/README.md @@ -10,127 +10,72 @@ issues to display incidents and labels for severity. ## Demo -![DEMO](https://github.com/pyupio/statuspage/blob/master/demo.gif) +![DEMO](https://github.com/jayfk/statuspage/blob/master/demo.gif) See a real status page generated by this at [status.pyup.io](http://status.pyup.io/) or a [demo site](https://jayfk.github.io/statuspage-demo/) -## Before you start +## Quickstart -You'll need to create a GitHub API token. Go to your -[Personal Access tokens](https://github.com/settings/tokens) page, click on `Generate new token` and give it a description. Make -sure to check the `public_repo` scope. Copy the token somewhere safe, you won't be able to see it -again once you leave the page. - - -## Installation - -### Using pip +Install statuspage with pip: pip install statuspage -### Binaries -#### macOS (64Bit) - curl -L https://github.com/jayfk/statuspage/releases/download/0.5.1/statuspage-darwin-64 > /usr/local/bin/statuspage - chmod +x /usr/local/bin/statuspage - -#### Linux (64Bit) - curl -L https://github.com/jayfk/statuspage/releases/download/0.5.1/statuspage-linux-64 > /usr/local/bin/statuspage - chmod +x /usr/local/bin/statuspage +*There are also binaries for macOS and Linux available, see [installation](docs/installation.md) for more. + +Now, create an GitHub API token: -## Create a status page +- Go to your [Personal Access tokens](https://github.com/settings/tokens) page. +- Click on `Generate new token`. +- Make sure to check the `public_repo` and `write:repo_hook` scope. +- Copy the token somewhere safe, you won't be able to see it again once you leave the page. -To create a new status page, run +To create a new status page, run: statuspage create --token= + +You'll be prompted for the name and the systems you want to show a status for. + Name: mystatuspage Systems, eg (Website,API): Website, CDN, API -You'll be prompted for the name and the systems you want to show a status for. +*Please note: name, bla bla bla* + +The command takes a couple of seconds to run. Once ready, it will output links to the issue tracker and your new status page. - - Name: This will be the name of the GitHub repo where your status page is hosted. It will - create a new GitHub repo on your account with that name, so make sure you don't use something - that already exists. - - Systems: The systems you want to show a status for. This can be your website, your API, your - CDN or whatever else you are using. + Create new issues at https://github.com//mystatuspage/issues + Visit your new status page at https://.github.com/mystatuspage/ +Next, you will be asked if you want to automate the update process, so that you don't have to run +the `statuspage update` command whenever you change anything on your repo. -The command takes a couple of seconds to run. Once ready, it will output the URLs to the issue tracker -and your new status page + Set up automation? [y/N]: y - Create new issues at https://github.com//mystatuspage/issues - Visit your new status page at https://.github.com/mystatuspage/ - +If you want use the service, choose `y` and grab a key at the [shop](https://www.statuspage-backend.com). + +If you don't want to use the service, choose `n`. The generator will then print the `statuspage update` +command filled with all the details you need to update your page. + ## Create an issue To create a new issue, go to your newly created repo and click on `New Issue`. -Click on the cog icon at labels on the right. What labels you choose next will tell the generator -about the affected system(s) and the severity. Your system's labels are all black. - -Add a systems label, eg. `Website` and pick a severity eg. `major outage` and add them to the issue. +- Click on the cog icon next to labels on the right. +- Choose the affected systems (black labels) +- Choose a severity label (major outage, degraded performance, investigating) +- Fill in the title, leave a comment and click on `Submit new issue`. -Now, fill in the title, leave a comment and click on `Submit new issue`. +![Add New Issue](docs/new_issue.png) -Go back to your commandline and type: +Now, update your status page. Go back to your commandline and type: statuspage update --token= Name: mystatuspage -This will update your status page and show a *major outage* on your *Website*. - If you change the issue (eg. when you add a new label, create a comment or close the issue), you'll need to run `statuspage update` again. -## Use Organization Account - -In order to create/update a status page for an organization, add the name of the organization to - the `--org` flag, e.g.: - - statuspage create --org=my-org --name=.. - - -Please note: You need to have the proper permissions to create a new repository for the given -organization. - ## Customizing +See [customizing](docs/customizing.md) -**Important:** All customizations have to happen in the `gh-pages` branch. If you are using the -command line, make sure to - - git checkout gh-pages - -or, on the website, select the `gh-pages` branch before editing things. - -### Template - -The template is fully customizable, edit `template.html`. - -### Logo - -Add a `logo.png` to your repo's root and change `template.html` to point to that file. - -### CSS - -CSS is located at `style.css` in the root directory. Just edit it and commit the file. - -### Use a subdomain - -If you want to use your own domain to host your status page, you'll need to create a CNAME file -in your repository and set up a CNAME record pointing to that page with your DNS provider. - -If you have e.g. the domain `mydomain.com`, your GitHub username is `myusername` and you want -your status page to be reachable at `status.mydomain.com` - - -- Create a `CNAME` file in the root of your repository - - status.mydomain.com - -- Go to your DNS provider and create a new CNAME record pointing to your - - - Name Type Value - status CNAME myusername.github.io - -See [Using a custom domain with GitHub Pages](https://help.github.com/articles/using-a-custom-domain-with-github-pages/) -for more info. +## Options +See [options](docs/options.md) diff --git a/docs/customizing.md b/docs/customizing.md new file mode 100644 index 0000000..b50c97a --- /dev/null +++ b/docs/customizing.md @@ -0,0 +1,42 @@ +## Customizing + +**Important:** All customizations have to happen in the `gh-pages` branch. If you are using the +command line, make sure to + + git checkout gh-pages + +or, on the website, select the `gh-pages` branch before editing things. + +### Template + +The template is fully customizable, edit `template.html`. + +### Logo + +Add a `logo.png` to your repo's root and change `template.html` to point to that file. + +### CSS + +CSS is located at `style.css` in the root directory. Just edit it and commit the file. + +### Use a subdomain + +If you want to use your own domain to host your status page, you'll need to create a CNAME file +in your repository and set up a CNAME record pointing to that page with your DNS provider. + +If you have e.g. the domain `mydomain.com`, your GitHub username is `myusername` and you want +your status page to be reachable at `status.mydomain.com` + + +- Create a `CNAME` file in the root of your repository + + status.mydomain.com + +- Go to your DNS provider and create a new CNAME record pointing to your + + + Name Type Value + status CNAME myusername.github.io + +See [Using a custom domain with GitHub Pages](https://help.github.com/articles/using-a-custom-domain-with-github-pages/) +for more info. \ No newline at end of file diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..d467123 --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,15 @@ +# Installation + +## Using pip +The prefered way to install statuspage is with Pythons package manager pip: + + pip install statuspage + +## Binaries +### macOS (64Bit) + curl -L https://github.com/jayfk/statuspage/releases/download/0.6.0/statuspage-darwin-64 > /usr/local/bin/statuspage + chmod +x /usr/local/bin/statuspage + +### Linux (64Bit) + curl -L https://github.com/jayfk/statuspage/releases/download/0.6.0/statuspage-linux-64 > /usr/local/bin/statuspage + chmod +x /usr/local/bin/statuspage \ No newline at end of file diff --git a/docs/new_issue.png b/docs/new_issue.png new file mode 100644 index 0000000..56a4ffa Binary files /dev/null and b/docs/new_issue.png differ diff --git a/docs/options.md b/docs/options.md new file mode 100644 index 0000000..92d55a6 --- /dev/null +++ b/docs/options.md @@ -0,0 +1,22 @@ +# Options + +## Create a private status page + +*Please note: Your Github API token needs the `repo` scope.* + +To create a private status page, set the `--private` flag. + + statuspage create --private --token= + +This will create a private repository, however the GitHub page will be public. + +## Use Organization Account + +*Please note: You need to have the proper permissions to create a new repository for the given +organization.* + +In order to create/update a status page for an organization, add the name of the organization to + the `--org` flag, e.g.: + + statuspage create --org=my-org --name=.. + diff --git a/requirements/base.txt b/requirements/base.txt index 1418a26..d61e98d 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,4 +1,5 @@ pygithub-redux==1.30.0 click==6.6 jinja2==2.8 -tqdm==4.8.1 \ No newline at end of file +tqdm==4.8.1 +requests \ No newline at end of file diff --git a/setup.py b/setup.py index 3765ca4..2ec8946 100644 --- a/setup.py +++ b/setup.py @@ -14,10 +14,11 @@ history = history_file.read() requirements = [ - 'pygithub-redux>=1.30.0', + 'pygithub', 'click', 'jinja2', 'tqdm', + 'requests' ] long_description = readme + '\n\n' + history diff --git a/statuspage/statuspage.py b/statuspage/statuspage.py index 59658f5..e6ce457 100644 --- a/statuspage/statuspage.py +++ b/statuspage/statuspage.py @@ -5,7 +5,8 @@ import hashlib import base64 from datetime import datetime, timedelta - +import requests +from requests.exceptions import ConnectionError from github import Github, UnknownObjectException import click from jinja2 import Template @@ -48,8 +49,9 @@ def cli(): # pragma: no cover @click.option('--token', prompt='GitHub API Token', help='') @click.option('--org', help='GitHub Organization', default=False) @click.option('--systems', prompt='Systems, eg (Website,API)', help='') -def create(token, name, systems, org): - run_create(name=name, token=token, systems=systems, org=org) +@click.option('--private/--public', default=False) +def create(token, name, systems, org, private): + run_create(name=name, token=token, systems=systems, org=org, private=private) @cli.command() @@ -59,6 +61,14 @@ def create(token, name, systems, org): def update(name, token, org): run_update(name=name, token=token, org=org) +@cli.command() +@click.option('--name', prompt='Name', help='') +@click.option('--org', help='GitHub Organization', default=False) +@click.option('--token', prompt='GitHub API Token', help='') +@click.option('--key', prompt='Key', help='', default=None) +def automate(name, token, org, key): + run_automate(name=name, token=token, org=org, key=key) + def run_update(name, token, org): click.echo("Generating..") @@ -114,7 +124,7 @@ def run_update(name, token, org): ) -def run_create(name, token, systems, org): +def run_create(name, token, systems, org, private): gh = Github(token) if org: @@ -123,7 +133,7 @@ def run_create(name, token, systems, org): entity = gh.get_user() # create the repo - repo = entity.create_repo(name=name) + repo = entity.create_repo(name=name, private=private) # get all labels an delete them for label in tqdm(list(repo.get_labels()), "Deleting initial labels"): @@ -168,7 +178,7 @@ def run_create(name, token, systems, org): # run an initial update to add content to the index run_update(token=token, name=name, org=org) - click.echo("Create new issues at https://github.com/{login}/{name}/issues".format( + click.echo("\nCreate new issues at https://github.com/{login}/{name}/issues".format( login=entity.login, name=name )) @@ -177,14 +187,52 @@ def run_create(name, token, systems, org): name=name )) - click.echo("") - click.echo("###############################################################################") - click.echo("# IMPORTANT: Whenever you add or close an issue you have to run the update #") - click.echo("# command to show the changes reflected on your status page. #") - click.echo("# Here's a one-off command for this repo to safe it somewhere safe: #") - click.echo("# statuspage update --name={name} --token={token} {org}".format( + click.secho("\nYour status page is now set up and ready!\n", fg="green") + click.echo("Please note: You need to run the 'statuspage update' command whenever you update or create an issue.\n") + click.echo("There is a small service available ($39/year) that does that " + "automatically for you.") + if click.confirm("Set up automation?"): + click.secho("\nAwesome!\n\n", fg="green") + run_automate(name=name, token=token, org=org) + else: + click.echo("\nIn order to update this status page, run the following command:") + click.echo("statuspage update --name={name} --token={token} {org}".format( + name=name, token=token, org="--org=" + entity.login if org else "")) + click.echo("") + click.echo("In case you want to set up automation later, run:") + click.echo("statuspage automate --name={name} --token={token} {org}".format( name=name, token=token, org="--org=" + entity.login if org else "")) - click.echo("###############################################################################") + + +def run_automate(name, token, org, key=None): + + if not key: + click.echo("If you don't have a key to use the backend service, go to " + "https://www.statuspage-backend.com to purchase one.\n") + key = click.prompt('Key') + + data = { + "name": name, + "token": token, + "org": org, + "key": key + } + try: + r = requests.post("https://www.statuspage-backend.com/register", json=data) + except ConnectionError: + click.secho("The backend server is not available. Please try again later.", fg="red") + return + try: + data = r.json() + except ValueError: + click.secho("There was an error communicating with the backend server.", fg="red") + return + + if not data.get("success", False): + click.secho("Error: {}".format(data.get("error", "Unknown Error.")), fg="red") + return + + click.secho("Automation activated.", fg="green") def iter_systems(labels):