Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
oxplot committed Aug 29, 2019
0 parents commit cf64f61
Show file tree
Hide file tree
Showing 26 changed files with 55,560 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
github: oxplot
patreon: oxplot
open_collective: oxplot
ko_fi: oxplot
issuehunt: oxplot
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
test.db
config.*
runsheet-*-*
data/prod_static.go
license_file.txt
154 changes: 154 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
Welcome to Runsheet V2 (RsV2). This guide will help you understand how
to setup this software and how it works under the hood.

## What is RsV2?

RsV2 is a second iteration, re-written from scratch, of an original
runsheet script which given a set of tasks and their dependencies,
scheduled them in the most time optimized arrangement and provided a UI
to help tracking the progress of those tasks. You can think of it as a
simpler, collaborative and more focused Gantt chart with live task
status updates.

![GitHub Logo](example.gif)

## What can I use it for?

RsV2 can be used to track a weekend roll out for instance. You have a
bunch of tasks that must be done in a certain order, such as putting up
a maintenance notice, taking systems down, upgrading and testing. RsV2’s
real advantage comes into play when multiple people are involved and
prompt starting and finishing of tasks is of importance.

## Features

* RDBMS backed storage for tasks and runsheets
* Multiple runsheets per server
* Lax requirements on how the tasks and runsheets are stored
* Completely reactive UI with live collaborative features.
* Automatic time divisions based on total run time
* Support for variety of database backends
* Start time and “Behind Schedule” notifications
* Single Go binary for ease of deployment (not static yet!)
* Multi-platform support

## Build & Install

```
go generate
go install -tags prod
```

## Quick Demo

Run `runsheet -config example-config.json` and open your browser at
http://localhost:8080

## Setup

### Config

RsV2 is configured using a file named `config.yaml` which must be placed
in either: same directory as the executable; `/etc/runsheet`;
`$HOME/.runsheet` or their equivalent locations on other platforms.

`config.yaml` has the following format:

```yaml
# Optional
Listen: :8080

# A comment starting with hash character
ConnectionUrl: dbdriver://…
RunsheetsSql: select * from …
```
`Listen` specifies which interface and port number to listen for
connections to serve the UI. `:8080` is the default and means: serve on
port `8080` on all interfaces. To limit to localhost for instance, you
can use `127.0.0.1:8080`.

`ConnectionUrl` specifies which DB driver to use and what parameters to
pass, such as username, password, host and others. Following are
examples of `ConnectionUrl`s for various supported databases:

```yaml
-# Oracle - Oracle Instant Client Basic is required
-ConnectionUrl: goracle://username/password@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)(HOST=host.name.com)(PORT=1530)))(CONNECT_DATA=(SERVICE_NAME=MY_SERVICE_NAME)))
# Microsoft SQL
ConnectionUrl: sqlserver://username:password@host.name.com?database=my_db
# SQLite
ConnectionUrl: sqlite3://./relative/path/to/test.db
```

`RunsheetsSql` is a query or otherwise any valid SQL for the given
database that retrieves the list of runsheets.

### Runsheet

A **runsheet** is simply a list of tasks and their dependencies.
`RunsheetsSql` must return the following columns (some optional):

* `id` (string): ID of the runsheet
* `name` (string)(optional): name or title of the runsheet — supports
markdown
* `description` (string)(optional): runsheet description — supports
markdown
* `connection_url` (string): Same format as `ConnectionUrl` above but
for this runsheet
* `tasks_sql` (string): SQL to get the list of tasks
* `update_sql` (string): SQL to update status of a task
* `start_time` (string)(optional): start time and date of the first task

All column names are case sensitive and `RunsheetsSql` must not retrieve
any column that is not specified above.

`tasks_sql` is a query or otherwise any valid SQL for the given database
that retrieves the list of tasks for the corresponding runsheet.

### Task

A **task** is an undertaking assigned to a specific resource (person)
and has defined duration in minutes. It may also have dependencies on
other tasks. `tasks_sql` must return the following columns (some
optional):

* `id` (string): Task ID
* `name` (string)(optional): Task name — supports markdown
* `description` (string)(optional): Task description — supports markdown
* `assignee` (string): Name of assignee
* `duration` (number): Task duration in minutes
* `status` (string): Task status which must be one of `idle`, `ongoing`
or `done`
* `dependees` (string): List of task IDs this task depends on, each
separated by `|`

All column names are case sensitive and `tasks_sql` must not retrieve
any column that is not specified above.

As an example of `dependees`: say we have three tasks with IDs of `A`,
`B` and `C`. If `C` depends on `A` and `B`, then `C`’s record will have
`A|B` in the `dependees` column.

`update_sql` is a valid SQL for the given database which updates status
for a given task. All occurrences of `{{task}}` inside `update_sql` will
be replaced with ID of the task whose status is being updated. All
occurences of `{{status}}` inside `update_sql` will be replaced with the
new status of the task. Below is an example:

```
update tasks set "status" = '{{status}}' where "id" = '{{task}}'
```

Note that no DB aware substitutions are done. Thus you’re required to
quote literal string values in your SQL.

`start_time` is a string representation of the start time and date the
earliest task in the runsheet is to be stamped with. Regular interval
timestamps are shown on the left side of a runsheet UI. You may use any
format supported by Javascript. Following is recommended: `2018-10-25
18:10:00 EST` where `EST` defines the time zone, in this case Australian
Eastern Standard Time. You may use an offset instead, such as `+11:00`
or [other abbreviations](https://www.timeanddate.com/time/zones/).
23 changes: 23 additions & 0 deletions assets_generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// +build ignore

package main

import (
"log"

"github.com/shurcooL/vfsgen"

"github.com/oxplot/runsheet/data"
)

func main() {
err := vfsgen.Generate(data.StaticAssets, vfsgen.Options{
Filename: "data/prod_static.go",
PackageName: "data",
BuildTags: "prod",
VariableName: "StaticAssets",
})
if err != nil {
log.Fatalln(err)
}
}
6 changes: 6 additions & 0 deletions contrib/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM debian:experimental

RUN apt-get update -y && apt-get -y install golang-1.12 mingw-w64

ENV GOPATH=/go
ENV PATH=/usr/lib/go-1.12/bin:$PATH
3 changes: 3 additions & 0 deletions contrib/build
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

docker build -t go-win .
9 changes: 9 additions & 0 deletions data/dev_static.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// +build !prod

package data

import (
"net/http"
)

var StaticAssets = http.Dir("static")
23 changes: 23 additions & 0 deletions data/spa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package data

var SpaHtml = []byte(`<!doctype html>
<html>
<head>
<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons' rel="stylesheet">
<link href="/static/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<link href="/static/main.css" rel="stylesheet">
<body>
<div id="app" v-cloak><router-view></router-view></div>
<script src="/static/vue.js"></script>
<script src="/static/vue-router.js"></script>
<script src="/static/vue-meta.js"></script>
<script src="/static/vue-markdown.js"></script>
<script src="/static/vuetify.js"></script>
<script src="/static/main.js"></script>
</body>
</html>`)
5 changes: 5 additions & 0 deletions example-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"Listen": ":8080",
"ConnectionUrl": "sqlite3://./example-db",
"RunsheetsSql": "select id, connection_url, tasks_sql, update_sql from sheets"
}
Binary file added example-db
Binary file not shown.
Binary file added example.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module github.com/oxplot/runsheet

go 1.12

require (
github.com/denisenkom/go-mssqldb v0.0.0-20190820223206-44cdfe8d8ba9
github.com/go-sql-driver/mysql v1.4.1
github.com/google/go-cmp v0.3.1 // indirect
github.com/gorilla/mux v1.7.3
github.com/jmoiron/sqlx v1.2.0
github.com/lib/pq v1.2.0
github.com/looplab/tarjan v0.0.0-20161115091335-9cc6d6cebfb5
github.com/mattn/go-sqlite3 v1.11.0
gopkg.in/goracle.v2 v2.19.0
)
Loading

0 comments on commit cf64f61

Please sign in to comment.