├── .github ├── CODEOWNERS └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .mergify.yml ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── assets └── img │ └── logo.png ├── config.json ├── config.toml ├── docker-compose.yml ├── fixtures ├── create.json ├── delete.json ├── issue_comment.json ├── issues.json ├── label.json ├── pull_request.json ├── pull_request_review.json ├── pull_request_review_comment.json ├── push.json ├── status.json └── watch.json ├── go.mod ├── go.sum ├── hamster.go ├── internal └── app │ ├── controller │ ├── auth.go │ ├── health_check.go │ ├── home.go │ ├── listener.go │ └── login.go │ ├── event │ ├── check_run.go │ ├── check_suite.go │ ├── command.go │ ├── commit_comment.go │ ├── create.go │ ├── delete.go │ ├── deployment.go │ ├── deployment_status.go │ ├── fork.go │ ├── github_app_authorization.go │ ├── gollum.go │ ├── installation.go │ ├── installation_repositories.go │ ├── issue_comment.go │ ├── issue_comment_test.go │ ├── issues.go │ ├── issues_test.go │ ├── label.go │ ├── marketplace_purchase.go │ ├── member.go │ ├── membership.go │ ├── milestone.go │ ├── org_block.go │ ├── organization.go │ ├── page_build.go │ ├── project.go │ ├── project_card.go │ ├── project_column.go │ ├── public.go │ ├── pull_request.go │ ├── pull_request_review.go │ ├── pull_request_review_comment.go │ ├── push.go │ ├── raw.go │ ├── release.go │ ├── repository.go │ ├── repository_import.go │ ├── repository_vulnerability_alert.go │ ├── status.go │ ├── status_test.go │ ├── team.go │ ├── team_add.go │ ├── watch.go │ └── watch_test.go │ ├── listener │ ├── action.go │ ├── command.go │ └── parser.go │ ├── pkg │ ├── github │ │ ├── api.go │ │ └── oauth.go │ ├── logger │ │ └── logger.go │ └── utils │ │ ├── configs.go │ │ └── http.go │ ├── response │ ├── annotation.go │ ├── check_run.go │ ├── created_comment.go │ └── label.go │ └── sender │ ├── check_run.go │ ├── comment.go │ └── label.go ├── plugin └── base.go ├── renovate.json ├── templates ├── index.tmpl └── login.tmpl └── var └── logs └── .gitignore /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Docs: https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners 2 | * @clivern 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **Development or production environment** 11 | - OS: [e.g. Ubuntu 18.04] 12 | - Go 1.11 13 | 14 | **Additional context** 15 | Add any other context about the problem here. 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Additional context** 14 | Add any other context or screenshots about the feature request here. 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Config file 15 | config.dist.json 16 | 17 | # App build 18 | hamster 19 | 20 | # Ignore vendor and run dep ensure 21 | vendor -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | pull_request_rules: 3 | - 4 | actions: 5 | merge: 6 | method: squash 7 | conditions: 8 | - author!=Clivern 9 | - approved-reviews-by=Clivern 10 | - label=merge 11 | - status-success=Travis CI - Pull Request 12 | - status-success=Travis CI - Branch 13 | name: "Automatic Merge 🚀" 14 | - 15 | actions: 16 | merge: 17 | method: merge 18 | conditions: 19 | - author=Clivern 20 | - label=merge 21 | name: "Automatic Merge 🚀" 22 | - 23 | actions: 24 | merge: 25 | method: squash 26 | conditions: 27 | - "author=renovate[bot]" 28 | - label=merge 29 | - status-success=Travis CI - Pull Request 30 | - status-success=Travis CI - Branch 31 | name: "Automatic Merge for Renovate PRs 🚀" 32 | - 33 | actions: 34 | comment: 35 | message: "Nice! PR merged successfully." 36 | conditions: 37 | - merged 38 | name: "Merge Done 🚀" 39 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.9.x 5 | - 1.10.x 6 | - 1.11.x 7 | - 1.13.x 8 | - master 9 | 10 | env: 11 | - GO111MODULE=on 12 | 13 | install: true 14 | 15 | # Fix this by renaming the directory before testing. 16 | # https://github.com/travis-ci/travis-ci/issues/4573 17 | script: 18 | - export GOBIN="$GOPATH/bin" 19 | - export PATH="$PATH:$GOBIN" 20 | # Fix dir names 21 | - cd $GOPATH/src/github.com/ 22 | - mv Clivern/Hamster Clivern/hamster 23 | - mv Clivern clivern 24 | - cd clivern/hamster 25 | # Config & execute ci tasks 26 | - make install_revive 27 | - make ci 28 | 29 | matrix: 30 | include: 31 | allow_failures: 32 | - go: 1.9.x 33 | - go: 1.10.x 34 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at hello@clivern.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | - With issues: 4 | - Use the search tool before opening a new issue. 5 | - Please provide source code and commit sha if you found a bug. 6 | - Review existing issues and provide feedback or react to them. 7 | 8 | - With pull requests: 9 | - Open your pull request against `master` 10 | - Your pull request should have no more than two commits, if not you should squash them. 11 | - It should pass all tests in the available continuous integrations systems such as TravisCI. 12 | - You should add/modify tests to cover your proposed code changes. 13 | - If your pull request contains a new feature, please document it on the README. 14 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.18.3 2 | 3 | RUN mkdir -p /go/src/github.com/clivern/hamster/ 4 | 5 | ADD . /go/src/github.com/clivern/hamster/ 6 | 7 | WORKDIR /go/src/github.com/clivern/hamster 8 | 9 | RUN go build -o hamster hamster.go 10 | 11 | EXPOSE 8080 12 | 13 | CMD ["./hamster"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 A. F 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GO ?= go 2 | GOFMT ?= $(GO)fmt 3 | pkgs = ./... 4 | 5 | 6 | ## install_revive: Install revive for linting. 7 | install_revive: 8 | @echo ">> Install revive" 9 | $(GO) get github.com/mgechev/revive 10 | 11 | 12 | ## style: Check code style. 13 | style: 14 | @echo ">> checking code style" 15 | @fmtRes=$$($(GOFMT) -d $$(find . -path ./vendor -prune -o -name '*.go' -print)); \ 16 | if [ -n "$${fmtRes}" ]; then \ 17 | echo "gofmt checking failed!"; echo "$${fmtRes}"; echo; \ 18 | echo "Please ensure you are using $$($(GO) version) for formatting code."; \ 19 | exit 1; \ 20 | fi 21 | 22 | 23 | ## check_license: Check if license header on all files. 24 | check_license: 25 | @echo ">> checking license header" 26 | @licRes=$$(for file in $$(find . -type f -iname '*.go' ! -path './vendor/*') ; do \ 27 | awk 'NR<=3' $$file | grep -Eq "(Copyright|generated|GENERATED)" || echo $$file; \ 28 | done); \ 29 | if [ -n "$${licRes}" ]; then \ 30 | echo "license header checking failed:"; echo "$${licRes}"; \ 31 | exit 1; \ 32 | fi 33 | 34 | 35 | ## test_short: Run test cases with short flag. 36 | test_short: 37 | @echo ">> running short tests" 38 | $(GO) test -short $(pkgs) 39 | 40 | 41 | ## test: Run test cases. 42 | test: 43 | @echo ">> running all tests" 44 | $(GO) test -race $(pkgs) 45 | 46 | 47 | ## lint: Lint the code. 48 | lint: 49 | @echo ">> Lint all files" 50 | revive -config config.toml -exclude vendor/... -formatter friendly ./... 51 | 52 | 53 | ## format: Format the code. 54 | format: 55 | @echo ">> formatting code" 56 | $(GO) fmt $(pkgs) 57 | 58 | 59 | ## vet: Examines source code and reports suspicious constructs. 60 | vet: 61 | @echo ">> vetting code" 62 | $(GO) vet $(pkgs) 63 | 64 | 65 | ## dev_run: Run the application main file. 66 | dev_run: 67 | $(GO) run hamster.go 68 | 69 | 70 | ## prod_run: Build and run the application. 71 | prod_run: build 72 | ./hamster 73 | 74 | 75 | ## build: Build the application. 76 | build: 77 | rm -f hamster 78 | $(GO) build -o hamster hamster.go 79 | 80 | 81 | ## ci: Run all CI tests. 82 | ci: style check_license test vet lint 83 | @echo "\n==> All quality checks passed" 84 | 85 | 86 | help: Makefile 87 | @echo 88 | @echo " Choose a command run in Hamster:" 89 | @echo 90 | @sed -n 's/^##//p' $< | column -t -s ':' | sed -e 's/^/ /' 91 | @echo 92 | 93 | .PHONY: help -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | - With pull requests: 2 | - Open your pull request against `master` 3 | - Your pull request should have no more than two commits, if not you should squash them. 4 | - It should pass all tests in the available continuous integrations systems such as TravisCI. 5 | - You should add/modify tests to cover your proposed code changes. 6 | - If your pull request contains a new feature, please document it on the README. 7 | -------------------------------------------------------------------------------- /assets/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Clivern/Hamster/321905c488353d86346aea16b83a9eea48c86d1e/assets/img/logo.png -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "app_mode": "dev", 3 | "app_port": "8080", 4 | "app_log_level": "info", 5 | "github_token": "..", 6 | "github_webhook_secret": "..", 7 | "repository_author": "..", 8 | "repository_name": "..", 9 | "app_domain": "example.com", 10 | "github_app_client_id": "..", 11 | "github_app_redirect_uri": "..", 12 | "github_app_allow_signup": "false", 13 | "github_app_scope": "..", 14 | "github_app_client_secret": ".." 15 | } -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | ignoreGeneratedHeader = false 2 | severity = "warning" 3 | confidence = 0.8 4 | errorCode = 0 5 | warningCode = 0 6 | 7 | [rule.blank-imports] 8 | [rule.context-as-argument] 9 | [rule.context-keys-type] 10 | [rule.dot-imports] 11 | [rule.error-return] 12 | [rule.error-strings] 13 | [rule.error-naming] 14 | [rule.exported] 15 | [rule.if-return] 16 | [rule.increment-decrement] 17 | [rule.var-naming] 18 | [rule.var-declaration] 19 | [rule.package-comments] 20 | [rule.range] 21 | [rule.receiver-naming] 22 | [rule.time-naming] 23 | [rule.unexported-return] 24 | [rule.indent-error-flow] 25 | [rule.errorf] 26 | [rule.empty-block] 27 | [rule.superfluous-else] 28 | [rule.unused-parameter] 29 | [rule.unreachable-code] 30 | [rule.redefines-builtin-id] -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | db: 4 | image: "mysql:8.0" 5 | environment: 6 | - MYSQL_ROOT_PASSWORD=root 7 | - MYSQL_DATABASE=hamster 8 | - MYSQL_USER=hamster 9 | - MYSQL_PASSWORD=secret 10 | - MYSQL_ALLOW_EMPTY_PASSWORD=yes 11 | restart: always 12 | healthcheck: 13 | test: '/usr/bin/mysql --user=hamster --password=secret --execute "SHOW DATABASES;"' 14 | interval: 3s 15 | timeout: 1s 16 | retries: 5 17 | web: 18 | image: "clivern_hamster:3.1.0" 19 | build: . 20 | command: './hamster' 21 | ports: 22 | - "8080:8080" 23 | depends_on: 24 | - db 25 | volumes: 26 | - './var:/go/src/github.com/clivern/hamster/var' 27 | restart: always 28 | environment: 29 | - GithubToken=YourTokenHere 30 | - GithubWebhookSecret=YourSecretHere 31 | - RepositoryAuthor=Clivern 32 | - RepositoryName=Hamster 33 | - AppMode=prod 34 | - AppPort=8080 35 | - AppLogLevel=info 36 | - GithubAppClientID=ValueHere 37 | - GithubAppRedirectURI=ValueHere 38 | - GithubAppAllowSignup=true 39 | - GithubAppScope=ValueHere 40 | - GithubAppClientSecret=ValueHere 41 | - AppDomain=example.com -------------------------------------------------------------------------------- /fixtures/create.json: -------------------------------------------------------------------------------- 1 | { 2 | "ref": "feature/new-events", 3 | "ref_type": "branch", 4 | "master_branch": "master", 5 | "description": ":rat: A Bot Toolkit for Github!", 6 | "pusher_type": "user", 7 | "repository": { 8 | "id": 150013651, 9 | "node_id": "MDEwOlJlcG9zaXRvcnkxNTAwMTM2NTE=", 10 | "name": "Hamster", 11 | "full_name": "Clivern/Hamster", 12 | "private": false, 13 | "owner": { 14 | "login": "Clivern", 15 | "id": 1634427, 16 | "node_id": "MDQ6VXNlcjE2MzQ0Mjc=", 17 | "avatar_url": "https://avatars3.githubusercontent.com/u/1634427?v=4", 18 | "gravatar_id": "", 19 | "url": "https://api.github.com/users/Clivern", 20 | "html_url": "https://github.com/Clivern", 21 | "followers_url": "https://api.github.com/users/Clivern/followers", 22 | "following_url": "https://api.github.com/users/Clivern/following{/other_user}", 23 | "gists_url": "https://api.github.com/users/Clivern/gists{/gist_id}", 24 | "starred_url": "https://api.github.com/users/Clivern/starred{/owner}{/repo}", 25 | "subscriptions_url": "https://api.github.com/users/Clivern/subscriptions", 26 | "organizations_url": "https://api.github.com/users/Clivern/orgs", 27 | "repos_url": "https://api.github.com/users/Clivern/repos", 28 | "events_url": "https://api.github.com/users/Clivern/events{/privacy}", 29 | "received_events_url": "https://api.github.com/users/Clivern/received_events", 30 | "type": "User", 31 | "site_admin": false 32 | }, 33 | "html_url": "https://github.com/Clivern/Hamster", 34 | "description": ":rat: A Bot Toolkit for Github!", 35 | "fork": false, 36 | "url": "https://api.github.com/repos/Clivern/Hamster", 37 | "forks_url": "https://api.github.com/repos/Clivern/Hamster/forks", 38 | "keys_url": "https://api.github.com/repos/Clivern/Hamster/keys{/key_id}", 39 | "collaborators_url": "https://api.github.com/repos/Clivern/Hamster/collaborators{/collaborator}", 40 | "teams_url": "https://api.github.com/repos/Clivern/Hamster/teams", 41 | "hooks_url": "https://api.github.com/repos/Clivern/Hamster/hooks", 42 | "issue_events_url": "https://api.github.com/repos/Clivern/Hamster/issues/events{/number}", 43 | "events_url": "https://api.github.com/repos/Clivern/Hamster/events", 44 | "assignees_url": "https://api.github.com/repos/Clivern/Hamster/assignees{/user}", 45 | "branches_url": "https://api.github.com/repos/Clivern/Hamster/branches{/branch}", 46 | "tags_url": "https://api.github.com/repos/Clivern/Hamster/tags", 47 | "blobs_url": "https://api.github.com/repos/Clivern/Hamster/git/blobs{/sha}", 48 | "git_tags_url": "https://api.github.com/repos/Clivern/Hamster/git/tags{/sha}", 49 | "git_refs_url": "https://api.github.com/repos/Clivern/Hamster/git/refs{/sha}", 50 | "trees_url": "https://api.github.com/repos/Clivern/Hamster/git/trees{/sha}", 51 | "statuses_url": "https://api.github.com/repos/Clivern/Hamster/statuses/{sha}", 52 | "languages_url": "https://api.github.com/repos/Clivern/Hamster/languages", 53 | "stargazers_url": "https://api.github.com/repos/Clivern/Hamster/stargazers", 54 | "contributors_url": "https://api.github.com/repos/Clivern/Hamster/contributors", 55 | "subscribers_url": "https://api.github.com/repos/Clivern/Hamster/subscribers", 56 | "subscription_url": "https://api.github.com/repos/Clivern/Hamster/subscription", 57 | "commits_url": "https://api.github.com/repos/Clivern/Hamster/commits{/sha}", 58 | "git_commits_url": "https://api.github.com/repos/Clivern/Hamster/git/commits{/sha}", 59 | "comments_url": "https://api.github.com/repos/Clivern/Hamster/comments{/number}", 60 | "issue_comment_url": "https://api.github.com/repos/Clivern/Hamster/issues/comments{/number}", 61 | "contents_url": "https://api.github.com/repos/Clivern/Hamster/contents/{+path}", 62 | "compare_url": "https://api.github.com/repos/Clivern/Hamster/compare/{base}...{head}", 63 | "merges_url": "https://api.github.com/repos/Clivern/Hamster/merges", 64 | "archive_url": "https://api.github.com/repos/Clivern/Hamster/{archive_format}{/ref}", 65 | "downloads_url": "https://api.github.com/repos/Clivern/Hamster/downloads", 66 | "issues_url": "https://api.github.com/repos/Clivern/Hamster/issues{/number}", 67 | "pulls_url": "https://api.github.com/repos/Clivern/Hamster/pulls{/number}", 68 | "milestones_url": "https://api.github.com/repos/Clivern/Hamster/milestones{/number}", 69 | "notifications_url": "https://api.github.com/repos/Clivern/Hamster/notifications{?since,all,participating}", 70 | "labels_url": "https://api.github.com/repos/Clivern/Hamster/labels{/name}", 71 | "releases_url": "https://api.github.com/repos/Clivern/Hamster/releases{/id}", 72 | "deployments_url": "https://api.github.com/repos/Clivern/Hamster/deployments", 73 | "created_at": "2018-09-23T18:33:43Z", 74 | "updated_at": "2018-10-04T11:45:56Z", 75 | "pushed_at": "2018-10-04T20:19:57Z", 76 | "git_url": "git://github.com/Clivern/Hamster.git", 77 | "ssh_url": "git@github.com:Clivern/Hamster.git", 78 | "clone_url": "https://github.com/Clivern/Hamster.git", 79 | "svn_url": "https://github.com/Clivern/Hamster", 80 | "homepage": "", 81 | "size": 1397, 82 | "stargazers_count": 0, 83 | "watchers_count": 0, 84 | "language": "Go", 85 | "has_issues": true, 86 | "has_projects": true, 87 | "has_downloads": true, 88 | "has_wiki": true, 89 | "has_pages": false, 90 | "forks_count": 0, 91 | "mirror_url": null, 92 | "archived": false, 93 | "open_issues_count": 2, 94 | "license": { 95 | "key": "mit", 96 | "name": "MIT License", 97 | "spdx_id": "MIT", 98 | "url": "https://api.github.com/licenses/mit", 99 | "node_id": "MDc6TGljZW5zZTEz" 100 | }, 101 | "forks": 0, 102 | "open_issues": 2, 103 | "watchers": 0, 104 | "default_branch": "master" 105 | }, 106 | "sender": { 107 | "login": "Clivern", 108 | "id": 1634427, 109 | "node_id": "MDQ6VXNlcjE2MzQ0Mjc=", 110 | "avatar_url": "https://avatars3.githubusercontent.com/u/1634427?v=4", 111 | "gravatar_id": "", 112 | "url": "https://api.github.com/users/Clivern", 113 | "html_url": "https://github.com/Clivern", 114 | "followers_url": "https://api.github.com/users/Clivern/followers", 115 | "following_url": "https://api.github.com/users/Clivern/following{/other_user}", 116 | "gists_url": "https://api.github.com/users/Clivern/gists{/gist_id}", 117 | "starred_url": "https://api.github.com/users/Clivern/starred{/owner}{/repo}", 118 | "subscriptions_url": "https://api.github.com/users/Clivern/subscriptions", 119 | "organizations_url": "https://api.github.com/users/Clivern/orgs", 120 | "repos_url": "https://api.github.com/users/Clivern/repos", 121 | "events_url": "https://api.github.com/users/Clivern/events{/privacy}", 122 | "received_events_url": "https://api.github.com/users/Clivern/received_events", 123 | "type": "User", 124 | "site_admin": false 125 | } 126 | } -------------------------------------------------------------------------------- /fixtures/delete.json: -------------------------------------------------------------------------------- 1 | { 2 | "ref": "feature/test", 3 | "ref_type": "branch", 4 | "pusher_type": "user", 5 | "repository": { 6 | "id": 150013651, 7 | "node_id": "MDEwOlJlcG9zaXRvcnkxNTAwMTM2NTE=", 8 | "name": "Hamster", 9 | "full_name": "Clivern/Hamster", 10 | "private": false, 11 | "owner": { 12 | "login": "Clivern", 13 | "id": 1634427, 14 | "node_id": "MDQ6VXNlcjE2MzQ0Mjc=", 15 | "avatar_url": "https://avatars3.githubusercontent.com/u/1634427?v=4", 16 | "gravatar_id": "", 17 | "url": "https://api.github.com/users/Clivern", 18 | "html_url": "https://github.com/Clivern", 19 | "followers_url": "https://api.github.com/users/Clivern/followers", 20 | "following_url": "https://api.github.com/users/Clivern/following{/other_user}", 21 | "gists_url": "https://api.github.com/users/Clivern/gists{/gist_id}", 22 | "starred_url": "https://api.github.com/users/Clivern/starred{/owner}{/repo}", 23 | "subscriptions_url": "https://api.github.com/users/Clivern/subscriptions", 24 | "organizations_url": "https://api.github.com/users/Clivern/orgs", 25 | "repos_url": "https://api.github.com/users/Clivern/repos", 26 | "events_url": "https://api.github.com/users/Clivern/events{/privacy}", 27 | "received_events_url": "https://api.github.com/users/Clivern/received_events", 28 | "type": "User", 29 | "site_admin": false 30 | }, 31 | "html_url": "https://github.com/Clivern/Hamster", 32 | "description": ":rat: A Bot Toolkit for Github!", 33 | "fork": false, 34 | "url": "https://api.github.com/repos/Clivern/Hamster", 35 | "forks_url": "https://api.github.com/repos/Clivern/Hamster/forks", 36 | "keys_url": "https://api.github.com/repos/Clivern/Hamster/keys{/key_id}", 37 | "collaborators_url": "https://api.github.com/repos/Clivern/Hamster/collaborators{/collaborator}", 38 | "teams_url": "https://api.github.com/repos/Clivern/Hamster/teams", 39 | "hooks_url": "https://api.github.com/repos/Clivern/Hamster/hooks", 40 | "issue_events_url": "https://api.github.com/repos/Clivern/Hamster/issues/events{/number}", 41 | "events_url": "https://api.github.com/repos/Clivern/Hamster/events", 42 | "assignees_url": "https://api.github.com/repos/Clivern/Hamster/assignees{/user}", 43 | "branches_url": "https://api.github.com/repos/Clivern/Hamster/branches{/branch}", 44 | "tags_url": "https://api.github.com/repos/Clivern/Hamster/tags", 45 | "blobs_url": "https://api.github.com/repos/Clivern/Hamster/git/blobs{/sha}", 46 | "git_tags_url": "https://api.github.com/repos/Clivern/Hamster/git/tags{/sha}", 47 | "git_refs_url": "https://api.github.com/repos/Clivern/Hamster/git/refs{/sha}", 48 | "trees_url": "https://api.github.com/repos/Clivern/Hamster/git/trees{/sha}", 49 | "statuses_url": "https://api.github.com/repos/Clivern/Hamster/statuses/{sha}", 50 | "languages_url": "https://api.github.com/repos/Clivern/Hamster/languages", 51 | "stargazers_url": "https://api.github.com/repos/Clivern/Hamster/stargazers", 52 | "contributors_url": "https://api.github.com/repos/Clivern/Hamster/contributors", 53 | "subscribers_url": "https://api.github.com/repos/Clivern/Hamster/subscribers", 54 | "subscription_url": "https://api.github.com/repos/Clivern/Hamster/subscription", 55 | "commits_url": "https://api.github.com/repos/Clivern/Hamster/commits{/sha}", 56 | "git_commits_url": "https://api.github.com/repos/Clivern/Hamster/git/commits{/sha}", 57 | "comments_url": "https://api.github.com/repos/Clivern/Hamster/comments{/number}", 58 | "issue_comment_url": "https://api.github.com/repos/Clivern/Hamster/issues/comments{/number}", 59 | "contents_url": "https://api.github.com/repos/Clivern/Hamster/contents/{+path}", 60 | "compare_url": "https://api.github.com/repos/Clivern/Hamster/compare/{base}...{head}", 61 | "merges_url": "https://api.github.com/repos/Clivern/Hamster/merges", 62 | "archive_url": "https://api.github.com/repos/Clivern/Hamster/{archive_format}{/ref}", 63 | "downloads_url": "https://api.github.com/repos/Clivern/Hamster/downloads", 64 | "issues_url": "https://api.github.com/repos/Clivern/Hamster/issues{/number}", 65 | "pulls_url": "https://api.github.com/repos/Clivern/Hamster/pulls{/number}", 66 | "milestones_url": "https://api.github.com/repos/Clivern/Hamster/milestones{/number}", 67 | "notifications_url": "https://api.github.com/repos/Clivern/Hamster/notifications{?since,all,participating}", 68 | "labels_url": "https://api.github.com/repos/Clivern/Hamster/labels{/name}", 69 | "releases_url": "https://api.github.com/repos/Clivern/Hamster/releases{/id}", 70 | "deployments_url": "https://api.github.com/repos/Clivern/Hamster/deployments", 71 | "created_at": "2018-09-23T18:33:43Z", 72 | "updated_at": "2018-10-04T11:45:56Z", 73 | "pushed_at": "2018-10-06T19:58:31Z", 74 | "git_url": "git://github.com/Clivern/Hamster.git", 75 | "ssh_url": "git@github.com:Clivern/Hamster.git", 76 | "clone_url": "https://github.com/Clivern/Hamster.git", 77 | "svn_url": "https://github.com/Clivern/Hamster", 78 | "homepage": "", 79 | "size": 1422, 80 | "stargazers_count": 0, 81 | "watchers_count": 0, 82 | "language": "Go", 83 | "has_issues": true, 84 | "has_projects": true, 85 | "has_downloads": true, 86 | "has_wiki": true, 87 | "has_pages": false, 88 | "forks_count": 0, 89 | "mirror_url": null, 90 | "archived": false, 91 | "open_issues_count": 2, 92 | "license": { 93 | "key": "mit", 94 | "name": "MIT License", 95 | "spdx_id": "MIT", 96 | "url": "https://api.github.com/licenses/mit", 97 | "node_id": "MDc6TGljZW5zZTEz" 98 | }, 99 | "forks": 0, 100 | "open_issues": 2, 101 | "watchers": 0, 102 | "default_branch": "master" 103 | }, 104 | "sender": { 105 | "login": "Clivern", 106 | "id": 1634427, 107 | "node_id": "MDQ6VXNlcjE2MzQ0Mjc=", 108 | "avatar_url": "https://avatars3.githubusercontent.com/u/1634427?v=4", 109 | "gravatar_id": "", 110 | "url": "https://api.github.com/users/Clivern", 111 | "html_url": "https://github.com/Clivern", 112 | "followers_url": "https://api.github.com/users/Clivern/followers", 113 | "following_url": "https://api.github.com/users/Clivern/following{/other_user}", 114 | "gists_url": "https://api.github.com/users/Clivern/gists{/gist_id}", 115 | "starred_url": "https://api.github.com/users/Clivern/starred{/owner}{/repo}", 116 | "subscriptions_url": "https://api.github.com/users/Clivern/subscriptions", 117 | "organizations_url": "https://api.github.com/users/Clivern/orgs", 118 | "repos_url": "https://api.github.com/users/Clivern/repos", 119 | "events_url": "https://api.github.com/users/Clivern/events{/privacy}", 120 | "received_events_url": "https://api.github.com/users/Clivern/received_events", 121 | "type": "User", 122 | "site_admin": false 123 | } 124 | } -------------------------------------------------------------------------------- /fixtures/issues.json: -------------------------------------------------------------------------------- 1 | { 2 | "action":"opened", 3 | "issue":{ 4 | "url":"https://api.github.com/repos/Clivern/Hamster/issues/1", 5 | "repository_url":"https://api.github.com/repos/Clivern/Hamster", 6 | "labels_url":"https://api.github.com/repos/Clivern/Hamster/issues/1/labels{/name}", 7 | "comments_url":"https://api.github.com/repos/Clivern/Hamster/issues/1/comments", 8 | "events_url":"https://api.github.com/repos/Clivern/Hamster/issues/1/events", 9 | "html_url":"https://github.com/Clivern/Hamster/issues/1", 10 | "id":362969620, 11 | "node_id":"MDU6SXNzdWUzNjI5Njk2MjA=", 12 | "number":1, 13 | "title":"Test Hamster", 14 | "user":{ 15 | "login":"Clivern", 16 | "id":1634427, 17 | "node_id":"MDQ6VXNlcjE2MzQ0Mjc=", 18 | "avatar_url":"https://avatars3.githubusercontent.com/u/1634427?v=4", 19 | "gravatar_id":"", 20 | "url":"https://api.github.com/users/Clivern", 21 | "html_url":"https://github.com/Clivern", 22 | "followers_url":"https://api.github.com/users/Clivern/followers", 23 | "following_url":"https://api.github.com/users/Clivern/following{/other_user}", 24 | "gists_url":"https://api.github.com/users/Clivern/gists{/gist_id}", 25 | "starred_url":"https://api.github.com/users/Clivern/starred{/owner}{/repo}", 26 | "subscriptions_url":"https://api.github.com/users/Clivern/subscriptions", 27 | "organizations_url":"https://api.github.com/users/Clivern/orgs", 28 | "repos_url":"https://api.github.com/users/Clivern/repos", 29 | "events_url":"https://api.github.com/users/Clivern/events{/privacy}", 30 | "received_events_url":"https://api.github.com/users/Clivern/received_events", 31 | "type":"User", 32 | "site_admin":false 33 | }, 34 | "labels":[ 35 | 36 | ], 37 | "state":"open", 38 | "locked":false, 39 | "assignee":null, 40 | "assignees":[ 41 | 42 | ], 43 | "milestone":null, 44 | "comments":0, 45 | "created_at":"2018-09-23T19:22:09Z", 46 | "updated_at":"2018-09-23T19:22:09Z", 47 | "closed_at":null, 48 | "author_association":"OWNER", 49 | "body":"" 50 | }, 51 | "repository":{ 52 | "id":150013651, 53 | "node_id":"MDEwOlJlcG9zaXRvcnkxNTAwMTM2NTE=", 54 | "name":"Hamster", 55 | "full_name":"Clivern/Hamster", 56 | "private":false, 57 | "owner":{ 58 | "login":"Clivern", 59 | "id":1634427, 60 | "node_id":"MDQ6VXNlcjE2MzQ0Mjc=", 61 | "avatar_url":"https://avatars3.githubusercontent.com/u/1634427?v=4", 62 | "gravatar_id":"", 63 | "url":"https://api.github.com/users/Clivern", 64 | "html_url":"https://github.com/Clivern", 65 | "followers_url":"https://api.github.com/users/Clivern/followers", 66 | "following_url":"https://api.github.com/users/Clivern/following{/other_user}", 67 | "gists_url":"https://api.github.com/users/Clivern/gists{/gist_id}", 68 | "starred_url":"https://api.github.com/users/Clivern/starred{/owner}{/repo}", 69 | "subscriptions_url":"https://api.github.com/users/Clivern/subscriptions", 70 | "organizations_url":"https://api.github.com/users/Clivern/orgs", 71 | "repos_url":"https://api.github.com/users/Clivern/repos", 72 | "events_url":"https://api.github.com/users/Clivern/events{/privacy}", 73 | "received_events_url":"https://api.github.com/users/Clivern/received_events", 74 | "type":"User", 75 | "site_admin":false 76 | }, 77 | "html_url":"https://github.com/Clivern/Hamster", 78 | "description":":rat: An Opinionated Github Bot!", 79 | "fork":false, 80 | "url":"https://api.github.com/repos/Clivern/Hamster", 81 | "forks_url":"https://api.github.com/repos/Clivern/Hamster/forks", 82 | "keys_url":"https://api.github.com/repos/Clivern/Hamster/keys{/key_id}", 83 | "collaborators_url":"https://api.github.com/repos/Clivern/Hamster/collaborators{/collaborator}", 84 | "teams_url":"https://api.github.com/repos/Clivern/Hamster/teams", 85 | "hooks_url":"https://api.github.com/repos/Clivern/Hamster/hooks", 86 | "issue_events_url":"https://api.github.com/repos/Clivern/Hamster/issues/events{/number}", 87 | "events_url":"https://api.github.com/repos/Clivern/Hamster/events", 88 | "assignees_url":"https://api.github.com/repos/Clivern/Hamster/assignees{/user}", 89 | "branches_url":"https://api.github.com/repos/Clivern/Hamster/branches{/branch}", 90 | "tags_url":"https://api.github.com/repos/Clivern/Hamster/tags", 91 | "blobs_url":"https://api.github.com/repos/Clivern/Hamster/git/blobs{/sha}", 92 | "git_tags_url":"https://api.github.com/repos/Clivern/Hamster/git/tags{/sha}", 93 | "git_refs_url":"https://api.github.com/repos/Clivern/Hamster/git/refs{/sha}", 94 | "trees_url":"https://api.github.com/repos/Clivern/Hamster/git/trees{/sha}", 95 | "statuses_url":"https://api.github.com/repos/Clivern/Hamster/statuses/{sha}", 96 | "languages_url":"https://api.github.com/repos/Clivern/Hamster/languages", 97 | "stargazers_url":"https://api.github.com/repos/Clivern/Hamster/stargazers", 98 | "contributors_url":"https://api.github.com/repos/Clivern/Hamster/contributors", 99 | "subscribers_url":"https://api.github.com/repos/Clivern/Hamster/subscribers", 100 | "subscription_url":"https://api.github.com/repos/Clivern/Hamster/subscription", 101 | "commits_url":"https://api.github.com/repos/Clivern/Hamster/commits{/sha}", 102 | "git_commits_url":"https://api.github.com/repos/Clivern/Hamster/git/commits{/sha}", 103 | "comments_url":"https://api.github.com/repos/Clivern/Hamster/comments{/number}", 104 | "issue_comment_url":"https://api.github.com/repos/Clivern/Hamster/issues/comments{/number}", 105 | "contents_url":"https://api.github.com/repos/Clivern/Hamster/contents/{+path}", 106 | "compare_url":"https://api.github.com/repos/Clivern/Hamster/compare/{base}...{head}", 107 | "merges_url":"https://api.github.com/repos/Clivern/Hamster/merges", 108 | "archive_url":"https://api.github.com/repos/Clivern/Hamster/{archive_format}{/ref}", 109 | "downloads_url":"https://api.github.com/repos/Clivern/Hamster/downloads", 110 | "issues_url":"https://api.github.com/repos/Clivern/Hamster/issues{/number}", 111 | "pulls_url":"https://api.github.com/repos/Clivern/Hamster/pulls{/number}", 112 | "milestones_url":"https://api.github.com/repos/Clivern/Hamster/milestones{/number}", 113 | "notifications_url":"https://api.github.com/repos/Clivern/Hamster/notifications{?since,all,participating}", 114 | "labels_url":"https://api.github.com/repos/Clivern/Hamster/labels{/name}", 115 | "releases_url":"https://api.github.com/repos/Clivern/Hamster/releases{/id}", 116 | "deployments_url":"https://api.github.com/repos/Clivern/Hamster/deployments", 117 | "created_at":"2018-09-23T18:33:43Z", 118 | "updated_at":"2018-09-23T18:49:42Z", 119 | "pushed_at":"2018-09-23T18:33:44Z", 120 | "git_url":"git://github.com/Clivern/Hamster.git", 121 | "ssh_url":"git@github.com:Clivern/Hamster.git", 122 | "clone_url":"https://github.com/Clivern/Hamster.git", 123 | "svn_url":"https://github.com/Clivern/Hamster", 124 | "homepage":"", 125 | "size":0, 126 | "stargazers_count":0, 127 | "watchers_count":0, 128 | "language":null, 129 | "has_issues":true, 130 | "has_projects":true, 131 | "has_downloads":true, 132 | "has_wiki":true, 133 | "has_pages":false, 134 | "forks_count":0, 135 | "mirror_url":null, 136 | "archived":false, 137 | "open_issues_count":1, 138 | "license":{ 139 | "key":"mit", 140 | "name":"MIT License", 141 | "spdx_id":"MIT", 142 | "url":"https://api.github.com/licenses/mit", 143 | "node_id":"MDc6TGljZW5zZTEz" 144 | }, 145 | "forks":0, 146 | "open_issues":1, 147 | "watchers":0, 148 | "default_branch":"master" 149 | }, 150 | "sender":{ 151 | "login":"Clivern", 152 | "id":1634427, 153 | "node_id":"MDQ6VXNlcjE2MzQ0Mjc=", 154 | "avatar_url":"https://avatars3.githubusercontent.com/u/1634427?v=4", 155 | "gravatar_id":"", 156 | "url":"https://api.github.com/users/Clivern", 157 | "html_url":"https://github.com/Clivern", 158 | "followers_url":"https://api.github.com/users/Clivern/followers", 159 | "following_url":"https://api.github.com/users/Clivern/following{/other_user}", 160 | "gists_url":"https://api.github.com/users/Clivern/gists{/gist_id}", 161 | "starred_url":"https://api.github.com/users/Clivern/starred{/owner}{/repo}", 162 | "subscriptions_url":"https://api.github.com/users/Clivern/subscriptions", 163 | "organizations_url":"https://api.github.com/users/Clivern/orgs", 164 | "repos_url":"https://api.github.com/users/Clivern/repos", 165 | "events_url":"https://api.github.com/users/Clivern/events{/privacy}", 166 | "received_events_url":"https://api.github.com/users/Clivern/received_events", 167 | "type":"User", 168 | "site_admin":false 169 | } 170 | } -------------------------------------------------------------------------------- /fixtures/label.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "created", 3 | "label": { 4 | "id": 1080937496, 5 | "node_id": "MDU6TGFiZWwxMDgwOTM3NDk2", 6 | "url": "https://api.github.com/repos/Clivern/Hamster/labels/Test", 7 | "name": "Test", 8 | "color": "fef2c0", 9 | "default": false 10 | }, 11 | "repository": { 12 | "id": 150013651, 13 | "node_id": "MDEwOlJlcG9zaXRvcnkxNTAwMTM2NTE=", 14 | "name": "Hamster", 15 | "full_name": "Clivern/Hamster", 16 | "private": false, 17 | "owner": { 18 | "login": "Clivern", 19 | "id": 1634427, 20 | "node_id": "MDQ6VXNlcjE2MzQ0Mjc=", 21 | "avatar_url": "https://avatars3.githubusercontent.com/u/1634427?v=4", 22 | "gravatar_id": "", 23 | "url": "https://api.github.com/users/Clivern", 24 | "html_url": "https://github.com/Clivern", 25 | "followers_url": "https://api.github.com/users/Clivern/followers", 26 | "following_url": "https://api.github.com/users/Clivern/following{/other_user}", 27 | "gists_url": "https://api.github.com/users/Clivern/gists{/gist_id}", 28 | "starred_url": "https://api.github.com/users/Clivern/starred{/owner}{/repo}", 29 | "subscriptions_url": "https://api.github.com/users/Clivern/subscriptions", 30 | "organizations_url": "https://api.github.com/users/Clivern/orgs", 31 | "repos_url": "https://api.github.com/users/Clivern/repos", 32 | "events_url": "https://api.github.com/users/Clivern/events{/privacy}", 33 | "received_events_url": "https://api.github.com/users/Clivern/received_events", 34 | "type": "User", 35 | "site_admin": false 36 | }, 37 | "html_url": "https://github.com/Clivern/Hamster", 38 | "description": ":rat: A Bot Toolkit for Github!", 39 | "fork": false, 40 | "url": "https://api.github.com/repos/Clivern/Hamster", 41 | "forks_url": "https://api.github.com/repos/Clivern/Hamster/forks", 42 | "keys_url": "https://api.github.com/repos/Clivern/Hamster/keys{/key_id}", 43 | "collaborators_url": "https://api.github.com/repos/Clivern/Hamster/collaborators{/collaborator}", 44 | "teams_url": "https://api.github.com/repos/Clivern/Hamster/teams", 45 | "hooks_url": "https://api.github.com/repos/Clivern/Hamster/hooks", 46 | "issue_events_url": "https://api.github.com/repos/Clivern/Hamster/issues/events{/number}", 47 | "events_url": "https://api.github.com/repos/Clivern/Hamster/events", 48 | "assignees_url": "https://api.github.com/repos/Clivern/Hamster/assignees{/user}", 49 | "branches_url": "https://api.github.com/repos/Clivern/Hamster/branches{/branch}", 50 | "tags_url": "https://api.github.com/repos/Clivern/Hamster/tags", 51 | "blobs_url": "https://api.github.com/repos/Clivern/Hamster/git/blobs{/sha}", 52 | "git_tags_url": "https://api.github.com/repos/Clivern/Hamster/git/tags{/sha}", 53 | "git_refs_url": "https://api.github.com/repos/Clivern/Hamster/git/refs{/sha}", 54 | "trees_url": "https://api.github.com/repos/Clivern/Hamster/git/trees{/sha}", 55 | "statuses_url": "https://api.github.com/repos/Clivern/Hamster/statuses/{sha}", 56 | "languages_url": "https://api.github.com/repos/Clivern/Hamster/languages", 57 | "stargazers_url": "https://api.github.com/repos/Clivern/Hamster/stargazers", 58 | "contributors_url": "https://api.github.com/repos/Clivern/Hamster/contributors", 59 | "subscribers_url": "https://api.github.com/repos/Clivern/Hamster/subscribers", 60 | "subscription_url": "https://api.github.com/repos/Clivern/Hamster/subscription", 61 | "commits_url": "https://api.github.com/repos/Clivern/Hamster/commits{/sha}", 62 | "git_commits_url": "https://api.github.com/repos/Clivern/Hamster/git/commits{/sha}", 63 | "comments_url": "https://api.github.com/repos/Clivern/Hamster/comments{/number}", 64 | "issue_comment_url": "https://api.github.com/repos/Clivern/Hamster/issues/comments{/number}", 65 | "contents_url": "https://api.github.com/repos/Clivern/Hamster/contents/{+path}", 66 | "compare_url": "https://api.github.com/repos/Clivern/Hamster/compare/{base}...{head}", 67 | "merges_url": "https://api.github.com/repos/Clivern/Hamster/merges", 68 | "archive_url": "https://api.github.com/repos/Clivern/Hamster/{archive_format}{/ref}", 69 | "downloads_url": "https://api.github.com/repos/Clivern/Hamster/downloads", 70 | "issues_url": "https://api.github.com/repos/Clivern/Hamster/issues{/number}", 71 | "pulls_url": "https://api.github.com/repos/Clivern/Hamster/pulls{/number}", 72 | "milestones_url": "https://api.github.com/repos/Clivern/Hamster/milestones{/number}", 73 | "notifications_url": "https://api.github.com/repos/Clivern/Hamster/notifications{?since,all,participating}", 74 | "labels_url": "https://api.github.com/repos/Clivern/Hamster/labels{/name}", 75 | "releases_url": "https://api.github.com/repos/Clivern/Hamster/releases{/id}", 76 | "deployments_url": "https://api.github.com/repos/Clivern/Hamster/deployments", 77 | "created_at": "2018-09-23T18:33:43Z", 78 | "updated_at": "2018-10-04T11:45:56Z", 79 | "pushed_at": "2018-10-05T17:40:56Z", 80 | "git_url": "git://github.com/Clivern/Hamster.git", 81 | "ssh_url": "git@github.com:Clivern/Hamster.git", 82 | "clone_url": "https://github.com/Clivern/Hamster.git", 83 | "svn_url": "https://github.com/Clivern/Hamster", 84 | "homepage": "", 85 | "size": 1416, 86 | "stargazers_count": 0, 87 | "watchers_count": 0, 88 | "language": "Go", 89 | "has_issues": true, 90 | "has_projects": true, 91 | "has_downloads": true, 92 | "has_wiki": true, 93 | "has_pages": false, 94 | "forks_count": 0, 95 | "mirror_url": null, 96 | "archived": false, 97 | "open_issues_count": 2, 98 | "license": { 99 | "key": "mit", 100 | "name": "MIT License", 101 | "spdx_id": "MIT", 102 | "url": "https://api.github.com/licenses/mit", 103 | "node_id": "MDc6TGljZW5zZTEz" 104 | }, 105 | "forks": 0, 106 | "open_issues": 2, 107 | "watchers": 0, 108 | "default_branch": "master" 109 | }, 110 | "sender": { 111 | "login": "Clivern", 112 | "id": 1634427, 113 | "node_id": "MDQ6VXNlcjE2MzQ0Mjc=", 114 | "avatar_url": "https://avatars3.githubusercontent.com/u/1634427?v=4", 115 | "gravatar_id": "", 116 | "url": "https://api.github.com/users/Clivern", 117 | "html_url": "https://github.com/Clivern", 118 | "followers_url": "https://api.github.com/users/Clivern/followers", 119 | "following_url": "https://api.github.com/users/Clivern/following{/other_user}", 120 | "gists_url": "https://api.github.com/users/Clivern/gists{/gist_id}", 121 | "starred_url": "https://api.github.com/users/Clivern/starred{/owner}{/repo}", 122 | "subscriptions_url": "https://api.github.com/users/Clivern/subscriptions", 123 | "organizations_url": "https://api.github.com/users/Clivern/orgs", 124 | "repos_url": "https://api.github.com/users/Clivern/repos", 125 | "events_url": "https://api.github.com/users/Clivern/events{/privacy}", 126 | "received_events_url": "https://api.github.com/users/Clivern/received_events", 127 | "type": "User", 128 | "site_admin": false 129 | } 130 | } -------------------------------------------------------------------------------- /fixtures/push.json: -------------------------------------------------------------------------------- 1 | { 2 | "ref": "refs/heads/feature/new-events", 3 | "before": "0000000000000000000000000000000000000000", 4 | "after": "4c16c2c55ac4eca69c1b9cf35f7ee1dabf237462", 5 | "created": true, 6 | "deleted": false, 7 | "forced": false, 8 | "base_ref": null, 9 | "compare": "https://github.com/Clivern/Hamster/commit/4c16c2c55ac4", 10 | "commits": [ 11 | { 12 | "id": "4c16c2c55ac4eca69c1b9cf35f7ee1dabf237462", 13 | "tree_id": "b04ccbfd9cf5f97d85657458a0076aeb45999285", 14 | "distinct": true, 15 | "message": "Add raw event", 16 | "timestamp": "2018-10-04T22:19:41+02:00", 17 | "url": "https://github.com/Clivern/Hamster/commit/4c16c2c55ac4eca69c1b9cf35f7ee1dabf237462", 18 | "author": { 19 | "name": "Clivern", 20 | "email": "hello@clivern.com", 21 | "username": "Clivern" 22 | }, 23 | "committer": { 24 | "name": "Clivern", 25 | "email": "hello@clivern.com", 26 | "username": "Clivern" 27 | }, 28 | "added": [ 29 | "internal/app/event/raw.go", 30 | "var/logs/.gitignore" 31 | ], 32 | "removed": [ 33 | "var/logs/.gitkeep" 34 | ], 35 | "modified": [ 36 | "README.md", 37 | "internal/app/controller/listener.go", 38 | "internal/app/listener/action.go", 39 | "plugin/base.go", 40 | "hamster.go" 41 | ] 42 | } 43 | ], 44 | "head_commit": { 45 | "id": "4c16c2c55ac4eca69c1b9cf35f7ee1dabf237462", 46 | "tree_id": "b04ccbfd9cf5f97d85657458a0076aeb45999285", 47 | "distinct": true, 48 | "message": "Add raw event", 49 | "timestamp": "2018-10-04T22:19:41+02:00", 50 | "url": "https://github.com/Clivern/Hamster/commit/4c16c2c55ac4eca69c1b9cf35f7ee1dabf237462", 51 | "author": { 52 | "name": "Clivern", 53 | "email": "hello@clivern.com", 54 | "username": "Clivern" 55 | }, 56 | "committer": { 57 | "name": "Clivern", 58 | "email": "hello@clivern.com", 59 | "username": "Clivern" 60 | }, 61 | "added": [ 62 | "internal/app/event/raw.go", 63 | "var/logs/.gitignore" 64 | ], 65 | "removed": [ 66 | "var/logs/.gitkeep" 67 | ], 68 | "modified": [ 69 | "README.md", 70 | "internal/app/controller/listener.go", 71 | "internal/app/listener/action.go", 72 | "plugin/base.go", 73 | "hamster.go" 74 | ] 75 | }, 76 | "repository": { 77 | "id": 150013651, 78 | "node_id": "MDEwOlJlcG9zaXRvcnkxNTAwMTM2NTE=", 79 | "name": "Hamster", 80 | "full_name": "Clivern/Hamster", 81 | "private": false, 82 | "owner": { 83 | "name": "Clivern", 84 | "email": "hello@clivern.com", 85 | "login": "Clivern", 86 | "id": 1634427, 87 | "node_id": "MDQ6VXNlcjE2MzQ0Mjc=", 88 | "avatar_url": "https://avatars3.githubusercontent.com/u/1634427?v=4", 89 | "gravatar_id": "", 90 | "url": "https://api.github.com/users/Clivern", 91 | "html_url": "https://github.com/Clivern", 92 | "followers_url": "https://api.github.com/users/Clivern/followers", 93 | "following_url": "https://api.github.com/users/Clivern/following{/other_user}", 94 | "gists_url": "https://api.github.com/users/Clivern/gists{/gist_id}", 95 | "starred_url": "https://api.github.com/users/Clivern/starred{/owner}{/repo}", 96 | "subscriptions_url": "https://api.github.com/users/Clivern/subscriptions", 97 | "organizations_url": "https://api.github.com/users/Clivern/orgs", 98 | "repos_url": "https://api.github.com/users/Clivern/repos", 99 | "events_url": "https://api.github.com/users/Clivern/events{/privacy}", 100 | "received_events_url": "https://api.github.com/users/Clivern/received_events", 101 | "type": "User", 102 | "site_admin": false 103 | }, 104 | "html_url": "https://github.com/Clivern/Hamster", 105 | "description": ":rat: A Bot Toolkit for Github!", 106 | "fork": false, 107 | "url": "https://github.com/Clivern/Hamster", 108 | "forks_url": "https://api.github.com/repos/Clivern/Hamster/forks", 109 | "keys_url": "https://api.github.com/repos/Clivern/Hamster/keys{/key_id}", 110 | "collaborators_url": "https://api.github.com/repos/Clivern/Hamster/collaborators{/collaborator}", 111 | "teams_url": "https://api.github.com/repos/Clivern/Hamster/teams", 112 | "hooks_url": "https://api.github.com/repos/Clivern/Hamster/hooks", 113 | "issue_events_url": "https://api.github.com/repos/Clivern/Hamster/issues/events{/number}", 114 | "events_url": "https://api.github.com/repos/Clivern/Hamster/events", 115 | "assignees_url": "https://api.github.com/repos/Clivern/Hamster/assignees{/user}", 116 | "branches_url": "https://api.github.com/repos/Clivern/Hamster/branches{/branch}", 117 | "tags_url": "https://api.github.com/repos/Clivern/Hamster/tags", 118 | "blobs_url": "https://api.github.com/repos/Clivern/Hamster/git/blobs{/sha}", 119 | "git_tags_url": "https://api.github.com/repos/Clivern/Hamster/git/tags{/sha}", 120 | "git_refs_url": "https://api.github.com/repos/Clivern/Hamster/git/refs{/sha}", 121 | "trees_url": "https://api.github.com/repos/Clivern/Hamster/git/trees{/sha}", 122 | "statuses_url": "https://api.github.com/repos/Clivern/Hamster/statuses/{sha}", 123 | "languages_url": "https://api.github.com/repos/Clivern/Hamster/languages", 124 | "stargazers_url": "https://api.github.com/repos/Clivern/Hamster/stargazers", 125 | "contributors_url": "https://api.github.com/repos/Clivern/Hamster/contributors", 126 | "subscribers_url": "https://api.github.com/repos/Clivern/Hamster/subscribers", 127 | "subscription_url": "https://api.github.com/repos/Clivern/Hamster/subscription", 128 | "commits_url": "https://api.github.com/repos/Clivern/Hamster/commits{/sha}", 129 | "git_commits_url": "https://api.github.com/repos/Clivern/Hamster/git/commits{/sha}", 130 | "comments_url": "https://api.github.com/repos/Clivern/Hamster/comments{/number}", 131 | "issue_comment_url": "https://api.github.com/repos/Clivern/Hamster/issues/comments{/number}", 132 | "contents_url": "https://api.github.com/repos/Clivern/Hamster/contents/{+path}", 133 | "compare_url": "https://api.github.com/repos/Clivern/Hamster/compare/{base}...{head}", 134 | "merges_url": "https://api.github.com/repos/Clivern/Hamster/merges", 135 | "archive_url": "https://api.github.com/repos/Clivern/Hamster/{archive_format}{/ref}", 136 | "downloads_url": "https://api.github.com/repos/Clivern/Hamster/downloads", 137 | "issues_url": "https://api.github.com/repos/Clivern/Hamster/issues{/number}", 138 | "pulls_url": "https://api.github.com/repos/Clivern/Hamster/pulls{/number}", 139 | "milestones_url": "https://api.github.com/repos/Clivern/Hamster/milestones{/number}", 140 | "notifications_url": "https://api.github.com/repos/Clivern/Hamster/notifications{?since,all,participating}", 141 | "labels_url": "https://api.github.com/repos/Clivern/Hamster/labels{/name}", 142 | "releases_url": "https://api.github.com/repos/Clivern/Hamster/releases{/id}", 143 | "deployments_url": "https://api.github.com/repos/Clivern/Hamster/deployments", 144 | "created_at": 1537727623, 145 | "updated_at": "2018-10-04T11:45:56Z", 146 | "pushed_at": 1538684397, 147 | "git_url": "git://github.com/Clivern/Hamster.git", 148 | "ssh_url": "git@github.com:Clivern/Hamster.git", 149 | "clone_url": "https://github.com/Clivern/Hamster.git", 150 | "svn_url": "https://github.com/Clivern/Hamster", 151 | "homepage": "", 152 | "size": 1397, 153 | "stargazers_count": 0, 154 | "watchers_count": 0, 155 | "language": "Go", 156 | "has_issues": true, 157 | "has_projects": true, 158 | "has_downloads": true, 159 | "has_wiki": true, 160 | "has_pages": false, 161 | "forks_count": 0, 162 | "mirror_url": null, 163 | "archived": false, 164 | "open_issues_count": 2, 165 | "license": { 166 | "key": "mit", 167 | "name": "MIT License", 168 | "spdx_id": "MIT", 169 | "url": "https://api.github.com/licenses/mit", 170 | "node_id": "MDc6TGljZW5zZTEz" 171 | }, 172 | "forks": 0, 173 | "open_issues": 2, 174 | "watchers": 0, 175 | "default_branch": "master", 176 | "stargazers": 0, 177 | "master_branch": "master" 178 | }, 179 | "pusher": { 180 | "name": "Clivern", 181 | "email": "hello@clivern.com" 182 | }, 183 | "sender": { 184 | "login": "Clivern", 185 | "id": 1634427, 186 | "node_id": "MDQ6VXNlcjE2MzQ0Mjc=", 187 | "avatar_url": "https://avatars3.githubusercontent.com/u/1634427?v=4", 188 | "gravatar_id": "", 189 | "url": "https://api.github.com/users/Clivern", 190 | "html_url": "https://github.com/Clivern", 191 | "followers_url": "https://api.github.com/users/Clivern/followers", 192 | "following_url": "https://api.github.com/users/Clivern/following{/other_user}", 193 | "gists_url": "https://api.github.com/users/Clivern/gists{/gist_id}", 194 | "starred_url": "https://api.github.com/users/Clivern/starred{/owner}{/repo}", 195 | "subscriptions_url": "https://api.github.com/users/Clivern/subscriptions", 196 | "organizations_url": "https://api.github.com/users/Clivern/orgs", 197 | "repos_url": "https://api.github.com/users/Clivern/repos", 198 | "events_url": "https://api.github.com/users/Clivern/events{/privacy}", 199 | "received_events_url": "https://api.github.com/users/Clivern/received_events", 200 | "type": "User", 201 | "site_admin": false 202 | } 203 | } -------------------------------------------------------------------------------- /fixtures/watch.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "started", 3 | "repository": { 4 | "id": 150013651, 5 | "node_id": "MDEwOlJlcG9zaXRvcnkxNTAwMTM2NTE=", 6 | "name": "Hamster", 7 | "full_name": "Clivern/Hamster", 8 | "private": false, 9 | "owner": { 10 | "login": "Clivern", 11 | "id": 1634427, 12 | "node_id": "MDQ6VXNlcjE2MzQ0Mjc=", 13 | "avatar_url": "https://avatars3.githubusercontent.com/u/1634427?v=4", 14 | "gravatar_id": "", 15 | "url": "https://api.github.com/users/Clivern", 16 | "html_url": "https://github.com/Clivern", 17 | "followers_url": "https://api.github.com/users/Clivern/followers", 18 | "following_url": "https://api.github.com/users/Clivern/following{/other_user}", 19 | "gists_url": "https://api.github.com/users/Clivern/gists{/gist_id}", 20 | "starred_url": "https://api.github.com/users/Clivern/starred{/owner}{/repo}", 21 | "subscriptions_url": "https://api.github.com/users/Clivern/subscriptions", 22 | "organizations_url": "https://api.github.com/users/Clivern/orgs", 23 | "repos_url": "https://api.github.com/users/Clivern/repos", 24 | "events_url": "https://api.github.com/users/Clivern/events{/privacy}", 25 | "received_events_url": "https://api.github.com/users/Clivern/received_events", 26 | "type": "User", 27 | "site_admin": false 28 | }, 29 | "html_url": "https://github.com/Clivern/Hamster", 30 | "description": ":rat: A Bot Toolkit for Github!", 31 | "fork": false, 32 | "url": "https://api.github.com/repos/Clivern/Hamster", 33 | "forks_url": "https://api.github.com/repos/Clivern/Hamster/forks", 34 | "keys_url": "https://api.github.com/repos/Clivern/Hamster/keys{/key_id}", 35 | "collaborators_url": "https://api.github.com/repos/Clivern/Hamster/collaborators{/collaborator}", 36 | "teams_url": "https://api.github.com/repos/Clivern/Hamster/teams", 37 | "hooks_url": "https://api.github.com/repos/Clivern/Hamster/hooks", 38 | "issue_events_url": "https://api.github.com/repos/Clivern/Hamster/issues/events{/number}", 39 | "events_url": "https://api.github.com/repos/Clivern/Hamster/events", 40 | "assignees_url": "https://api.github.com/repos/Clivern/Hamster/assignees{/user}", 41 | "branches_url": "https://api.github.com/repos/Clivern/Hamster/branches{/branch}", 42 | "tags_url": "https://api.github.com/repos/Clivern/Hamster/tags", 43 | "blobs_url": "https://api.github.com/repos/Clivern/Hamster/git/blobs{/sha}", 44 | "git_tags_url": "https://api.github.com/repos/Clivern/Hamster/git/tags{/sha}", 45 | "git_refs_url": "https://api.github.com/repos/Clivern/Hamster/git/refs{/sha}", 46 | "trees_url": "https://api.github.com/repos/Clivern/Hamster/git/trees{/sha}", 47 | "statuses_url": "https://api.github.com/repos/Clivern/Hamster/statuses/{sha}", 48 | "languages_url": "https://api.github.com/repos/Clivern/Hamster/languages", 49 | "stargazers_url": "https://api.github.com/repos/Clivern/Hamster/stargazers", 50 | "contributors_url": "https://api.github.com/repos/Clivern/Hamster/contributors", 51 | "subscribers_url": "https://api.github.com/repos/Clivern/Hamster/subscribers", 52 | "subscription_url": "https://api.github.com/repos/Clivern/Hamster/subscription", 53 | "commits_url": "https://api.github.com/repos/Clivern/Hamster/commits{/sha}", 54 | "git_commits_url": "https://api.github.com/repos/Clivern/Hamster/git/commits{/sha}", 55 | "comments_url": "https://api.github.com/repos/Clivern/Hamster/comments{/number}", 56 | "issue_comment_url": "https://api.github.com/repos/Clivern/Hamster/issues/comments{/number}", 57 | "contents_url": "https://api.github.com/repos/Clivern/Hamster/contents/{+path}", 58 | "compare_url": "https://api.github.com/repos/Clivern/Hamster/compare/{base}...{head}", 59 | "merges_url": "https://api.github.com/repos/Clivern/Hamster/merges", 60 | "archive_url": "https://api.github.com/repos/Clivern/Hamster/{archive_format}{/ref}", 61 | "downloads_url": "https://api.github.com/repos/Clivern/Hamster/downloads", 62 | "issues_url": "https://api.github.com/repos/Clivern/Hamster/issues{/number}", 63 | "pulls_url": "https://api.github.com/repos/Clivern/Hamster/pulls{/number}", 64 | "milestones_url": "https://api.github.com/repos/Clivern/Hamster/milestones{/number}", 65 | "notifications_url": "https://api.github.com/repos/Clivern/Hamster/notifications{?since,all,participating}", 66 | "labels_url": "https://api.github.com/repos/Clivern/Hamster/labels{/name}", 67 | "releases_url": "https://api.github.com/repos/Clivern/Hamster/releases{/id}", 68 | "deployments_url": "https://api.github.com/repos/Clivern/Hamster/deployments", 69 | "created_at": "2018-09-23T18:33:43Z", 70 | "updated_at": "2018-10-02T21:11:46Z", 71 | "pushed_at": "2018-10-02T20:05:25Z", 72 | "git_url": "git://github.com/Clivern/Hamster.git", 73 | "ssh_url": "git@github.com:Clivern/Hamster.git", 74 | "clone_url": "https://github.com/Clivern/Hamster.git", 75 | "svn_url": "https://github.com/Clivern/Hamster", 76 | "homepage": "", 77 | "size": 1528, 78 | "stargazers_count": 1, 79 | "watchers_count": 1, 80 | "language": "Go", 81 | "has_issues": true, 82 | "has_projects": true, 83 | "has_downloads": true, 84 | "has_wiki": true, 85 | "has_pages": false, 86 | "forks_count": 0, 87 | "mirror_url": null, 88 | "archived": false, 89 | "open_issues_count": 0, 90 | "license": { 91 | "key": "mit", 92 | "name": "MIT License", 93 | "spdx_id": "MIT", 94 | "url": "https://api.github.com/licenses/mit", 95 | "node_id": "MDc6TGljZW5zZTEz" 96 | }, 97 | "forks": 0, 98 | "open_issues": 0, 99 | "watchers": 1, 100 | "default_branch": "master" 101 | }, 102 | "sender": { 103 | "login": "Clivern", 104 | "id": 1634427, 105 | "node_id": "MDQ6VXNlcjE2MzQ0Mjc=", 106 | "avatar_url": "https://avatars3.githubusercontent.com/u/1634427?v=4", 107 | "gravatar_id": "", 108 | "url": "https://api.github.com/users/Clivern", 109 | "html_url": "https://github.com/Clivern", 110 | "followers_url": "https://api.github.com/users/Clivern/followers", 111 | "following_url": "https://api.github.com/users/Clivern/following{/other_user}", 112 | "gists_url": "https://api.github.com/users/Clivern/gists{/gist_id}", 113 | "starred_url": "https://api.github.com/users/Clivern/starred{/owner}{/repo}", 114 | "subscriptions_url": "https://api.github.com/users/Clivern/subscriptions", 115 | "organizations_url": "https://api.github.com/users/Clivern/orgs", 116 | "repos_url": "https://api.github.com/users/Clivern/repos", 117 | "events_url": "https://api.github.com/users/Clivern/events{/privacy}", 118 | "received_events_url": "https://api.github.com/users/Clivern/received_events", 119 | "type": "User", 120 | "site_admin": false 121 | } 122 | } -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/clivern/hamster 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.8.1 7 | github.com/google/logger v1.1.1 8 | github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 9 | ) 10 | -------------------------------------------------------------------------------- /hamster.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "github.com/clivern/hamster/internal/app/controller" 9 | "github.com/clivern/hamster/internal/app/pkg/utils" 10 | "github.com/gin-gonic/gin" 11 | "io" 12 | "net/http" 13 | "os" 14 | ) 15 | 16 | func main() { 17 | // Load config.json file and store on env 18 | config := &utils.Config{} 19 | config.Load("config.dist.json") 20 | // This will never override ENV Vars if exists 21 | config.Cache() 22 | config.GinEnv() 23 | 24 | if os.Getenv("AppMode") == "prod" { 25 | gin.SetMode(gin.ReleaseMode) 26 | gin.DisableConsoleColor() 27 | f, _ := os.Create("var/logs/gin.log") 28 | gin.DefaultWriter = io.MultiWriter(f) 29 | } 30 | 31 | r := gin.Default() 32 | r.Static("/assets", "./assets") 33 | r.LoadHTMLGlob("templates/*") 34 | r.GET("/", controller.Index) 35 | r.GET("/_healthcheck", controller.HealthCheck) 36 | r.GET("/login", controller.Login) 37 | r.GET("/auth", controller.Auth) 38 | r.POST("/listen", controller.Listen) 39 | r.GET("/favicon.ico", func(c *gin.Context) { 40 | c.String(http.StatusNoContent, "") 41 | }) 42 | 43 | r.Run() 44 | } 45 | -------------------------------------------------------------------------------- /internal/app/controller/auth.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package controller 6 | 7 | import ( 8 | "github.com/clivern/hamster/internal/app/pkg/github" 9 | "github.com/gin-gonic/gin" 10 | "os" 11 | ) 12 | 13 | // Auth controller 14 | func Auth(c *gin.Context) { 15 | 16 | githubOauth := &github.OAuthApp{ 17 | ClientID: os.Getenv("GithubAppClientID"), 18 | RedirectURI: os.Getenv("GithubAppRedirectURI"), 19 | AllowSignup: os.Getenv("GithubAppAllowSignup"), 20 | Scope: os.Getenv("GithubAppScope"), 21 | ClientSecret: os.Getenv("GithubAppClientSecret"), 22 | } 23 | 24 | state, err := c.Cookie("gh_oauth_state") 25 | 26 | if err == nil && state != "" { 27 | githubOauth.SetState(state) 28 | } 29 | 30 | ok, err := githubOauth.FetchAccessToken( 31 | c.DefaultQuery("code", ""), 32 | c.DefaultQuery("state", ""), 33 | ) 34 | 35 | if ok && err == nil { 36 | c.JSON(200, gin.H{ 37 | "status": "ok", 38 | "accessToken": githubOauth.GetAccessToken(), 39 | }) 40 | } else { 41 | c.JSON(200, gin.H{ 42 | "status": "not ok", 43 | "error": err.Error(), 44 | }) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /internal/app/controller/health_check.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package controller 6 | 7 | import ( 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | // HealthCheck controller 12 | func HealthCheck(c *gin.Context) { 13 | c.JSON(200, gin.H{ 14 | "status": "ok", 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /internal/app/controller/home.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package controller 6 | 7 | import ( 8 | "github.com/gin-gonic/gin" 9 | "net/http" 10 | ) 11 | 12 | // Index controller 13 | func Index(c *gin.Context) { 14 | c.HTML(http.StatusOK, "index.tmpl", gin.H{ 15 | "title": "Hamster", 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /internal/app/controller/listener.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package controller 6 | 7 | import ( 8 | "github.com/clivern/hamster/internal/app/event" 9 | "github.com/clivern/hamster/internal/app/listener" 10 | "github.com/clivern/hamster/internal/app/pkg/logger" 11 | "github.com/clivern/hamster/plugin" 12 | "github.com/gin-gonic/gin" 13 | "os" 14 | ) 15 | 16 | // Listen controller 17 | func Listen(c *gin.Context) { 18 | var actions listener.Action 19 | var commands listener.Commands 20 | 21 | rawBody, _ := c.GetRawData() 22 | body := string(rawBody) 23 | 24 | parser := &listener.Parser{ 25 | UserAgent: c.GetHeader("User-Agent"), 26 | GithubDelivery: c.GetHeader("X-GitHub-Delivery"), 27 | GitHubEvent: c.GetHeader("X-GitHub-Event"), 28 | HubSignature: c.GetHeader("X-Hub-Signature"), 29 | Body: body, 30 | } 31 | 32 | ok := parser.VerifySignature(os.Getenv("GithubWebhookSecret")) 33 | evt := parser.GetGitHubEvent() 34 | 35 | logger.Infof("Incoming event %s with payload %s!", evt, body) 36 | 37 | if ok { 38 | switch evt { 39 | case "status": 40 | var status event.Status 41 | status.LoadFromJSON(rawBody) 42 | actions.RegisterStatusAction(plugin.StatusListener) 43 | actions.ExecuteStatusActions(status) 44 | case "watch": 45 | var watch event.Watch 46 | watch.LoadFromJSON(rawBody) 47 | actions.RegisterWatchAction(plugin.WatchListener) 48 | actions.ExecuteWatchActions(watch) 49 | case "issues": 50 | var issues event.Issues 51 | issues.LoadFromJSON(rawBody) 52 | actions.RegisterIssuesAction(plugin.IssuesListener) 53 | actions.ExecuteIssuesActions(issues) 54 | 55 | // Commands Listeners 56 | commands.RegisterIssuesAction("test", plugin.IssuesTestCommandListener) 57 | commands.ExecuteIssuesActions(issues) 58 | case "push": 59 | var push event.Push 60 | push.LoadFromJSON(rawBody) 61 | actions.RegisterPushAction(plugin.PushListener) 62 | actions.ExecutePushActions(push) 63 | case "issue_comment": 64 | var issueComment event.IssueComment 65 | issueComment.LoadFromJSON(rawBody) 66 | actions.RegisterIssueCommentAction(plugin.IssueCommentListener) 67 | actions.ExecuteIssueCommentActions(issueComment) 68 | 69 | // Commands Listeners 70 | commands.RegisterIssueCommentAction("test", plugin.IssueCommentTestCommandListener) 71 | commands.ExecuteIssueCommentActions(issueComment) 72 | case "create": 73 | var create event.Create 74 | create.LoadFromJSON(rawBody) 75 | actions.RegisterCreateAction(plugin.CreateListener) 76 | actions.ExecuteCreateActions(create) 77 | case "label": 78 | var label event.Label 79 | label.LoadFromJSON(rawBody) 80 | actions.RegisterLabelAction(plugin.LabelListener) 81 | actions.ExecuteLabelActions(label) 82 | case "delete": 83 | var delete event.Delete 84 | delete.LoadFromJSON(rawBody) 85 | actions.RegisterDeleteAction(plugin.DeleteListener) 86 | actions.ExecuteDeleteActions(delete) 87 | case "milestone": 88 | var milestone event.Milestone 89 | milestone.LoadFromJSON(rawBody) 90 | actions.RegisterMilestoneAction(plugin.MilestoneListener) 91 | actions.ExecuteMilestoneActions(milestone) 92 | case "pull_request": 93 | var pullRequest event.PullRequest 94 | pullRequest.LoadFromJSON(rawBody) 95 | actions.RegisterPullRequestAction(plugin.PullRequestListener) 96 | actions.ExecutePullRequestActions(pullRequest) 97 | case "pull_request_review": 98 | var pullRequestReview event.PullRequestReview 99 | pullRequestReview.LoadFromJSON(rawBody) 100 | actions.RegisterPullRequestReviewAction(plugin.PullRequestReviewListener) 101 | actions.ExecutePullRequestReviewActions(pullRequestReview) 102 | case "pull_request_review_comment": 103 | var pullRequestReviewComment event.PullRequestReviewComment 104 | pullRequestReviewComment.LoadFromJSON(rawBody) 105 | actions.RegisterPullRequestReviewCommentAction(plugin.PullRequestReviewCommentListener) 106 | actions.ExecutePullRequestReviewCommentActions(pullRequestReviewComment) 107 | default: 108 | logger.Infof("Unknown or unsupported event %s!", evt) 109 | } 110 | 111 | var raw event.Raw 112 | raw.SetEvent(evt) 113 | raw.SetBody(body) 114 | actions.RegisterRawAction(plugin.RawListener) 115 | actions.ExecuteRawActions(raw) 116 | 117 | c.JSON(200, gin.H{ 118 | "status": "Nice!", 119 | }) 120 | } else { 121 | c.JSON(200, gin.H{ 122 | "status": "Oops!", 123 | }) 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /internal/app/controller/login.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package controller 6 | 7 | import ( 8 | "github.com/clivern/hamster/internal/app/pkg/github" 9 | "github.com/gin-gonic/gin" 10 | "net/http" 11 | "os" 12 | ) 13 | 14 | // Login controller 15 | func Login(c *gin.Context) { 16 | 17 | githubOauth := &github.OAuthApp{ 18 | ClientID: os.Getenv("GithubAppClientID"), 19 | RedirectURI: os.Getenv("GithubAppRedirectURI"), 20 | AllowSignup: os.Getenv("GithubAppAllowSignup"), 21 | Scope: os.Getenv("GithubAppScope"), 22 | ClientSecret: os.Getenv("GithubAppClientSecret"), 23 | } 24 | 25 | state, err := c.Cookie("gh_oauth_state") 26 | 27 | if err != nil || state == "" { 28 | githubOauth.GenerateState() 29 | c.SetCookie("gh_oauth_state", githubOauth.GetState(), 3600, "/", os.Getenv("AppDomain"), true, true) 30 | } else { 31 | githubOauth.SetState(state) 32 | } 33 | 34 | c.HTML(http.StatusOK, "login.tmpl", gin.H{ 35 | "title": "Hamster", 36 | "oauthURL": githubOauth.BuildAuthorizeURL(), 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /internal/app/event/check_run.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // CheckRun event received Any time a check run is created, requested, or rerequested. 12 | type CheckRun struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *CheckRun) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *CheckRun) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/check_suite.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // CheckSuite event received any time a check suite is completed, requested, or rerequested. 12 | type CheckSuite struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *CheckSuite) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *CheckSuite) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/command.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | "strings" 10 | ) 11 | 12 | // Command struct 13 | type Command struct { 14 | Data string 15 | Name string 16 | Parameters []string 17 | } 18 | 19 | // LoadFromJSON update object from json 20 | func (e *Command) LoadFromJSON(data []byte) (bool, error) { 21 | err := json.Unmarshal(data, &e) 22 | if err != nil { 23 | return false, err 24 | } 25 | return true, nil 26 | } 27 | 28 | // ConvertToJSON convert object to json 29 | func (e *Command) ConvertToJSON() (string, error) { 30 | data, err := json.Marshal(&e) 31 | if err != nil { 32 | return "", err 33 | } 34 | return string(data), nil 35 | } 36 | 37 | // Parse parses the incoming command 38 | func (e *Command) Parse() { 39 | if strings.Contains(e.Data, "{") && strings.Contains(e.Data, "}") { 40 | items := strings.Split(e.Data, "{") 41 | if len(items) == 2 { 42 | e.Name = strings.Trim(items[0], "/") 43 | e.Parameters = strings.Split(strings.Trim(items[1], "}"), ",") 44 | } 45 | } else { 46 | e.Name = strings.Trim(e.Data, "/") 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /internal/app/event/commit_comment.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // CommitComment event received any time a Commit is commented on. 12 | type CommitComment struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *CommitComment) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *CommitComment) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/create.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | "time" 10 | ) 11 | 12 | // Create event received any time a Branch or Tag is created. 13 | type Create struct { 14 | Ref string `json:"ref"` 15 | RefType string `json:"ref_type"` 16 | MasterBranch string `json:"master_branch"` 17 | Description string `json:"description"` 18 | PusherType string `json:"pusher_type"` 19 | Repository struct { 20 | ID int `json:"id"` 21 | NodeID string `json:"node_id"` 22 | Name string `json:"name"` 23 | FullName string `json:"full_name"` 24 | Private bool `json:"private"` 25 | Owner struct { 26 | Login string `json:"login"` 27 | ID int `json:"id"` 28 | NodeID string `json:"node_id"` 29 | AvatarURL string `json:"avatar_url"` 30 | GravatarID string `json:"gravatar_id"` 31 | URL string `json:"url"` 32 | HTMLURL string `json:"html_url"` 33 | FollowersURL string `json:"followers_url"` 34 | FollowingURL string `json:"following_url"` 35 | GistsURL string `json:"gists_url"` 36 | StarredURL string `json:"starred_url"` 37 | SubscriptionsURL string `json:"subscriptions_url"` 38 | OrganizationsURL string `json:"organizations_url"` 39 | ReposURL string `json:"repos_url"` 40 | EventsURL string `json:"events_url"` 41 | ReceivedEventsURL string `json:"received_events_url"` 42 | Type string `json:"type"` 43 | SiteAdmin bool `json:"site_admin"` 44 | } `json:"owner"` 45 | HTMLURL string `json:"html_url"` 46 | Description string `json:"description"` 47 | Fork bool `json:"fork"` 48 | URL string `json:"url"` 49 | ForksURL string `json:"forks_url"` 50 | KeysURL string `json:"keys_url"` 51 | CollaboratorsURL string `json:"collaborators_url"` 52 | TeamsURL string `json:"teams_url"` 53 | HooksURL string `json:"hooks_url"` 54 | IssueEventsURL string `json:"issue_events_url"` 55 | EventsURL string `json:"events_url"` 56 | AssigneesURL string `json:"assignees_url"` 57 | BranchesURL string `json:"branches_url"` 58 | TagsURL string `json:"tags_url"` 59 | BlobsURL string `json:"blobs_url"` 60 | GitTagsURL string `json:"git_tags_url"` 61 | GitRefsURL string `json:"git_refs_url"` 62 | TreesURL string `json:"trees_url"` 63 | StatusesURL string `json:"statuses_url"` 64 | LanguagesURL string `json:"languages_url"` 65 | StargazersURL string `json:"stargazers_url"` 66 | ContributorsURL string `json:"contributors_url"` 67 | SubscribersURL string `json:"subscribers_url"` 68 | SubscriptionURL string `json:"subscription_url"` 69 | CommitsURL string `json:"commits_url"` 70 | GitCommitsURL string `json:"git_commits_url"` 71 | CommentsURL string `json:"comments_url"` 72 | IssueCommentURL string `json:"issue_comment_url"` 73 | ContentsURL string `json:"contents_url"` 74 | CompareURL string `json:"compare_url"` 75 | MergesURL string `json:"merges_url"` 76 | ArchiveURL string `json:"archive_url"` 77 | DownloadsURL string `json:"downloads_url"` 78 | IssuesURL string `json:"issues_url"` 79 | PullsURL string `json:"pulls_url"` 80 | MilestonesURL string `json:"milestones_url"` 81 | NotificationsURL string `json:"notifications_url"` 82 | LabelsURL string `json:"labels_url"` 83 | ReleasesURL string `json:"releases_url"` 84 | DeploymentsURL string `json:"deployments_url"` 85 | CreatedAt time.Time `json:"created_at"` 86 | UpdatedAt time.Time `json:"updated_at"` 87 | PushedAt time.Time `json:"pushed_at"` 88 | GitURL string `json:"git_url"` 89 | SSHURL string `json:"ssh_url"` 90 | CloneURL string `json:"clone_url"` 91 | SvnURL string `json:"svn_url"` 92 | Homepage string `json:"homepage"` 93 | Size int `json:"size"` 94 | StargazersCount int `json:"stargazers_count"` 95 | WatchersCount int `json:"watchers_count"` 96 | Language string `json:"language"` 97 | HasIssues bool `json:"has_issues"` 98 | HasProjects bool `json:"has_projects"` 99 | HasDownloads bool `json:"has_downloads"` 100 | HasWiki bool `json:"has_wiki"` 101 | HasPages bool `json:"has_pages"` 102 | ForksCount int `json:"forks_count"` 103 | MirrorURL interface{} `json:"mirror_url"` 104 | Archived bool `json:"archived"` 105 | OpenIssuesCount int `json:"open_issues_count"` 106 | License struct { 107 | Key string `json:"key"` 108 | Name string `json:"name"` 109 | SpdxID string `json:"spdx_id"` 110 | URL string `json:"url"` 111 | NodeID string `json:"node_id"` 112 | } `json:"license"` 113 | Forks int `json:"forks"` 114 | OpenIssues int `json:"open_issues"` 115 | Watchers int `json:"watchers"` 116 | DefaultBranch string `json:"default_branch"` 117 | } `json:"repository"` 118 | Sender struct { 119 | Login string `json:"login"` 120 | ID int `json:"id"` 121 | NodeID string `json:"node_id"` 122 | AvatarURL string `json:"avatar_url"` 123 | GravatarID string `json:"gravatar_id"` 124 | URL string `json:"url"` 125 | HTMLURL string `json:"html_url"` 126 | FollowersURL string `json:"followers_url"` 127 | FollowingURL string `json:"following_url"` 128 | GistsURL string `json:"gists_url"` 129 | StarredURL string `json:"starred_url"` 130 | SubscriptionsURL string `json:"subscriptions_url"` 131 | OrganizationsURL string `json:"organizations_url"` 132 | ReposURL string `json:"repos_url"` 133 | EventsURL string `json:"events_url"` 134 | ReceivedEventsURL string `json:"received_events_url"` 135 | Type string `json:"type"` 136 | SiteAdmin bool `json:"site_admin"` 137 | } `json:"sender"` 138 | } 139 | 140 | // LoadFromJSON update object from json 141 | func (e *Create) LoadFromJSON(data []byte) (bool, error) { 142 | err := json.Unmarshal(data, &e) 143 | if err != nil { 144 | return false, err 145 | } 146 | return true, nil 147 | } 148 | 149 | // ConvertToJSON convert object to json 150 | func (e *Create) ConvertToJSON() (string, error) { 151 | data, err := json.Marshal(&e) 152 | if err != nil { 153 | return "", err 154 | } 155 | return string(data), nil 156 | } 157 | -------------------------------------------------------------------------------- /internal/app/event/delete.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | "time" 10 | ) 11 | 12 | // Delete event received any time a Branch or Tag is deleted. 13 | type Delete struct { 14 | Ref string `json:"ref"` 15 | RefType string `json:"ref_type"` 16 | PusherType string `json:"pusher_type"` 17 | Repository struct { 18 | ID int `json:"id"` 19 | NodeID string `json:"node_id"` 20 | Name string `json:"name"` 21 | FullName string `json:"full_name"` 22 | Private bool `json:"private"` 23 | Owner struct { 24 | Login string `json:"login"` 25 | ID int `json:"id"` 26 | NodeID string `json:"node_id"` 27 | AvatarURL string `json:"avatar_url"` 28 | GravatarID string `json:"gravatar_id"` 29 | URL string `json:"url"` 30 | HTMLURL string `json:"html_url"` 31 | FollowersURL string `json:"followers_url"` 32 | FollowingURL string `json:"following_url"` 33 | GistsURL string `json:"gists_url"` 34 | StarredURL string `json:"starred_url"` 35 | SubscriptionsURL string `json:"subscriptions_url"` 36 | OrganizationsURL string `json:"organizations_url"` 37 | ReposURL string `json:"repos_url"` 38 | EventsURL string `json:"events_url"` 39 | ReceivedEventsURL string `json:"received_events_url"` 40 | Type string `json:"type"` 41 | SiteAdmin bool `json:"site_admin"` 42 | } `json:"owner"` 43 | HTMLURL string `json:"html_url"` 44 | Description string `json:"description"` 45 | Fork bool `json:"fork"` 46 | URL string `json:"url"` 47 | ForksURL string `json:"forks_url"` 48 | KeysURL string `json:"keys_url"` 49 | CollaboratorsURL string `json:"collaborators_url"` 50 | TeamsURL string `json:"teams_url"` 51 | HooksURL string `json:"hooks_url"` 52 | IssueEventsURL string `json:"issue_events_url"` 53 | EventsURL string `json:"events_url"` 54 | AssigneesURL string `json:"assignees_url"` 55 | BranchesURL string `json:"branches_url"` 56 | TagsURL string `json:"tags_url"` 57 | BlobsURL string `json:"blobs_url"` 58 | GitTagsURL string `json:"git_tags_url"` 59 | GitRefsURL string `json:"git_refs_url"` 60 | TreesURL string `json:"trees_url"` 61 | StatusesURL string `json:"statuses_url"` 62 | LanguagesURL string `json:"languages_url"` 63 | StargazersURL string `json:"stargazers_url"` 64 | ContributorsURL string `json:"contributors_url"` 65 | SubscribersURL string `json:"subscribers_url"` 66 | SubscriptionURL string `json:"subscription_url"` 67 | CommitsURL string `json:"commits_url"` 68 | GitCommitsURL string `json:"git_commits_url"` 69 | CommentsURL string `json:"comments_url"` 70 | IssueCommentURL string `json:"issue_comment_url"` 71 | ContentsURL string `json:"contents_url"` 72 | CompareURL string `json:"compare_url"` 73 | MergesURL string `json:"merges_url"` 74 | ArchiveURL string `json:"archive_url"` 75 | DownloadsURL string `json:"downloads_url"` 76 | IssuesURL string `json:"issues_url"` 77 | PullsURL string `json:"pulls_url"` 78 | MilestonesURL string `json:"milestones_url"` 79 | NotificationsURL string `json:"notifications_url"` 80 | LabelsURL string `json:"labels_url"` 81 | ReleasesURL string `json:"releases_url"` 82 | DeploymentsURL string `json:"deployments_url"` 83 | CreatedAt time.Time `json:"created_at"` 84 | UpdatedAt time.Time `json:"updated_at"` 85 | PushedAt time.Time `json:"pushed_at"` 86 | GitURL string `json:"git_url"` 87 | SSHURL string `json:"ssh_url"` 88 | CloneURL string `json:"clone_url"` 89 | SvnURL string `json:"svn_url"` 90 | Homepage string `json:"homepage"` 91 | Size int `json:"size"` 92 | StargazersCount int `json:"stargazers_count"` 93 | WatchersCount int `json:"watchers_count"` 94 | Language string `json:"language"` 95 | HasIssues bool `json:"has_issues"` 96 | HasProjects bool `json:"has_projects"` 97 | HasDownloads bool `json:"has_downloads"` 98 | HasWiki bool `json:"has_wiki"` 99 | HasPages bool `json:"has_pages"` 100 | ForksCount int `json:"forks_count"` 101 | MirrorURL interface{} `json:"mirror_url"` 102 | Archived bool `json:"archived"` 103 | OpenIssuesCount int `json:"open_issues_count"` 104 | License struct { 105 | Key string `json:"key"` 106 | Name string `json:"name"` 107 | SpdxID string `json:"spdx_id"` 108 | URL string `json:"url"` 109 | NodeID string `json:"node_id"` 110 | } `json:"license"` 111 | Forks int `json:"forks"` 112 | OpenIssues int `json:"open_issues"` 113 | Watchers int `json:"watchers"` 114 | DefaultBranch string `json:"default_branch"` 115 | } `json:"repository"` 116 | Sender struct { 117 | Login string `json:"login"` 118 | ID int `json:"id"` 119 | NodeID string `json:"node_id"` 120 | AvatarURL string `json:"avatar_url"` 121 | GravatarID string `json:"gravatar_id"` 122 | URL string `json:"url"` 123 | HTMLURL string `json:"html_url"` 124 | FollowersURL string `json:"followers_url"` 125 | FollowingURL string `json:"following_url"` 126 | GistsURL string `json:"gists_url"` 127 | StarredURL string `json:"starred_url"` 128 | SubscriptionsURL string `json:"subscriptions_url"` 129 | OrganizationsURL string `json:"organizations_url"` 130 | ReposURL string `json:"repos_url"` 131 | EventsURL string `json:"events_url"` 132 | ReceivedEventsURL string `json:"received_events_url"` 133 | Type string `json:"type"` 134 | SiteAdmin bool `json:"site_admin"` 135 | } `json:"sender"` 136 | } 137 | 138 | // LoadFromJSON update object from json 139 | func (e *Delete) LoadFromJSON(data []byte) (bool, error) { 140 | err := json.Unmarshal(data, &e) 141 | if err != nil { 142 | return false, err 143 | } 144 | return true, nil 145 | } 146 | 147 | // ConvertToJSON convert object to json 148 | func (e *Delete) ConvertToJSON() (string, error) { 149 | data, err := json.Marshal(&e) 150 | if err != nil { 151 | return "", err 152 | } 153 | return string(data), nil 154 | } 155 | -------------------------------------------------------------------------------- /internal/app/event/deployment.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Deployment event received any time a Repository has a new deployment created from the API. 12 | type Deployment struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *Deployment) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *Deployment) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/deployment_status.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // DeploymentStatus event received any time a deployment for a Repository has a status update from the API. 12 | type DeploymentStatus struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *DeploymentStatus) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *DeploymentStatus) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/fork.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Fork event received any time a Repository is forked. 12 | type Fork struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *Fork) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *Fork) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/github_app_authorization.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // GithubAppAuthorization event received any time someone revokes their authorization of a GitHub App. GitHub Apps receive this webhook by default and cannot unsubscribe from this event. 12 | type GithubAppAuthorization struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *GithubAppAuthorization) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *GithubAppAuthorization) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/gollum.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Gollum event received any time a Wiki page is updated. 12 | type Gollum struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *Gollum) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *Gollum) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/installation.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Installation event received any time a GitHub App is installed or uninstalled. 12 | type Installation struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *Installation) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *Installation) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/installation_repositories.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // InstallationRepositories event received any time a repository is added or removed from an installation. 12 | type InstallationRepositories struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *InstallationRepositories) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *InstallationRepositories) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/issue_comment.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | "time" 10 | ) 11 | 12 | // IssueComment event received any time a comment on an issue is created, edited, or deleted. 13 | type IssueComment struct { 14 | Action string `json:"action"` 15 | Issue struct { 16 | URL string `json:"url"` 17 | RepositoryURL string `json:"repository_url"` 18 | LabelsURL string `json:"labels_url"` 19 | CommentsURL string `json:"comments_url"` 20 | EventsURL string `json:"events_url"` 21 | HTMLURL string `json:"html_url"` 22 | ID int `json:"id"` 23 | NodeID string `json:"node_id"` 24 | Number int `json:"number"` 25 | Title string `json:"title"` 26 | User struct { 27 | Login string `json:"login"` 28 | ID int `json:"id"` 29 | NodeID string `json:"node_id"` 30 | AvatarURL string `json:"avatar_url"` 31 | GravatarID string `json:"gravatar_id"` 32 | URL string `json:"url"` 33 | HTMLURL string `json:"html_url"` 34 | FollowersURL string `json:"followers_url"` 35 | FollowingURL string `json:"following_url"` 36 | GistsURL string `json:"gists_url"` 37 | StarredURL string `json:"starred_url"` 38 | SubscriptionsURL string `json:"subscriptions_url"` 39 | OrganizationsURL string `json:"organizations_url"` 40 | ReposURL string `json:"repos_url"` 41 | EventsURL string `json:"events_url"` 42 | ReceivedEventsURL string `json:"received_events_url"` 43 | Type string `json:"type"` 44 | SiteAdmin bool `json:"site_admin"` 45 | } `json:"user"` 46 | Labels []interface{} `json:"labels"` 47 | State string `json:"state"` 48 | Locked bool `json:"locked"` 49 | Assignee interface{} `json:"assignee"` 50 | Assignees []interface{} `json:"assignees"` 51 | Milestone interface{} `json:"milestone"` 52 | Comments int `json:"comments"` 53 | CreatedAt time.Time `json:"created_at"` 54 | UpdatedAt time.Time `json:"updated_at"` 55 | ClosedAt time.Time `json:"closed_at"` 56 | AuthorAssociation string `json:"author_association"` 57 | Body string `json:"body"` 58 | } `json:"issue"` 59 | Comment struct { 60 | URL string `json:"url"` 61 | HTMLURL string `json:"html_url"` 62 | IssueURL string `json:"issue_url"` 63 | ID int `json:"id"` 64 | NodeID string `json:"node_id"` 65 | User struct { 66 | Login string `json:"login"` 67 | ID int `json:"id"` 68 | NodeID string `json:"node_id"` 69 | AvatarURL string `json:"avatar_url"` 70 | GravatarID string `json:"gravatar_id"` 71 | URL string `json:"url"` 72 | HTMLURL string `json:"html_url"` 73 | FollowersURL string `json:"followers_url"` 74 | FollowingURL string `json:"following_url"` 75 | GistsURL string `json:"gists_url"` 76 | StarredURL string `json:"starred_url"` 77 | SubscriptionsURL string `json:"subscriptions_url"` 78 | OrganizationsURL string `json:"organizations_url"` 79 | ReposURL string `json:"repos_url"` 80 | EventsURL string `json:"events_url"` 81 | ReceivedEventsURL string `json:"received_events_url"` 82 | Type string `json:"type"` 83 | SiteAdmin bool `json:"site_admin"` 84 | } `json:"user"` 85 | CreatedAt time.Time `json:"created_at"` 86 | UpdatedAt time.Time `json:"updated_at"` 87 | AuthorAssociation string `json:"author_association"` 88 | Body string `json:"body"` 89 | } `json:"comment"` 90 | Repository struct { 91 | ID int `json:"id"` 92 | NodeID string `json:"node_id"` 93 | Name string `json:"name"` 94 | FullName string `json:"full_name"` 95 | Private bool `json:"private"` 96 | Owner struct { 97 | Login string `json:"login"` 98 | ID int `json:"id"` 99 | NodeID string `json:"node_id"` 100 | AvatarURL string `json:"avatar_url"` 101 | GravatarID string `json:"gravatar_id"` 102 | URL string `json:"url"` 103 | HTMLURL string `json:"html_url"` 104 | FollowersURL string `json:"followers_url"` 105 | FollowingURL string `json:"following_url"` 106 | GistsURL string `json:"gists_url"` 107 | StarredURL string `json:"starred_url"` 108 | SubscriptionsURL string `json:"subscriptions_url"` 109 | OrganizationsURL string `json:"organizations_url"` 110 | ReposURL string `json:"repos_url"` 111 | EventsURL string `json:"events_url"` 112 | ReceivedEventsURL string `json:"received_events_url"` 113 | Type string `json:"type"` 114 | SiteAdmin bool `json:"site_admin"` 115 | } `json:"owner"` 116 | HTMLURL string `json:"html_url"` 117 | Description string `json:"description"` 118 | Fork bool `json:"fork"` 119 | URL string `json:"url"` 120 | ForksURL string `json:"forks_url"` 121 | KeysURL string `json:"keys_url"` 122 | CollaboratorsURL string `json:"collaborators_url"` 123 | TeamsURL string `json:"teams_url"` 124 | HooksURL string `json:"hooks_url"` 125 | IssueEventsURL string `json:"issue_events_url"` 126 | EventsURL string `json:"events_url"` 127 | AssigneesURL string `json:"assignees_url"` 128 | BranchesURL string `json:"branches_url"` 129 | TagsURL string `json:"tags_url"` 130 | BlobsURL string `json:"blobs_url"` 131 | GitTagsURL string `json:"git_tags_url"` 132 | GitRefsURL string `json:"git_refs_url"` 133 | TreesURL string `json:"trees_url"` 134 | StatusesURL string `json:"statuses_url"` 135 | LanguagesURL string `json:"languages_url"` 136 | StargazersURL string `json:"stargazers_url"` 137 | ContributorsURL string `json:"contributors_url"` 138 | SubscribersURL string `json:"subscribers_url"` 139 | SubscriptionURL string `json:"subscription_url"` 140 | CommitsURL string `json:"commits_url"` 141 | GitCommitsURL string `json:"git_commits_url"` 142 | CommentsURL string `json:"comments_url"` 143 | IssueCommentURL string `json:"issue_comment_url"` 144 | ContentsURL string `json:"contents_url"` 145 | CompareURL string `json:"compare_url"` 146 | MergesURL string `json:"merges_url"` 147 | ArchiveURL string `json:"archive_url"` 148 | DownloadsURL string `json:"downloads_url"` 149 | IssuesURL string `json:"issues_url"` 150 | PullsURL string `json:"pulls_url"` 151 | MilestonesURL string `json:"milestones_url"` 152 | NotificationsURL string `json:"notifications_url"` 153 | LabelsURL string `json:"labels_url"` 154 | ReleasesURL string `json:"releases_url"` 155 | DeploymentsURL string `json:"deployments_url"` 156 | CreatedAt time.Time `json:"created_at"` 157 | UpdatedAt time.Time `json:"updated_at"` 158 | PushedAt time.Time `json:"pushed_at"` 159 | GitURL string `json:"git_url"` 160 | SSHURL string `json:"ssh_url"` 161 | CloneURL string `json:"clone_url"` 162 | SvnURL string `json:"svn_url"` 163 | Homepage string `json:"homepage"` 164 | Size int `json:"size"` 165 | StargazersCount int `json:"stargazers_count"` 166 | WatchersCount int `json:"watchers_count"` 167 | Language interface{} `json:"language"` 168 | HasIssues bool `json:"has_issues"` 169 | HasProjects bool `json:"has_projects"` 170 | HasDownloads bool `json:"has_downloads"` 171 | HasWiki bool `json:"has_wiki"` 172 | HasPages bool `json:"has_pages"` 173 | ForksCount int `json:"forks_count"` 174 | MirrorURL interface{} `json:"mirror_url"` 175 | Archived bool `json:"archived"` 176 | OpenIssuesCount int `json:"open_issues_count"` 177 | License struct { 178 | Key string `json:"key"` 179 | Name string `json:"name"` 180 | SpdxID string `json:"spdx_id"` 181 | URL string `json:"url"` 182 | NodeID string `json:"node_id"` 183 | } `json:"license"` 184 | Forks int `json:"forks"` 185 | OpenIssues int `json:"open_issues"` 186 | Watchers int `json:"watchers"` 187 | DefaultBranch string `json:"default_branch"` 188 | } `json:"repository"` 189 | Sender struct { 190 | Login string `json:"login"` 191 | ID int `json:"id"` 192 | NodeID string `json:"node_id"` 193 | AvatarURL string `json:"avatar_url"` 194 | GravatarID string `json:"gravatar_id"` 195 | URL string `json:"url"` 196 | HTMLURL string `json:"html_url"` 197 | FollowersURL string `json:"followers_url"` 198 | FollowingURL string `json:"following_url"` 199 | GistsURL string `json:"gists_url"` 200 | StarredURL string `json:"starred_url"` 201 | SubscriptionsURL string `json:"subscriptions_url"` 202 | OrganizationsURL string `json:"organizations_url"` 203 | ReposURL string `json:"repos_url"` 204 | EventsURL string `json:"events_url"` 205 | ReceivedEventsURL string `json:"received_events_url"` 206 | Type string `json:"type"` 207 | SiteAdmin bool `json:"site_admin"` 208 | } `json:"sender"` 209 | } 210 | 211 | // LoadFromJSON update object from json 212 | func (e *IssueComment) LoadFromJSON(data []byte) (bool, error) { 213 | err := json.Unmarshal(data, &e) 214 | if err != nil { 215 | return false, err 216 | } 217 | return true, nil 218 | } 219 | 220 | // ConvertToJSON convert object to json 221 | func (e *IssueComment) ConvertToJSON() (string, error) { 222 | data, err := json.Marshal(&e) 223 | if err != nil { 224 | return "", err 225 | } 226 | return string(data), nil 227 | } 228 | -------------------------------------------------------------------------------- /internal/app/event/issue_comment_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "github.com/nbio/st" 9 | "io/ioutil" 10 | "testing" 11 | ) 12 | 13 | // TestIssueComment test cases 14 | func TestIssueComment(t *testing.T) { 15 | 16 | var issueComment IssueComment 17 | 18 | dat, err := ioutil.ReadFile("../../../fixtures/issue_comment.json") 19 | 20 | if err != nil { 21 | t.Errorf("File fixtures/issue_comment.json is invalid!") 22 | } 23 | 24 | ok, _ := issueComment.LoadFromJSON(dat) 25 | 26 | if !ok { 27 | t.Errorf("Testing with file fixtures/issue_comment.json is invalid") 28 | } 29 | 30 | st.Expect(t, issueComment.Issue.User.Login, "Clivern") 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/issues.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | "time" 10 | ) 11 | 12 | // Issues event received any time an Issue is assigned, unassigned, labeled, unlabeled, opened, edited, milestoned, demilestoned, closed, or reopened. 13 | type Issues struct { 14 | Action string `json:"action"` 15 | Issue struct { 16 | URL string `json:"url"` 17 | RepositoryURL string `json:"repository_url"` 18 | LabelsURL string `json:"labels_url"` 19 | CommentsURL string `json:"comments_url"` 20 | EventsURL string `json:"events_url"` 21 | HTMLURL string `json:"html_url"` 22 | ID int `json:"id"` 23 | NodeID string `json:"node_id"` 24 | Number int `json:"number"` 25 | Title string `json:"title"` 26 | User struct { 27 | Login string `json:"login"` 28 | ID int `json:"id"` 29 | NodeID string `json:"node_id"` 30 | AvatarURL string `json:"avatar_url"` 31 | GravatarID string `json:"gravatar_id"` 32 | URL string `json:"url"` 33 | HTMLURL string `json:"html_url"` 34 | FollowersURL string `json:"followers_url"` 35 | FollowingURL string `json:"following_url"` 36 | GistsURL string `json:"gists_url"` 37 | StarredURL string `json:"starred_url"` 38 | SubscriptionsURL string `json:"subscriptions_url"` 39 | OrganizationsURL string `json:"organizations_url"` 40 | ReposURL string `json:"repos_url"` 41 | EventsURL string `json:"events_url"` 42 | ReceivedEventsURL string `json:"received_events_url"` 43 | Type string `json:"type"` 44 | SiteAdmin bool `json:"site_admin"` 45 | } `json:"user"` 46 | Labels []interface{} `json:"labels"` 47 | State string `json:"state"` 48 | Locked bool `json:"locked"` 49 | Assignee interface{} `json:"assignee"` 50 | Assignees []interface{} `json:"assignees"` 51 | Milestone interface{} `json:"milestone"` 52 | Comments int `json:"comments"` 53 | CreatedAt time.Time `json:"created_at"` 54 | UpdatedAt time.Time `json:"updated_at"` 55 | ClosedAt interface{} `json:"closed_at"` 56 | AuthorAssociation string `json:"author_association"` 57 | Body string `json:"body"` 58 | } `json:"issue"` 59 | Repository struct { 60 | ID int `json:"id"` 61 | NodeID string `json:"node_id"` 62 | Name string `json:"name"` 63 | FullName string `json:"full_name"` 64 | Private bool `json:"private"` 65 | Owner struct { 66 | Login string `json:"login"` 67 | ID int `json:"id"` 68 | NodeID string `json:"node_id"` 69 | AvatarURL string `json:"avatar_url"` 70 | GravatarID string `json:"gravatar_id"` 71 | URL string `json:"url"` 72 | HTMLURL string `json:"html_url"` 73 | FollowersURL string `json:"followers_url"` 74 | FollowingURL string `json:"following_url"` 75 | GistsURL string `json:"gists_url"` 76 | StarredURL string `json:"starred_url"` 77 | SubscriptionsURL string `json:"subscriptions_url"` 78 | OrganizationsURL string `json:"organizations_url"` 79 | ReposURL string `json:"repos_url"` 80 | EventsURL string `json:"events_url"` 81 | ReceivedEventsURL string `json:"received_events_url"` 82 | Type string `json:"type"` 83 | SiteAdmin bool `json:"site_admin"` 84 | } `json:"owner"` 85 | HTMLURL string `json:"html_url"` 86 | Description string `json:"description"` 87 | Fork bool `json:"fork"` 88 | URL string `json:"url"` 89 | ForksURL string `json:"forks_url"` 90 | KeysURL string `json:"keys_url"` 91 | CollaboratorsURL string `json:"collaborators_url"` 92 | TeamsURL string `json:"teams_url"` 93 | HooksURL string `json:"hooks_url"` 94 | IssueEventsURL string `json:"issue_events_url"` 95 | EventsURL string `json:"events_url"` 96 | AssigneesURL string `json:"assignees_url"` 97 | BranchesURL string `json:"branches_url"` 98 | TagsURL string `json:"tags_url"` 99 | BlobsURL string `json:"blobs_url"` 100 | GitTagsURL string `json:"git_tags_url"` 101 | GitRefsURL string `json:"git_refs_url"` 102 | TreesURL string `json:"trees_url"` 103 | StatusesURL string `json:"statuses_url"` 104 | LanguagesURL string `json:"languages_url"` 105 | StargazersURL string `json:"stargazers_url"` 106 | ContributorsURL string `json:"contributors_url"` 107 | SubscribersURL string `json:"subscribers_url"` 108 | SubscriptionURL string `json:"subscription_url"` 109 | CommitsURL string `json:"commits_url"` 110 | GitCommitsURL string `json:"git_commits_url"` 111 | CommentsURL string `json:"comments_url"` 112 | IssueCommentURL string `json:"issue_comment_url"` 113 | ContentsURL string `json:"contents_url"` 114 | CompareURL string `json:"compare_url"` 115 | MergesURL string `json:"merges_url"` 116 | ArchiveURL string `json:"archive_url"` 117 | DownloadsURL string `json:"downloads_url"` 118 | IssuesURL string `json:"issues_url"` 119 | PullsURL string `json:"pulls_url"` 120 | MilestonesURL string `json:"milestones_url"` 121 | NotificationsURL string `json:"notifications_url"` 122 | LabelsURL string `json:"labels_url"` 123 | ReleasesURL string `json:"releases_url"` 124 | DeploymentsURL string `json:"deployments_url"` 125 | CreatedAt time.Time `json:"created_at"` 126 | UpdatedAt time.Time `json:"updated_at"` 127 | PushedAt time.Time `json:"pushed_at"` 128 | GitURL string `json:"git_url"` 129 | SSHURL string `json:"ssh_url"` 130 | CloneURL string `json:"clone_url"` 131 | SvnURL string `json:"svn_url"` 132 | Homepage string `json:"homepage"` 133 | Size int `json:"size"` 134 | StargazersCount int `json:"stargazers_count"` 135 | WatchersCount int `json:"watchers_count"` 136 | Language interface{} `json:"language"` 137 | HasIssues bool `json:"has_issues"` 138 | HasProjects bool `json:"has_projects"` 139 | HasDownloads bool `json:"has_downloads"` 140 | HasWiki bool `json:"has_wiki"` 141 | HasPages bool `json:"has_pages"` 142 | ForksCount int `json:"forks_count"` 143 | MirrorURL interface{} `json:"mirror_url"` 144 | Archived bool `json:"archived"` 145 | OpenIssuesCount int `json:"open_issues_count"` 146 | License struct { 147 | Key string `json:"key"` 148 | Name string `json:"name"` 149 | SpdxID string `json:"spdx_id"` 150 | URL string `json:"url"` 151 | NodeID string `json:"node_id"` 152 | } `json:"license"` 153 | Forks int `json:"forks"` 154 | OpenIssues int `json:"open_issues"` 155 | Watchers int `json:"watchers"` 156 | DefaultBranch string `json:"default_branch"` 157 | } `json:"repository"` 158 | Sender struct { 159 | Login string `json:"login"` 160 | ID int `json:"id"` 161 | NodeID string `json:"node_id"` 162 | AvatarURL string `json:"avatar_url"` 163 | GravatarID string `json:"gravatar_id"` 164 | URL string `json:"url"` 165 | HTMLURL string `json:"html_url"` 166 | FollowersURL string `json:"followers_url"` 167 | FollowingURL string `json:"following_url"` 168 | GistsURL string `json:"gists_url"` 169 | StarredURL string `json:"starred_url"` 170 | SubscriptionsURL string `json:"subscriptions_url"` 171 | OrganizationsURL string `json:"organizations_url"` 172 | ReposURL string `json:"repos_url"` 173 | EventsURL string `json:"events_url"` 174 | ReceivedEventsURL string `json:"received_events_url"` 175 | Type string `json:"type"` 176 | SiteAdmin bool `json:"site_admin"` 177 | } `json:"sender"` 178 | } 179 | 180 | // LoadFromJSON update object from json 181 | func (e *Issues) LoadFromJSON(data []byte) (bool, error) { 182 | err := json.Unmarshal(data, &e) 183 | if err != nil { 184 | return false, err 185 | } 186 | return true, nil 187 | } 188 | 189 | // ConvertToJSON convert object to json 190 | func (e *Issues) ConvertToJSON() (string, error) { 191 | data, err := json.Marshal(&e) 192 | if err != nil { 193 | return "", err 194 | } 195 | return string(data), nil 196 | } 197 | -------------------------------------------------------------------------------- /internal/app/event/issues_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "github.com/nbio/st" 9 | "io/ioutil" 10 | "testing" 11 | ) 12 | 13 | // TestIssues test cases 14 | func TestIssues(t *testing.T) { 15 | 16 | var issues Issues 17 | dat, err := ioutil.ReadFile("../../../fixtures/issues.json") 18 | 19 | if err != nil { 20 | t.Errorf("File fixtures/issues.json is invalid!") 21 | } 22 | 23 | ok, _ := issues.LoadFromJSON(dat) 24 | 25 | if !ok { 26 | t.Errorf("Testing with file fixtures/issues.json is invalid") 27 | } 28 | 29 | st.Expect(t, issues.Issue.User.Login, "Clivern") 30 | } 31 | -------------------------------------------------------------------------------- /internal/app/event/label.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | "time" 10 | ) 11 | 12 | // Label event received any time a Label is created, edited, or deleted. 13 | type Label struct { 14 | Action string `json:"action"` 15 | Label struct { 16 | ID int `json:"id"` 17 | NodeID string `json:"node_id"` 18 | URL string `json:"url"` 19 | Name string `json:"name"` 20 | Color string `json:"color"` 21 | Default bool `json:"default"` 22 | } `json:"label"` 23 | Repository struct { 24 | ID int `json:"id"` 25 | NodeID string `json:"node_id"` 26 | Name string `json:"name"` 27 | FullName string `json:"full_name"` 28 | Private bool `json:"private"` 29 | Owner struct { 30 | Login string `json:"login"` 31 | ID int `json:"id"` 32 | NodeID string `json:"node_id"` 33 | AvatarURL string `json:"avatar_url"` 34 | GravatarID string `json:"gravatar_id"` 35 | URL string `json:"url"` 36 | HTMLURL string `json:"html_url"` 37 | FollowersURL string `json:"followers_url"` 38 | FollowingURL string `json:"following_url"` 39 | GistsURL string `json:"gists_url"` 40 | StarredURL string `json:"starred_url"` 41 | SubscriptionsURL string `json:"subscriptions_url"` 42 | OrganizationsURL string `json:"organizations_url"` 43 | ReposURL string `json:"repos_url"` 44 | EventsURL string `json:"events_url"` 45 | ReceivedEventsURL string `json:"received_events_url"` 46 | Type string `json:"type"` 47 | SiteAdmin bool `json:"site_admin"` 48 | } `json:"owner"` 49 | HTMLURL string `json:"html_url"` 50 | Description string `json:"description"` 51 | Fork bool `json:"fork"` 52 | URL string `json:"url"` 53 | ForksURL string `json:"forks_url"` 54 | KeysURL string `json:"keys_url"` 55 | CollaboratorsURL string `json:"collaborators_url"` 56 | TeamsURL string `json:"teams_url"` 57 | HooksURL string `json:"hooks_url"` 58 | IssueEventsURL string `json:"issue_events_url"` 59 | EventsURL string `json:"events_url"` 60 | AssigneesURL string `json:"assignees_url"` 61 | BranchesURL string `json:"branches_url"` 62 | TagsURL string `json:"tags_url"` 63 | BlobsURL string `json:"blobs_url"` 64 | GitTagsURL string `json:"git_tags_url"` 65 | GitRefsURL string `json:"git_refs_url"` 66 | TreesURL string `json:"trees_url"` 67 | StatusesURL string `json:"statuses_url"` 68 | LanguagesURL string `json:"languages_url"` 69 | StargazersURL string `json:"stargazers_url"` 70 | ContributorsURL string `json:"contributors_url"` 71 | SubscribersURL string `json:"subscribers_url"` 72 | SubscriptionURL string `json:"subscription_url"` 73 | CommitsURL string `json:"commits_url"` 74 | GitCommitsURL string `json:"git_commits_url"` 75 | CommentsURL string `json:"comments_url"` 76 | IssueCommentURL string `json:"issue_comment_url"` 77 | ContentsURL string `json:"contents_url"` 78 | CompareURL string `json:"compare_url"` 79 | MergesURL string `json:"merges_url"` 80 | ArchiveURL string `json:"archive_url"` 81 | DownloadsURL string `json:"downloads_url"` 82 | IssuesURL string `json:"issues_url"` 83 | PullsURL string `json:"pulls_url"` 84 | MilestonesURL string `json:"milestones_url"` 85 | NotificationsURL string `json:"notifications_url"` 86 | LabelsURL string `json:"labels_url"` 87 | ReleasesURL string `json:"releases_url"` 88 | DeploymentsURL string `json:"deployments_url"` 89 | CreatedAt time.Time `json:"created_at"` 90 | UpdatedAt time.Time `json:"updated_at"` 91 | PushedAt time.Time `json:"pushed_at"` 92 | GitURL string `json:"git_url"` 93 | SSHURL string `json:"ssh_url"` 94 | CloneURL string `json:"clone_url"` 95 | SvnURL string `json:"svn_url"` 96 | Homepage string `json:"homepage"` 97 | Size int `json:"size"` 98 | StargazersCount int `json:"stargazers_count"` 99 | WatchersCount int `json:"watchers_count"` 100 | Language string `json:"language"` 101 | HasIssues bool `json:"has_issues"` 102 | HasProjects bool `json:"has_projects"` 103 | HasDownloads bool `json:"has_downloads"` 104 | HasWiki bool `json:"has_wiki"` 105 | HasPages bool `json:"has_pages"` 106 | ForksCount int `json:"forks_count"` 107 | MirrorURL interface{} `json:"mirror_url"` 108 | Archived bool `json:"archived"` 109 | OpenIssuesCount int `json:"open_issues_count"` 110 | License struct { 111 | Key string `json:"key"` 112 | Name string `json:"name"` 113 | SpdxID string `json:"spdx_id"` 114 | URL string `json:"url"` 115 | NodeID string `json:"node_id"` 116 | } `json:"license"` 117 | Forks int `json:"forks"` 118 | OpenIssues int `json:"open_issues"` 119 | Watchers int `json:"watchers"` 120 | DefaultBranch string `json:"default_branch"` 121 | } `json:"repository"` 122 | Sender struct { 123 | Login string `json:"login"` 124 | ID int `json:"id"` 125 | NodeID string `json:"node_id"` 126 | AvatarURL string `json:"avatar_url"` 127 | GravatarID string `json:"gravatar_id"` 128 | URL string `json:"url"` 129 | HTMLURL string `json:"html_url"` 130 | FollowersURL string `json:"followers_url"` 131 | FollowingURL string `json:"following_url"` 132 | GistsURL string `json:"gists_url"` 133 | StarredURL string `json:"starred_url"` 134 | SubscriptionsURL string `json:"subscriptions_url"` 135 | OrganizationsURL string `json:"organizations_url"` 136 | ReposURL string `json:"repos_url"` 137 | EventsURL string `json:"events_url"` 138 | ReceivedEventsURL string `json:"received_events_url"` 139 | Type string `json:"type"` 140 | SiteAdmin bool `json:"site_admin"` 141 | } `json:"sender"` 142 | } 143 | 144 | // LoadFromJSON update object from json 145 | func (e *Label) LoadFromJSON(data []byte) (bool, error) { 146 | err := json.Unmarshal(data, &e) 147 | if err != nil { 148 | return false, err 149 | } 150 | return true, nil 151 | } 152 | 153 | // ConvertToJSON convert object to json 154 | func (e *Label) ConvertToJSON() (string, error) { 155 | data, err := json.Marshal(&e) 156 | if err != nil { 157 | return "", err 158 | } 159 | return string(data), nil 160 | } 161 | -------------------------------------------------------------------------------- /internal/app/event/marketplace_purchase.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // MarketplacePurchase event received any time a user purchases, cancels, or changes their GitHub Marketplace plan. 12 | type MarketplacePurchase struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *MarketplacePurchase) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *MarketplacePurchase) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/member.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Member event received any time a user accepts an invitation or is removed as a collaborator to a repository, or has their permissions modified. 12 | type Member struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *Member) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *Member) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/membership.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Membership event received any time a User is added or removed from a team. Organization hooks only. 12 | type Membership struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *Membership) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *Membership) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/milestone.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | "time" 10 | ) 11 | 12 | // Milestone event received any time a Milestone is created, closed, opened, edited, or deleted. 13 | type Milestone struct { 14 | Action string `json:"action"` 15 | Milestone struct { 16 | URL string `json:"url"` 17 | HTMLURL string `json:"html_url"` 18 | LabelsURL string `json:"labels_url"` 19 | ID int `json:"id"` 20 | NodeID string `json:"node_id"` 21 | Number int `json:"number"` 22 | Title string `json:"title"` 23 | Description string `json:"description"` 24 | Creator struct { 25 | Login string `json:"login"` 26 | ID int `json:"id"` 27 | NodeID string `json:"node_id"` 28 | AvatarURL string `json:"avatar_url"` 29 | GravatarID string `json:"gravatar_id"` 30 | URL string `json:"url"` 31 | HTMLURL string `json:"html_url"` 32 | FollowersURL string `json:"followers_url"` 33 | FollowingURL string `json:"following_url"` 34 | GistsURL string `json:"gists_url"` 35 | StarredURL string `json:"starred_url"` 36 | SubscriptionsURL string `json:"subscriptions_url"` 37 | OrganizationsURL string `json:"organizations_url"` 38 | ReposURL string `json:"repos_url"` 39 | EventsURL string `json:"events_url"` 40 | ReceivedEventsURL string `json:"received_events_url"` 41 | Type string `json:"type"` 42 | SiteAdmin bool `json:"site_admin"` 43 | } `json:"creator"` 44 | OpenIssues int `json:"open_issues"` 45 | ClosedIssues int `json:"closed_issues"` 46 | State string `json:"state"` 47 | CreatedAt time.Time `json:"created_at"` 48 | UpdatedAt time.Time `json:"updated_at"` 49 | DueOn time.Time `json:"due_on"` 50 | ClosedAt interface{} `json:"closed_at"` 51 | } `json:"milestone"` 52 | Repository struct { 53 | ID int `json:"id"` 54 | NodeID string `json:"node_id"` 55 | Name string `json:"name"` 56 | FullName string `json:"full_name"` 57 | Private bool `json:"private"` 58 | Owner struct { 59 | Login string `json:"login"` 60 | ID int `json:"id"` 61 | NodeID string `json:"node_id"` 62 | AvatarURL string `json:"avatar_url"` 63 | GravatarID string `json:"gravatar_id"` 64 | URL string `json:"url"` 65 | HTMLURL string `json:"html_url"` 66 | FollowersURL string `json:"followers_url"` 67 | FollowingURL string `json:"following_url"` 68 | GistsURL string `json:"gists_url"` 69 | StarredURL string `json:"starred_url"` 70 | SubscriptionsURL string `json:"subscriptions_url"` 71 | OrganizationsURL string `json:"organizations_url"` 72 | ReposURL string `json:"repos_url"` 73 | EventsURL string `json:"events_url"` 74 | ReceivedEventsURL string `json:"received_events_url"` 75 | Type string `json:"type"` 76 | SiteAdmin bool `json:"site_admin"` 77 | } `json:"owner"` 78 | HTMLURL string `json:"html_url"` 79 | Description string `json:"description"` 80 | Fork bool `json:"fork"` 81 | URL string `json:"url"` 82 | ForksURL string `json:"forks_url"` 83 | KeysURL string `json:"keys_url"` 84 | CollaboratorsURL string `json:"collaborators_url"` 85 | TeamsURL string `json:"teams_url"` 86 | HooksURL string `json:"hooks_url"` 87 | IssueEventsURL string `json:"issue_events_url"` 88 | EventsURL string `json:"events_url"` 89 | AssigneesURL string `json:"assignees_url"` 90 | BranchesURL string `json:"branches_url"` 91 | TagsURL string `json:"tags_url"` 92 | BlobsURL string `json:"blobs_url"` 93 | GitTagsURL string `json:"git_tags_url"` 94 | GitRefsURL string `json:"git_refs_url"` 95 | TreesURL string `json:"trees_url"` 96 | StatusesURL string `json:"statuses_url"` 97 | LanguagesURL string `json:"languages_url"` 98 | StargazersURL string `json:"stargazers_url"` 99 | ContributorsURL string `json:"contributors_url"` 100 | SubscribersURL string `json:"subscribers_url"` 101 | SubscriptionURL string `json:"subscription_url"` 102 | CommitsURL string `json:"commits_url"` 103 | GitCommitsURL string `json:"git_commits_url"` 104 | CommentsURL string `json:"comments_url"` 105 | IssueCommentURL string `json:"issue_comment_url"` 106 | ContentsURL string `json:"contents_url"` 107 | CompareURL string `json:"compare_url"` 108 | MergesURL string `json:"merges_url"` 109 | ArchiveURL string `json:"archive_url"` 110 | DownloadsURL string `json:"downloads_url"` 111 | IssuesURL string `json:"issues_url"` 112 | PullsURL string `json:"pulls_url"` 113 | MilestonesURL string `json:"milestones_url"` 114 | NotificationsURL string `json:"notifications_url"` 115 | LabelsURL string `json:"labels_url"` 116 | ReleasesURL string `json:"releases_url"` 117 | DeploymentsURL string `json:"deployments_url"` 118 | CreatedAt time.Time `json:"created_at"` 119 | UpdatedAt time.Time `json:"updated_at"` 120 | PushedAt time.Time `json:"pushed_at"` 121 | GitURL string `json:"git_url"` 122 | SSHURL string `json:"ssh_url"` 123 | CloneURL string `json:"clone_url"` 124 | SvnURL string `json:"svn_url"` 125 | Homepage string `json:"homepage"` 126 | Size int `json:"size"` 127 | StargazersCount int `json:"stargazers_count"` 128 | WatchersCount int `json:"watchers_count"` 129 | Language string `json:"language"` 130 | HasIssues bool `json:"has_issues"` 131 | HasProjects bool `json:"has_projects"` 132 | HasDownloads bool `json:"has_downloads"` 133 | HasWiki bool `json:"has_wiki"` 134 | HasPages bool `json:"has_pages"` 135 | ForksCount int `json:"forks_count"` 136 | MirrorURL interface{} `json:"mirror_url"` 137 | Archived bool `json:"archived"` 138 | OpenIssuesCount int `json:"open_issues_count"` 139 | License struct { 140 | Key string `json:"key"` 141 | Name string `json:"name"` 142 | SpdxID string `json:"spdx_id"` 143 | URL string `json:"url"` 144 | NodeID string `json:"node_id"` 145 | } `json:"license"` 146 | Forks int `json:"forks"` 147 | OpenIssues int `json:"open_issues"` 148 | Watchers int `json:"watchers"` 149 | DefaultBranch string `json:"default_branch"` 150 | } `json:"repository"` 151 | Sender struct { 152 | Login string `json:"login"` 153 | ID int `json:"id"` 154 | NodeID string `json:"node_id"` 155 | AvatarURL string `json:"avatar_url"` 156 | GravatarID string `json:"gravatar_id"` 157 | URL string `json:"url"` 158 | HTMLURL string `json:"html_url"` 159 | FollowersURL string `json:"followers_url"` 160 | FollowingURL string `json:"following_url"` 161 | GistsURL string `json:"gists_url"` 162 | StarredURL string `json:"starred_url"` 163 | SubscriptionsURL string `json:"subscriptions_url"` 164 | OrganizationsURL string `json:"organizations_url"` 165 | ReposURL string `json:"repos_url"` 166 | EventsURL string `json:"events_url"` 167 | ReceivedEventsURL string `json:"received_events_url"` 168 | Type string `json:"type"` 169 | SiteAdmin bool `json:"site_admin"` 170 | } `json:"sender"` 171 | } 172 | 173 | // LoadFromJSON update object from json 174 | func (e *Milestone) LoadFromJSON(data []byte) (bool, error) { 175 | err := json.Unmarshal(data, &e) 176 | if err != nil { 177 | return false, err 178 | } 179 | return true, nil 180 | } 181 | 182 | // ConvertToJSON convert object to json 183 | func (e *Milestone) ConvertToJSON() (string, error) { 184 | data, err := json.Marshal(&e) 185 | if err != nil { 186 | return "", err 187 | } 188 | return string(data), nil 189 | } 190 | -------------------------------------------------------------------------------- /internal/app/event/org_block.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // OrgBlock event received any time an organization blocks or unblocks a user. Organization hooks only. 12 | type OrgBlock struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *OrgBlock) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *OrgBlock) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/organization.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Organization event received any time a user is added, removed, or invited to an Organization. Organization hooks only. 12 | type Organization struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *Organization) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *Organization) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/page_build.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // PageBuild event received any time a Pages site is built or results in a failed build. 12 | type PageBuild struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *PageBuild) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *PageBuild) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/project.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Project event received any time a Project is created, edited, closed, reopened, or deleted. 12 | type Project struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *Project) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *Project) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/project_card.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // ProjectCard event received any time a Project Card is created, edited, moved, converted to an issue, or deleted. 12 | type ProjectCard struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *ProjectCard) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *ProjectCard) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/project_column.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // ProjectColumn event received any time a Project Column is created, edited, moved, or deleted. 12 | type ProjectColumn struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *ProjectColumn) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *ProjectColumn) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/public.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Public event received any time a Repository changes from private to public. 12 | type Public struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *Public) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *Public) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/push.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | "time" 10 | ) 11 | 12 | // Push event received any Git push to a Repository, including editing tags or branches. 13 | // Commits via API actions that update references are also counted. This is the default event. 14 | type Push struct { 15 | Ref string `json:"ref"` 16 | Before string `json:"before"` 17 | After string `json:"after"` 18 | Created bool `json:"created"` 19 | Deleted bool `json:"deleted"` 20 | Forced bool `json:"forced"` 21 | BaseRef interface{} `json:"base_ref"` 22 | Compare string `json:"compare"` 23 | Commits []struct { 24 | ID string `json:"id"` 25 | TreeID string `json:"tree_id"` 26 | Distinct bool `json:"distinct"` 27 | Message string `json:"message"` 28 | Timestamp time.Time `json:"timestamp"` 29 | URL string `json:"url"` 30 | Author struct { 31 | Name string `json:"name"` 32 | Email string `json:"email"` 33 | Username string `json:"username"` 34 | } `json:"author"` 35 | Committer struct { 36 | Name string `json:"name"` 37 | Email string `json:"email"` 38 | Username string `json:"username"` 39 | } `json:"committer"` 40 | Added []string `json:"added"` 41 | Removed []string `json:"removed"` 42 | Modified []string `json:"modified"` 43 | } `json:"commits"` 44 | HeadCommit struct { 45 | ID string `json:"id"` 46 | TreeID string `json:"tree_id"` 47 | Distinct bool `json:"distinct"` 48 | Message string `json:"message"` 49 | Timestamp time.Time `json:"timestamp"` 50 | URL string `json:"url"` 51 | Author struct { 52 | Name string `json:"name"` 53 | Email string `json:"email"` 54 | Username string `json:"username"` 55 | } `json:"author"` 56 | Committer struct { 57 | Name string `json:"name"` 58 | Email string `json:"email"` 59 | Username string `json:"username"` 60 | } `json:"committer"` 61 | Added []string `json:"added"` 62 | Removed []string `json:"removed"` 63 | Modified []string `json:"modified"` 64 | } `json:"head_commit"` 65 | Repository struct { 66 | ID int `json:"id"` 67 | NodeID string `json:"node_id"` 68 | Name string `json:"name"` 69 | FullName string `json:"full_name"` 70 | Private bool `json:"private"` 71 | Owner struct { 72 | Name string `json:"name"` 73 | Email string `json:"email"` 74 | Login string `json:"login"` 75 | ID int `json:"id"` 76 | NodeID string `json:"node_id"` 77 | AvatarURL string `json:"avatar_url"` 78 | GravatarID string `json:"gravatar_id"` 79 | URL string `json:"url"` 80 | HTMLURL string `json:"html_url"` 81 | FollowersURL string `json:"followers_url"` 82 | FollowingURL string `json:"following_url"` 83 | GistsURL string `json:"gists_url"` 84 | StarredURL string `json:"starred_url"` 85 | SubscriptionsURL string `json:"subscriptions_url"` 86 | OrganizationsURL string `json:"organizations_url"` 87 | ReposURL string `json:"repos_url"` 88 | EventsURL string `json:"events_url"` 89 | ReceivedEventsURL string `json:"received_events_url"` 90 | Type string `json:"type"` 91 | SiteAdmin bool `json:"site_admin"` 92 | } `json:"owner"` 93 | HTMLURL string `json:"html_url"` 94 | Description string `json:"description"` 95 | Fork bool `json:"fork"` 96 | URL string `json:"url"` 97 | ForksURL string `json:"forks_url"` 98 | KeysURL string `json:"keys_url"` 99 | CollaboratorsURL string `json:"collaborators_url"` 100 | TeamsURL string `json:"teams_url"` 101 | HooksURL string `json:"hooks_url"` 102 | IssueEventsURL string `json:"issue_events_url"` 103 | EventsURL string `json:"events_url"` 104 | AssigneesURL string `json:"assignees_url"` 105 | BranchesURL string `json:"branches_url"` 106 | TagsURL string `json:"tags_url"` 107 | BlobsURL string `json:"blobs_url"` 108 | GitTagsURL string `json:"git_tags_url"` 109 | GitRefsURL string `json:"git_refs_url"` 110 | TreesURL string `json:"trees_url"` 111 | StatusesURL string `json:"statuses_url"` 112 | LanguagesURL string `json:"languages_url"` 113 | StargazersURL string `json:"stargazers_url"` 114 | ContributorsURL string `json:"contributors_url"` 115 | SubscribersURL string `json:"subscribers_url"` 116 | SubscriptionURL string `json:"subscription_url"` 117 | CommitsURL string `json:"commits_url"` 118 | GitCommitsURL string `json:"git_commits_url"` 119 | CommentsURL string `json:"comments_url"` 120 | IssueCommentURL string `json:"issue_comment_url"` 121 | ContentsURL string `json:"contents_url"` 122 | CompareURL string `json:"compare_url"` 123 | MergesURL string `json:"merges_url"` 124 | ArchiveURL string `json:"archive_url"` 125 | DownloadsURL string `json:"downloads_url"` 126 | IssuesURL string `json:"issues_url"` 127 | PullsURL string `json:"pulls_url"` 128 | MilestonesURL string `json:"milestones_url"` 129 | NotificationsURL string `json:"notifications_url"` 130 | LabelsURL string `json:"labels_url"` 131 | ReleasesURL string `json:"releases_url"` 132 | DeploymentsURL string `json:"deployments_url"` 133 | CreatedAt int `json:"created_at"` 134 | UpdatedAt time.Time `json:"updated_at"` 135 | PushedAt int `json:"pushed_at"` 136 | GitURL string `json:"git_url"` 137 | SSHURL string `json:"ssh_url"` 138 | CloneURL string `json:"clone_url"` 139 | SvnURL string `json:"svn_url"` 140 | Homepage string `json:"homepage"` 141 | Size int `json:"size"` 142 | StargazersCount int `json:"stargazers_count"` 143 | WatchersCount int `json:"watchers_count"` 144 | Language string `json:"language"` 145 | HasIssues bool `json:"has_issues"` 146 | HasProjects bool `json:"has_projects"` 147 | HasDownloads bool `json:"has_downloads"` 148 | HasWiki bool `json:"has_wiki"` 149 | HasPages bool `json:"has_pages"` 150 | ForksCount int `json:"forks_count"` 151 | MirrorURL interface{} `json:"mirror_url"` 152 | Archived bool `json:"archived"` 153 | OpenIssuesCount int `json:"open_issues_count"` 154 | License struct { 155 | Key string `json:"key"` 156 | Name string `json:"name"` 157 | SpdxID string `json:"spdx_id"` 158 | URL string `json:"url"` 159 | NodeID string `json:"node_id"` 160 | } `json:"license"` 161 | Forks int `json:"forks"` 162 | OpenIssues int `json:"open_issues"` 163 | Watchers int `json:"watchers"` 164 | DefaultBranch string `json:"default_branch"` 165 | Stargazers int `json:"stargazers"` 166 | MasterBranch string `json:"master_branch"` 167 | } `json:"repository"` 168 | Pusher struct { 169 | Name string `json:"name"` 170 | Email string `json:"email"` 171 | } `json:"pusher"` 172 | Sender struct { 173 | Login string `json:"login"` 174 | ID int `json:"id"` 175 | NodeID string `json:"node_id"` 176 | AvatarURL string `json:"avatar_url"` 177 | GravatarID string `json:"gravatar_id"` 178 | URL string `json:"url"` 179 | HTMLURL string `json:"html_url"` 180 | FollowersURL string `json:"followers_url"` 181 | FollowingURL string `json:"following_url"` 182 | GistsURL string `json:"gists_url"` 183 | StarredURL string `json:"starred_url"` 184 | SubscriptionsURL string `json:"subscriptions_url"` 185 | OrganizationsURL string `json:"organizations_url"` 186 | ReposURL string `json:"repos_url"` 187 | EventsURL string `json:"events_url"` 188 | ReceivedEventsURL string `json:"received_events_url"` 189 | Type string `json:"type"` 190 | SiteAdmin bool `json:"site_admin"` 191 | } `json:"sender"` 192 | } 193 | 194 | // LoadFromJSON update object from json 195 | func (e *Push) LoadFromJSON(data []byte) (bool, error) { 196 | err := json.Unmarshal(data, &e) 197 | if err != nil { 198 | return false, err 199 | } 200 | return true, nil 201 | } 202 | 203 | // ConvertToJSON convert object to json 204 | func (e *Push) ConvertToJSON() (string, error) { 205 | data, err := json.Marshal(&e) 206 | if err != nil { 207 | return "", err 208 | } 209 | return string(data), nil 210 | } 211 | -------------------------------------------------------------------------------- /internal/app/event/raw.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | // Raw event 8 | type Raw struct { 9 | Body string 10 | Event string 11 | } 12 | 13 | // SetBody set event body 14 | func (e *Raw) SetBody(body string) { 15 | e.Body = body 16 | } 17 | 18 | // GetBody gets event body 19 | func (e *Raw) GetBody() string { 20 | return e.Body 21 | } 22 | 23 | // SetEvent sets event 24 | func (e *Raw) SetEvent(event string) { 25 | e.Event = event 26 | } 27 | 28 | // GetEvent gets event 29 | func (e *Raw) GetEvent() string { 30 | return e.Event 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/release.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Release event received any time a Release is published in a Repository. 12 | type Release struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *Release) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *Release) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/repository.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Repository event received any time a Repository is created, deleted (organization hooks only), archived, unarchived, made public, or made private. 12 | type Repository struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *Repository) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *Repository) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/repository_import.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // RepositoryImport event received any time a successful or unsuccessful repository import finishes for a GitHub organization or a personal repository. 12 | type RepositoryImport struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *RepositoryImport) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *RepositoryImport) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/repository_vulnerability_alert.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // RepositoryVulnerabilityAlert event received any time a security alert is created, dismissed, or resolved. 12 | type RepositoryVulnerabilityAlert struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *RepositoryVulnerabilityAlert) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *RepositoryVulnerabilityAlert) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/status_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "github.com/nbio/st" 9 | "io/ioutil" 10 | "testing" 11 | ) 12 | 13 | // TestStatus test cases 14 | func TestStatus(t *testing.T) { 15 | 16 | var status Status 17 | 18 | dat, err := ioutil.ReadFile("../../../fixtures/status.json") 19 | 20 | if err != nil { 21 | t.Errorf("File fixtures/status.json is invalid!") 22 | } 23 | 24 | ok, _ := status.LoadFromJSON(dat) 25 | 26 | if !ok { 27 | t.Errorf("Testing with file fixtures/status.json is invalid") 28 | } 29 | 30 | st.Expect(t, status.Commit.Commit.Author.Name, "Clivern") 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/team.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Team event received any time a team is created, deleted, modified, or added to or removed from a repository. Organization hooks only 12 | type Team struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *Team) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *Team) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/team_add.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // TeamAdd event received any time a team is added or modified on a Repository. 12 | type TeamAdd struct { 13 | } 14 | 15 | // LoadFromJSON update object from json 16 | func (e *TeamAdd) LoadFromJSON(data []byte) (bool, error) { 17 | err := json.Unmarshal(data, &e) 18 | if err != nil { 19 | return false, err 20 | } 21 | return true, nil 22 | } 23 | 24 | // ConvertToJSON convert object to json 25 | func (e *TeamAdd) ConvertToJSON() (string, error) { 26 | data, err := json.Marshal(&e) 27 | if err != nil { 28 | return "", err 29 | } 30 | return string(data), nil 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/event/watch.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "encoding/json" 9 | "time" 10 | ) 11 | 12 | // Watch event received any time a User stars a Repository. 13 | type Watch struct { 14 | Action string `json:"action"` 15 | Repository struct { 16 | ID int `json:"id"` 17 | NodeID string `json:"node_id"` 18 | Name string `json:"name"` 19 | FullName string `json:"full_name"` 20 | Private bool `json:"private"` 21 | Owner struct { 22 | Login string `json:"login"` 23 | ID int `json:"id"` 24 | NodeID string `json:"node_id"` 25 | AvatarURL string `json:"avatar_url"` 26 | GravatarID string `json:"gravatar_id"` 27 | URL string `json:"url"` 28 | HTMLURL string `json:"html_url"` 29 | FollowersURL string `json:"followers_url"` 30 | FollowingURL string `json:"following_url"` 31 | GistsURL string `json:"gists_url"` 32 | StarredURL string `json:"starred_url"` 33 | SubscriptionsURL string `json:"subscriptions_url"` 34 | OrganizationsURL string `json:"organizations_url"` 35 | ReposURL string `json:"repos_url"` 36 | EventsURL string `json:"events_url"` 37 | ReceivedEventsURL string `json:"received_events_url"` 38 | Type string `json:"type"` 39 | SiteAdmin bool `json:"site_admin"` 40 | } `json:"owner"` 41 | HTMLURL string `json:"html_url"` 42 | Description string `json:"description"` 43 | Fork bool `json:"fork"` 44 | URL string `json:"url"` 45 | ForksURL string `json:"forks_url"` 46 | KeysURL string `json:"keys_url"` 47 | CollaboratorsURL string `json:"collaborators_url"` 48 | TeamsURL string `json:"teams_url"` 49 | HooksURL string `json:"hooks_url"` 50 | IssueEventsURL string `json:"issue_events_url"` 51 | EventsURL string `json:"events_url"` 52 | AssigneesURL string `json:"assignees_url"` 53 | BranchesURL string `json:"branches_url"` 54 | TagsURL string `json:"tags_url"` 55 | BlobsURL string `json:"blobs_url"` 56 | GitTagsURL string `json:"git_tags_url"` 57 | GitRefsURL string `json:"git_refs_url"` 58 | TreesURL string `json:"trees_url"` 59 | StatusesURL string `json:"statuses_url"` 60 | LanguagesURL string `json:"languages_url"` 61 | StargazersURL string `json:"stargazers_url"` 62 | ContributorsURL string `json:"contributors_url"` 63 | SubscribersURL string `json:"subscribers_url"` 64 | SubscriptionURL string `json:"subscription_url"` 65 | CommitsURL string `json:"commits_url"` 66 | GitCommitsURL string `json:"git_commits_url"` 67 | CommentsURL string `json:"comments_url"` 68 | IssueCommentURL string `json:"issue_comment_url"` 69 | ContentsURL string `json:"contents_url"` 70 | CompareURL string `json:"compare_url"` 71 | MergesURL string `json:"merges_url"` 72 | ArchiveURL string `json:"archive_url"` 73 | DownloadsURL string `json:"downloads_url"` 74 | IssuesURL string `json:"issues_url"` 75 | PullsURL string `json:"pulls_url"` 76 | MilestonesURL string `json:"milestones_url"` 77 | NotificationsURL string `json:"notifications_url"` 78 | LabelsURL string `json:"labels_url"` 79 | ReleasesURL string `json:"releases_url"` 80 | DeploymentsURL string `json:"deployments_url"` 81 | CreatedAt time.Time `json:"created_at"` 82 | UpdatedAt time.Time `json:"updated_at"` 83 | PushedAt time.Time `json:"pushed_at"` 84 | GitURL string `json:"git_url"` 85 | SSHURL string `json:"ssh_url"` 86 | CloneURL string `json:"clone_url"` 87 | SvnURL string `json:"svn_url"` 88 | Homepage string `json:"homepage"` 89 | Size int `json:"size"` 90 | StargazersCount int `json:"stargazers_count"` 91 | WatchersCount int `json:"watchers_count"` 92 | Language string `json:"language"` 93 | HasIssues bool `json:"has_issues"` 94 | HasProjects bool `json:"has_projects"` 95 | HasDownloads bool `json:"has_downloads"` 96 | HasWiki bool `json:"has_wiki"` 97 | HasPages bool `json:"has_pages"` 98 | ForksCount int `json:"forks_count"` 99 | MirrorURL interface{} `json:"mirror_url"` 100 | Archived bool `json:"archived"` 101 | OpenIssuesCount int `json:"open_issues_count"` 102 | License struct { 103 | Key string `json:"key"` 104 | Name string `json:"name"` 105 | SpdxID string `json:"spdx_id"` 106 | URL string `json:"url"` 107 | NodeID string `json:"node_id"` 108 | } `json:"license"` 109 | Forks int `json:"forks"` 110 | OpenIssues int `json:"open_issues"` 111 | Watchers int `json:"watchers"` 112 | DefaultBranch string `json:"default_branch"` 113 | } `json:"repository"` 114 | Sender struct { 115 | Login string `json:"login"` 116 | ID int `json:"id"` 117 | NodeID string `json:"node_id"` 118 | AvatarURL string `json:"avatar_url"` 119 | GravatarID string `json:"gravatar_id"` 120 | URL string `json:"url"` 121 | HTMLURL string `json:"html_url"` 122 | FollowersURL string `json:"followers_url"` 123 | FollowingURL string `json:"following_url"` 124 | GistsURL string `json:"gists_url"` 125 | StarredURL string `json:"starred_url"` 126 | SubscriptionsURL string `json:"subscriptions_url"` 127 | OrganizationsURL string `json:"organizations_url"` 128 | ReposURL string `json:"repos_url"` 129 | EventsURL string `json:"events_url"` 130 | ReceivedEventsURL string `json:"received_events_url"` 131 | Type string `json:"type"` 132 | SiteAdmin bool `json:"site_admin"` 133 | } `json:"sender"` 134 | } 135 | 136 | // LoadFromJSON update object from json 137 | func (e *Watch) LoadFromJSON(data []byte) (bool, error) { 138 | err := json.Unmarshal(data, &e) 139 | if err != nil { 140 | return false, err 141 | } 142 | return true, nil 143 | } 144 | 145 | // ConvertToJSON convert object to json 146 | func (e *Watch) ConvertToJSON() (string, error) { 147 | data, err := json.Marshal(&e) 148 | if err != nil { 149 | return "", err 150 | } 151 | return string(data), nil 152 | } 153 | -------------------------------------------------------------------------------- /internal/app/event/watch_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package event 6 | 7 | import ( 8 | "github.com/nbio/st" 9 | "io/ioutil" 10 | "testing" 11 | ) 12 | 13 | // TestWatch test cases 14 | func TestWatch(t *testing.T) { 15 | 16 | var watch Watch 17 | 18 | dat, err := ioutil.ReadFile("../../../fixtures/watch.json") 19 | 20 | if err != nil { 21 | t.Errorf("File fixtures/watch.json is invalid!") 22 | } 23 | 24 | ok, _ := watch.LoadFromJSON(dat) 25 | 26 | if !ok { 27 | t.Errorf("Testing with file fixtures/watch.json is invalid") 28 | } 29 | 30 | st.Expect(t, watch.Repository.Owner.Login, "Clivern") 31 | } 32 | -------------------------------------------------------------------------------- /internal/app/listener/action.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package listener 6 | 7 | import ( 8 | "encoding/json" 9 | "github.com/clivern/hamster/internal/app/event" 10 | ) 11 | 12 | // Action struct 13 | type Action struct { 14 | Status []func(status event.Status) (bool, error) 15 | Issues []func(issue event.Issues) (bool, error) 16 | IssueComment []func(issueComment event.IssueComment) (bool, error) 17 | Watch []func(watch event.Watch) (bool, error) 18 | Push []func(watch event.Push) (bool, error) 19 | Create []func(watch event.Create) (bool, error) 20 | Label []func(label event.Label) (bool, error) 21 | Delete []func(delete event.Delete) (bool, error) 22 | Milestone []func(milestone event.Milestone) (bool, error) 23 | PullRequest []func(pullRequest event.PullRequest) (bool, error) 24 | PullRequestReview []func(pullRequestReview event.PullRequestReview) (bool, error) 25 | PullRequestReviewComment []func(pullRequestReviewComment event.PullRequestReviewComment) (bool, error) 26 | Raw []func(raw event.Raw) (bool, error) 27 | } 28 | 29 | // LoadFromJSON update object from json 30 | func (e *Action) LoadFromJSON(data []byte) (bool, error) { 31 | err := json.Unmarshal(data, &e) 32 | if err != nil { 33 | return false, err 34 | } 35 | return true, nil 36 | } 37 | 38 | // ConvertToJSON convert object to json 39 | func (e *Action) ConvertToJSON() (string, error) { 40 | data, err := json.Marshal(&e) 41 | if err != nil { 42 | return "", err 43 | } 44 | return string(data), nil 45 | } 46 | 47 | // RegisterRawAction adds action for all events 48 | func (e *Action) RegisterRawAction(f func(raw event.Raw) (bool, error)) { 49 | e.Raw = append(e.Raw, f) 50 | } 51 | 52 | // RegisterStatusAction adds action for status event 53 | func (e *Action) RegisterStatusAction(f func(status event.Status) (bool, error)) { 54 | e.Status = append(e.Status, f) 55 | } 56 | 57 | // RegisterIssuesAction adds action for issues event 58 | func (e *Action) RegisterIssuesAction(f func(issue event.Issues) (bool, error)) { 59 | e.Issues = append(e.Issues, f) 60 | } 61 | 62 | // RegisterIssueCommentAction adds action for issue comment event 63 | func (e *Action) RegisterIssueCommentAction(f func(issueComment event.IssueComment) (bool, error)) { 64 | e.IssueComment = append(e.IssueComment, f) 65 | } 66 | 67 | // RegisterWatchAction adds action for watch event 68 | func (e *Action) RegisterWatchAction(f func(watch event.Watch) (bool, error)) { 69 | e.Watch = append(e.Watch, f) 70 | } 71 | 72 | // RegisterPushAction adds action for push event 73 | func (e *Action) RegisterPushAction(f func(watch event.Push) (bool, error)) { 74 | e.Push = append(e.Push, f) 75 | } 76 | 77 | // RegisterCreateAction adds action for create event 78 | func (e *Action) RegisterCreateAction(f func(create event.Create) (bool, error)) { 79 | e.Create = append(e.Create, f) 80 | } 81 | 82 | // RegisterLabelAction adds action for label event 83 | func (e *Action) RegisterLabelAction(f func(label event.Label) (bool, error)) { 84 | e.Label = append(e.Label, f) 85 | } 86 | 87 | // RegisterDeleteAction adds action for delete event 88 | func (e *Action) RegisterDeleteAction(f func(delete event.Delete) (bool, error)) { 89 | e.Delete = append(e.Delete, f) 90 | } 91 | 92 | // RegisterMilestoneAction adds action for milestone event 93 | func (e *Action) RegisterMilestoneAction(f func(milestone event.Milestone) (bool, error)) { 94 | e.Milestone = append(e.Milestone, f) 95 | } 96 | 97 | // RegisterPullRequestAction adds action for pull request event 98 | func (e *Action) RegisterPullRequestAction(f func(pullRequest event.PullRequest) (bool, error)) { 99 | e.PullRequest = append(e.PullRequest, f) 100 | } 101 | 102 | // RegisterPullRequestReviewAction adds action for pull request review event 103 | func (e *Action) RegisterPullRequestReviewAction(f func(pullRequestReview event.PullRequestReview) (bool, error)) { 104 | e.PullRequestReview = append(e.PullRequestReview, f) 105 | } 106 | 107 | // RegisterPullRequestReviewCommentAction adds action for pull request review comment event 108 | func (e *Action) RegisterPullRequestReviewCommentAction(f func(pullRequestReviewComment event.PullRequestReviewComment) (bool, error)) { 109 | e.PullRequestReviewComment = append(e.PullRequestReviewComment, f) 110 | } 111 | 112 | // ExecuteRawActions executes actions for all events 113 | func (e *Action) ExecuteRawActions(raw event.Raw) (bool, error) { 114 | for _, fun := range e.Raw { 115 | ok, err := fun(raw) 116 | if !ok { 117 | return false, err 118 | } 119 | } 120 | return true, nil 121 | } 122 | 123 | // ExecuteStatusActions executes actions for status events 124 | func (e *Action) ExecuteStatusActions(status event.Status) (bool, error) { 125 | for _, fun := range e.Status { 126 | ok, err := fun(status) 127 | if !ok { 128 | return false, err 129 | } 130 | } 131 | return true, nil 132 | } 133 | 134 | // ExecuteIssuesActions executes actions for issues events 135 | func (e *Action) ExecuteIssuesActions(issue event.Issues) (bool, error) { 136 | for _, fun := range e.Issues { 137 | ok, err := fun(issue) 138 | if !ok { 139 | return false, err 140 | } 141 | } 142 | return true, nil 143 | } 144 | 145 | // ExecuteIssueCommentActions executes actions for issue comment events 146 | func (e *Action) ExecuteIssueCommentActions(issueComment event.IssueComment) (bool, error) { 147 | for _, fun := range e.IssueComment { 148 | ok, err := fun(issueComment) 149 | if !ok { 150 | return false, err 151 | } 152 | } 153 | return true, nil 154 | } 155 | 156 | // ExecuteWatchActions executes actions for watch events 157 | func (e *Action) ExecuteWatchActions(watch event.Watch) (bool, error) { 158 | for _, fun := range e.Watch { 159 | ok, err := fun(watch) 160 | if !ok { 161 | return false, err 162 | } 163 | } 164 | return true, nil 165 | } 166 | 167 | // ExecutePushActions executes actions for push events 168 | func (e *Action) ExecutePushActions(push event.Push) (bool, error) { 169 | for _, fun := range e.Push { 170 | ok, err := fun(push) 171 | if !ok { 172 | return false, err 173 | } 174 | } 175 | return true, nil 176 | } 177 | 178 | // ExecuteCreateActions executes actions for create events 179 | func (e *Action) ExecuteCreateActions(create event.Create) (bool, error) { 180 | for _, fun := range e.Create { 181 | ok, err := fun(create) 182 | if !ok { 183 | return false, err 184 | } 185 | } 186 | return true, nil 187 | } 188 | 189 | // ExecuteLabelActions executes actions for label events 190 | func (e *Action) ExecuteLabelActions(label event.Label) (bool, error) { 191 | for _, fun := range e.Label { 192 | ok, err := fun(label) 193 | if !ok { 194 | return false, err 195 | } 196 | } 197 | return true, nil 198 | } 199 | 200 | // ExecuteDeleteActions executes actions for delete events 201 | func (e *Action) ExecuteDeleteActions(delete event.Delete) (bool, error) { 202 | for _, fun := range e.Delete { 203 | ok, err := fun(delete) 204 | if !ok { 205 | return false, err 206 | } 207 | } 208 | return true, nil 209 | } 210 | 211 | // ExecuteMilestoneActions executes actions for milestone events 212 | func (e *Action) ExecuteMilestoneActions(milestone event.Milestone) (bool, error) { 213 | for _, fun := range e.Milestone { 214 | ok, err := fun(milestone) 215 | if !ok { 216 | return false, err 217 | } 218 | } 219 | return true, nil 220 | } 221 | 222 | // ExecutePullRequestActions executes actions for pull request events 223 | func (e *Action) ExecutePullRequestActions(pullRequest event.PullRequest) (bool, error) { 224 | for _, fun := range e.PullRequest { 225 | ok, err := fun(pullRequest) 226 | if !ok { 227 | return false, err 228 | } 229 | } 230 | return true, nil 231 | } 232 | 233 | // ExecutePullRequestReviewActions executes actions for pull requests review events 234 | func (e *Action) ExecutePullRequestReviewActions(pullRequestReview event.PullRequestReview) (bool, error) { 235 | for _, fun := range e.PullRequestReview { 236 | ok, err := fun(pullRequestReview) 237 | if !ok { 238 | return false, err 239 | } 240 | } 241 | return true, nil 242 | } 243 | 244 | // ExecutePullRequestReviewCommentActions executes actions for pull requests review comment events 245 | func (e *Action) ExecutePullRequestReviewCommentActions(pullRequestReviewComment event.PullRequestReviewComment) (bool, error) { 246 | for _, fun := range e.PullRequestReviewComment { 247 | ok, err := fun(pullRequestReviewComment) 248 | if !ok { 249 | return false, err 250 | } 251 | } 252 | return true, nil 253 | } 254 | -------------------------------------------------------------------------------- /internal/app/listener/command.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package listener 6 | 7 | import ( 8 | "github.com/clivern/hamster/internal/app/event" 9 | "regexp" 10 | ) 11 | 12 | // Commands struct 13 | type Commands struct { 14 | Incoming []event.Command 15 | Issues map[string]func(command event.Command, issues event.Issues) (bool, error) 16 | IssueComment map[string]func(command event.Command, issueComment event.IssueComment) (bool, error) 17 | } 18 | 19 | // Fetch will fetch all commands and parameters within the issue or issue comment 20 | func (e *Commands) Fetch(body string) { 21 | re := regexp.MustCompile(`\S*(/[a-zA-Z0-9])\S*`) 22 | re.MatchString(body) 23 | 24 | submatchall := re.FindAllString(body, -1) 25 | for _, element := range submatchall { 26 | command := event.Command{Data: element} 27 | command.Parse() 28 | e.Incoming = append(e.Incoming, command) 29 | } 30 | } 31 | 32 | // RegisterIssuesAction registers issue action for a specific command 33 | func (e *Commands) RegisterIssuesAction(command string, callback func(command event.Command, issues event.Issues) (bool, error)) { 34 | if e.Issues == nil { 35 | e.Issues = make(map[string]func(command event.Command, issues event.Issues) (bool, error)) 36 | } 37 | e.Issues[command] = callback 38 | } 39 | 40 | // RegisterIssueCommentAction registers issue comment action for a specific command 41 | func (e *Commands) RegisterIssueCommentAction(command string, callback func(command event.Command, issueComment event.IssueComment) (bool, error)) { 42 | if e.IssueComment == nil { 43 | e.IssueComment = make(map[string]func(command event.Command, issueComment event.IssueComment) (bool, error)) 44 | } 45 | e.IssueComment[command] = callback 46 | } 47 | 48 | // ExecuteIssuesActions runs issues actions 49 | func (e *Commands) ExecuteIssuesActions(issues event.Issues) (bool, error) { 50 | e.Fetch(issues.Issue.Body) 51 | for _, command := range e.Incoming { 52 | if fun, ok := e.Issues[command.Name]; ok { 53 | ok, err := fun(command, issues) 54 | if !ok { 55 | return false, err 56 | } 57 | } 58 | 59 | } 60 | return true, nil 61 | } 62 | 63 | // ExecuteIssueCommentActions runs issue comment actions 64 | func (e *Commands) ExecuteIssueCommentActions(issueComment event.IssueComment) (bool, error) { 65 | e.Fetch(issueComment.Comment.Body) 66 | for _, command := range e.Incoming { 67 | if fun, ok := e.IssueComment[command.Name]; ok { 68 | ok, err := fun(command, issueComment) 69 | if !ok { 70 | return false, err 71 | } 72 | } 73 | 74 | } 75 | return true, nil 76 | } 77 | -------------------------------------------------------------------------------- /internal/app/listener/parser.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package listener 6 | 7 | import ( 8 | "crypto/hmac" 9 | "crypto/sha1" 10 | "encoding/hex" 11 | "encoding/json" 12 | "strings" 13 | ) 14 | 15 | // Parser struct 16 | type Parser struct { 17 | UserAgent string 18 | GithubDelivery string 19 | GitHubEvent string 20 | HubSignature string 21 | Headers map[string]string 22 | Body string 23 | } 24 | 25 | // LoadFromJSON update object from json 26 | func (e *Parser) LoadFromJSON(data []byte) (bool, error) { 27 | err := json.Unmarshal(data, &e) 28 | if err != nil { 29 | return false, err 30 | } 31 | return true, nil 32 | } 33 | 34 | // ConvertToJSON convert object to json 35 | func (e *Parser) ConvertToJSON() (string, error) { 36 | data, err := json.Marshal(&e) 37 | if err != nil { 38 | return "", err 39 | } 40 | return string(data), nil 41 | } 42 | 43 | // SetUserAgent sets user agent 44 | func (e *Parser) SetUserAgent(userAgent string) { 45 | e.UserAgent = userAgent 46 | } 47 | 48 | // GetUserAgent gets user agent 49 | func (e *Parser) GetUserAgent() string { 50 | return e.UserAgent 51 | } 52 | 53 | // SetGithubDelivery sets github delivery 54 | func (e *Parser) SetGithubDelivery(githubDelivery string) { 55 | e.GithubDelivery = githubDelivery 56 | } 57 | 58 | // GetGithubDelivery gets github delivery 59 | func (e *Parser) GetGithubDelivery() string { 60 | return e.GithubDelivery 61 | } 62 | 63 | // SetGitHubEvent sets github event 64 | func (e *Parser) SetGitHubEvent(githubEvent string) { 65 | e.GitHubEvent = githubEvent 66 | } 67 | 68 | // GetGitHubEvent gets github event 69 | func (e *Parser) GetGitHubEvent() string { 70 | return e.GitHubEvent 71 | } 72 | 73 | // SetHubSignature sets hub signature 74 | func (e *Parser) SetHubSignature(hubSignature string) { 75 | e.HubSignature = hubSignature 76 | } 77 | 78 | // GetHubSignature gets hub signature 79 | func (e *Parser) GetHubSignature() string { 80 | return e.HubSignature 81 | } 82 | 83 | // SetBody sets body 84 | func (e *Parser) SetBody(body string) { 85 | e.Body = body 86 | } 87 | 88 | // GetBody gets body 89 | func (e *Parser) GetBody() string { 90 | return e.Body 91 | } 92 | 93 | // SetHeader sets header 94 | func (e *Parser) SetHeader(key string, value string) { 95 | e.Headers[key] = value 96 | } 97 | 98 | // GetHeader gets header 99 | func (e *Parser) GetHeader(key string) string { 100 | return e.Headers[key] 101 | } 102 | 103 | // VerifySignature verify signature 104 | func (e *Parser) VerifySignature(secret string) bool { 105 | 106 | signature := e.GetHubSignature() 107 | body := e.GetBody() 108 | 109 | if len(signature) != 45 || !strings.HasPrefix(signature, "sha1=") { 110 | return false 111 | } 112 | 113 | actual := make([]byte, 20) 114 | hex.Decode(actual, []byte(signature[5:])) 115 | 116 | return hmac.Equal(e.SignBody([]byte(secret), []byte(body)), actual) 117 | } 118 | 119 | // SignBody signs body 120 | func (e *Parser) SignBody(secret, body []byte) []byte { 121 | computed := hmac.New(sha1.New, secret) 122 | computed.Write(body) 123 | return []byte(computed.Sum(nil)) 124 | } 125 | -------------------------------------------------------------------------------- /internal/app/pkg/github/oauth.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package github 6 | 7 | import ( 8 | "bytes" 9 | "crypto/rand" 10 | "encoding/hex" 11 | "encoding/json" 12 | "fmt" 13 | "io/ioutil" 14 | "net/http" 15 | "net/url" 16 | "strings" 17 | ) 18 | 19 | const ( 20 | // GithubOAuthURL url 21 | GithubOAuthURL = "https://github.com/login/oauth/authorize" 22 | // OAuthAccessToken url 23 | OAuthAccessToken = "https://github.com/login/oauth/access_token" 24 | ) 25 | 26 | // OAuthApp struct 27 | type OAuthApp struct { 28 | ClientID string `json:"client_id"` 29 | RedirectURI string `json:"redirect_uri"` 30 | Scope string `json:"scope"` 31 | Scopes []string `json:"scopes"` 32 | State string `json:"state"` 33 | AllowSignup string `json:"allow_signup"` 34 | ClientSecret string `json:"client_secret"` 35 | AccessToken string `json:"access_token"` 36 | TokenType string `json:"token_type"` 37 | } 38 | 39 | // OAuthClient struct 40 | type OAuthClient struct { 41 | AccessToken string `json:"access_token"` 42 | TokenType string `json:"token_type"` 43 | } 44 | 45 | // AccessToken struct 46 | type AccessToken struct { 47 | ClientID string `json:"client_id"` 48 | ClientSecret string `json:"client_secret"` 49 | Code string `json:"code"` 50 | State string `json:"state"` 51 | } 52 | 53 | // GenerateState creates a random string 54 | func (e *OAuthApp) GenerateState() { 55 | val, err := e.RandomString(20) 56 | if err == nil { 57 | e.State = val 58 | } 59 | } 60 | 61 | // GetState returns the state 62 | func (e *OAuthApp) GetState() string { 63 | return e.State 64 | } 65 | 66 | // SetState sets the state 67 | func (e *OAuthApp) SetState(state string) { 68 | e.State = state 69 | } 70 | 71 | // AddScope adds a scope 72 | func (e *OAuthApp) AddScope(scope string) { 73 | e.Scopes = append(e.Scopes, scope) 74 | e.Scope = strings.Join(e.Scopes, ",") 75 | } 76 | 77 | // AddScopes adds all scopes 78 | func (e *OAuthApp) AddScopes(scopes []string) { 79 | e.Scopes = scopes 80 | e.Scope = strings.Join(e.Scopes, ",") 81 | } 82 | 83 | // BuildAuthorizeURL get the authorize url 84 | func (e *OAuthApp) BuildAuthorizeURL() string { 85 | e.Scope = strings.Join(e.Scopes, ",") 86 | 87 | u, err := url.Parse(GithubOAuthURL) 88 | 89 | if err != nil { 90 | return "" 91 | } 92 | 93 | q := u.Query() 94 | q.Set("client_id", e.ClientID) 95 | q.Set("redirect_uri", e.RedirectURI) 96 | q.Set("scope", e.Scope) 97 | q.Set("state", e.State) 98 | q.Set("allow_signup", e.AllowSignup) 99 | u.RawQuery = q.Encode() 100 | 101 | return u.String() 102 | } 103 | 104 | // RandomString creates a random string 105 | func (e *OAuthApp) RandomString(len int) (string, error) { 106 | bytes := make([]byte, len) 107 | if _, err := rand.Read(bytes); err != nil { 108 | return "", err 109 | } 110 | return hex.EncodeToString(bytes), nil 111 | } 112 | 113 | // FetchAccessToken fetches github access token 114 | func (e *OAuthApp) FetchAccessToken(code string, state string) (bool, error) { 115 | 116 | accessTokenRequest := &AccessToken{ 117 | ClientID: e.ClientID, 118 | ClientSecret: e.ClientSecret, 119 | Code: code, 120 | State: e.State, 121 | } 122 | 123 | jsonBody, err := accessTokenRequest.ConvertToJSON() 124 | 125 | if err != nil { 126 | return false, err 127 | } 128 | 129 | githubOAuthClient := &OAuthClient{} 130 | 131 | if state != e.State { 132 | return false, fmt.Errorf( 133 | "Invalid state provided %s, original one is %s", 134 | state, 135 | e.State, 136 | ) 137 | } 138 | 139 | client := &http.Client{} 140 | req, err := http.NewRequest( 141 | "POST", 142 | OAuthAccessToken, 143 | bytes.NewBufferString(jsonBody), 144 | ) 145 | 146 | if err != nil { 147 | return false, err 148 | } 149 | 150 | req.Header.Add("Accept", "application/json") 151 | req.Header.Add("Content-type", "application/json") 152 | 153 | resp, err := client.Do(req) 154 | 155 | if err != nil { 156 | return false, err 157 | } 158 | 159 | defer resp.Body.Close() 160 | 161 | bodyByte, err := ioutil.ReadAll(resp.Body) 162 | 163 | if err != nil { 164 | return false, err 165 | } 166 | 167 | err = json.Unmarshal(bodyByte, &githubOAuthClient) 168 | 169 | if err != nil { 170 | return false, err 171 | } 172 | 173 | e.AccessToken = githubOAuthClient.AccessToken 174 | e.TokenType = githubOAuthClient.TokenType 175 | 176 | return true, nil 177 | } 178 | 179 | // GetAccessToken gets access token 180 | func (e *OAuthApp) GetAccessToken() string { 181 | return e.AccessToken 182 | } 183 | 184 | // GetTokenType gets token type 185 | func (e *OAuthApp) GetTokenType() string { 186 | return e.TokenType 187 | } 188 | 189 | // ConvertToJSON convert object to json 190 | func (e *AccessToken) ConvertToJSON() (string, error) { 191 | data, err := json.Marshal(&e) 192 | if err != nil { 193 | return "", err 194 | } 195 | return string(data), nil 196 | } 197 | -------------------------------------------------------------------------------- /internal/app/pkg/logger/logger.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package logger 6 | 7 | import ( 8 | "fmt" 9 | "github.com/google/logger" 10 | "os" 11 | "time" 12 | ) 13 | 14 | // LogsPath is the logs path 15 | const LogsPath = "var/logs" 16 | 17 | // Info log function 18 | func Info(v ...interface{}) { 19 | 20 | logLevel := os.Getenv("AppLogLevel") 21 | ok := logLevel == "info" 22 | 23 | if ok { 24 | currentTime := time.Now().Local() 25 | file := fmt.Sprintf("%s/%s.log", LogsPath, currentTime.Format("2006-01-02")) 26 | lf, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660) 27 | 28 | if err != nil { 29 | logger.Fatalf("Failed to open log file: %v", err) 30 | } 31 | 32 | defer lf.Close() 33 | 34 | out := logger.Init("Hamster", false, false, lf) 35 | defer out.Close() 36 | 37 | out.Info(v...) 38 | } 39 | } 40 | 41 | // Infoln log function 42 | func Infoln(v ...interface{}) { 43 | 44 | logLevel := os.Getenv("AppLogLevel") 45 | ok := logLevel == "info" 46 | 47 | if ok { 48 | currentTime := time.Now().Local() 49 | file := fmt.Sprintf("%s/%s.log", LogsPath, currentTime.Format("2006-01-02")) 50 | lf, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660) 51 | 52 | if err != nil { 53 | logger.Fatalf("Failed to open log file: %v", err) 54 | } 55 | 56 | defer lf.Close() 57 | 58 | out := logger.Init("Hamster", false, false, lf) 59 | defer out.Close() 60 | 61 | out.Infoln(v...) 62 | } 63 | } 64 | 65 | // Infof log function 66 | func Infof(format string, v ...interface{}) { 67 | 68 | logLevel := os.Getenv("AppLogLevel") 69 | ok := logLevel == "info" 70 | 71 | if ok { 72 | currentTime := time.Now().Local() 73 | file := fmt.Sprintf("%s/%s.log", LogsPath, currentTime.Format("2006-01-02")) 74 | lf, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660) 75 | 76 | if err != nil { 77 | logger.Fatalf("Failed to open log file: %v", err) 78 | } 79 | 80 | defer lf.Close() 81 | 82 | out := logger.Init("Hamster", false, false, lf) 83 | defer out.Close() 84 | 85 | out.Infof(format, v...) 86 | } 87 | } 88 | 89 | // Warning log function 90 | func Warning(v ...interface{}) { 91 | 92 | logLevel := os.Getenv("AppLogLevel") 93 | ok := logLevel == "info" || logLevel == "warning" 94 | 95 | if ok { 96 | currentTime := time.Now().Local() 97 | file := fmt.Sprintf("%s/%s.log", LogsPath, currentTime.Format("2006-01-02")) 98 | lf, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660) 99 | 100 | if err != nil { 101 | logger.Fatalf("Failed to open log file: %v", err) 102 | } 103 | 104 | defer lf.Close() 105 | 106 | out := logger.Init("Hamster", false, false, lf) 107 | defer out.Close() 108 | 109 | out.Warning(v...) 110 | } 111 | } 112 | 113 | // Warningln log function 114 | func Warningln(v ...interface{}) { 115 | 116 | logLevel := os.Getenv("AppLogLevel") 117 | ok := logLevel == "info" || logLevel == "warning" 118 | 119 | if ok { 120 | currentTime := time.Now().Local() 121 | file := fmt.Sprintf("%s/%s.log", LogsPath, currentTime.Format("2006-01-02")) 122 | lf, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660) 123 | 124 | if err != nil { 125 | logger.Fatalf("Failed to open log file: %v", err) 126 | } 127 | 128 | defer lf.Close() 129 | 130 | out := logger.Init("Hamster", false, false, lf) 131 | defer out.Close() 132 | 133 | out.Warningln(v...) 134 | } 135 | } 136 | 137 | // Warningf log function 138 | func Warningf(format string, v ...interface{}) { 139 | 140 | logLevel := os.Getenv("AppLogLevel") 141 | ok := logLevel == "info" || logLevel == "warning" 142 | 143 | if ok { 144 | currentTime := time.Now().Local() 145 | file := fmt.Sprintf("%s/%s.log", LogsPath, currentTime.Format("2006-01-02")) 146 | lf, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660) 147 | 148 | if err != nil { 149 | logger.Fatalf("Failed to open log file: %v", err) 150 | } 151 | 152 | defer lf.Close() 153 | 154 | out := logger.Init("Hamster", false, false, lf) 155 | defer out.Close() 156 | 157 | out.Warningf(format, v...) 158 | } 159 | } 160 | 161 | // Error log function 162 | func Error(v ...interface{}) { 163 | 164 | logLevel := os.Getenv("AppLogLevel") 165 | ok := logLevel == "info" || logLevel == "warning" || logLevel == "error" 166 | 167 | if ok { 168 | currentTime := time.Now().Local() 169 | file := fmt.Sprintf("%s/%s.log", LogsPath, currentTime.Format("2006-01-02")) 170 | lf, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660) 171 | 172 | if err != nil { 173 | logger.Fatalf("Failed to open log file: %v", err) 174 | } 175 | 176 | defer lf.Close() 177 | 178 | out := logger.Init("Hamster", false, false, lf) 179 | defer out.Close() 180 | 181 | out.Error(v...) 182 | } 183 | } 184 | 185 | // Errorln log function 186 | func Errorln(v ...interface{}) { 187 | 188 | logLevel := os.Getenv("AppLogLevel") 189 | ok := logLevel == "info" || logLevel == "warning" || logLevel == "error" 190 | 191 | if ok { 192 | currentTime := time.Now().Local() 193 | file := fmt.Sprintf("%s/%s.log", LogsPath, currentTime.Format("2006-01-02")) 194 | lf, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660) 195 | 196 | if err != nil { 197 | logger.Fatalf("Failed to open log file: %v", err) 198 | } 199 | 200 | defer lf.Close() 201 | 202 | out := logger.Init("Hamster", false, false, lf) 203 | defer out.Close() 204 | 205 | out.Errorln(v...) 206 | } 207 | } 208 | 209 | // Errorf log function 210 | func Errorf(format string, v ...interface{}) { 211 | 212 | logLevel := os.Getenv("AppLogLevel") 213 | ok := logLevel == "info" || logLevel == "warning" || logLevel == "error" 214 | 215 | if ok { 216 | currentTime := time.Now().Local() 217 | file := fmt.Sprintf("%s/%s.log", LogsPath, currentTime.Format("2006-01-02")) 218 | lf, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660) 219 | 220 | if err != nil { 221 | logger.Fatalf("Failed to open log file: %v", err) 222 | } 223 | 224 | defer lf.Close() 225 | 226 | out := logger.Init("Hamster", false, false, lf) 227 | defer out.Close() 228 | 229 | out.Errorf(format, v...) 230 | } 231 | } 232 | 233 | // Fatal log function 234 | func Fatal(v ...interface{}) { 235 | 236 | logLevel := os.Getenv("AppLogLevel") 237 | ok := logLevel == "info" || logLevel == "warning" || logLevel == "error" || logLevel == "fatal" 238 | 239 | if ok { 240 | currentTime := time.Now().Local() 241 | file := fmt.Sprintf("%s/%s.log", LogsPath, currentTime.Format("2006-01-02")) 242 | lf, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660) 243 | 244 | if err != nil { 245 | logger.Fatalf("Failed to open log file: %v", err) 246 | } 247 | 248 | defer lf.Close() 249 | 250 | out := logger.Init("Hamster", false, false, lf) 251 | defer out.Close() 252 | 253 | out.Fatal(v...) 254 | } 255 | } 256 | 257 | // Fatalln log function 258 | func Fatalln(v ...interface{}) { 259 | 260 | logLevel := os.Getenv("AppLogLevel") 261 | ok := logLevel == "info" || logLevel == "warning" || logLevel == "error" || logLevel == "fatal" 262 | 263 | if ok { 264 | currentTime := time.Now().Local() 265 | file := fmt.Sprintf("%s/%s.log", LogsPath, currentTime.Format("2006-01-02")) 266 | lf, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660) 267 | 268 | if err != nil { 269 | logger.Fatalf("Failed to open log file: %v", err) 270 | } 271 | 272 | defer lf.Close() 273 | 274 | out := logger.Init("Hamster", false, false, lf) 275 | defer out.Close() 276 | 277 | out.Fatalln(v...) 278 | } 279 | } 280 | 281 | // Fatalf log function 282 | func Fatalf(format string, v ...interface{}) { 283 | 284 | logLevel := os.Getenv("AppLogLevel") 285 | ok := logLevel == "info" || logLevel == "warning" || logLevel == "error" || logLevel == "fatal" 286 | 287 | if ok { 288 | currentTime := time.Now().Local() 289 | file := fmt.Sprintf("%s/%s.log", LogsPath, currentTime.Format("2006-01-02")) 290 | lf, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0660) 291 | 292 | if err != nil { 293 | logger.Fatalf("Failed to open log file: %v", err) 294 | } 295 | 296 | defer lf.Close() 297 | 298 | out := logger.Init("Hamster", false, false, lf) 299 | defer out.Close() 300 | 301 | out.Fatalf(format, v...) 302 | } 303 | } 304 | -------------------------------------------------------------------------------- /internal/app/pkg/utils/configs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package utils 6 | 7 | import ( 8 | "encoding/json" 9 | "fmt" 10 | "io/ioutil" 11 | "os" 12 | ) 13 | 14 | // Config struct 15 | type Config struct { 16 | GithubToken string `json:"github_token"` 17 | GithubWebhookSecret string `json:"github_webhook_secret"` 18 | RepositoryAuthor string `json:"repository_author"` 19 | RepositoryName string `json:"repository_name"` 20 | AppMode string `json:"app_mode"` 21 | AppPort string `json:"app_port"` 22 | AppLogLevel string `json:"app_log_level"` 23 | AppDomain string `json:"app_domain"` 24 | GithubAppClientID string `json:"github_app_client_id"` 25 | GithubAppRedirectURI string `json:"github_app_redirect_uri"` 26 | GithubAppAllowSignup string `json:"github_app_allow_signup"` 27 | GithubAppScope string `json:"github_app_scope"` 28 | GithubAppClientSecret string `json:"github_app_client_secret"` 29 | } 30 | 31 | // Load method loads configs from json file 32 | func (e *Config) Load(file string) (bool, error) { 33 | 34 | _, err := os.Stat(file) 35 | 36 | if err != nil { 37 | return false, fmt.Errorf("config file %s not found", file) 38 | } 39 | 40 | data, err := ioutil.ReadFile(file) 41 | 42 | if err != nil { 43 | return false, err 44 | } 45 | 46 | err = json.Unmarshal(data, &e) 47 | 48 | if err != nil { 49 | return false, err 50 | } 51 | 52 | return true, nil 53 | } 54 | 55 | // Cache store the configs as env vars 56 | func (e *Config) Cache() { 57 | if os.Getenv("AppMode") == "" { 58 | os.Setenv("GithubToken", e.GithubToken) 59 | os.Setenv("GithubWebhookSecret", e.GithubWebhookSecret) 60 | os.Setenv("RepositoryAuthor", e.RepositoryAuthor) 61 | os.Setenv("RepositoryName", e.RepositoryName) 62 | os.Setenv("AppMode", e.AppMode) 63 | os.Setenv("AppLogLevel", e.AppLogLevel) 64 | os.Setenv("AppPort", e.AppPort) 65 | os.Setenv("GithubAppClientID", e.GithubAppClientID) 66 | os.Setenv("GithubAppRedirectURI", e.GithubAppRedirectURI) 67 | os.Setenv("GithubAppAllowSignup", e.GithubAppAllowSignup) 68 | os.Setenv("GithubAppScope", e.GithubAppScope) 69 | os.Setenv("GithubAppClientSecret", e.GithubAppClientSecret) 70 | os.Setenv("AppDomain", e.AppDomain) 71 | } 72 | } 73 | 74 | // GinEnv set gin env vars 75 | func (e *Config) GinEnv() { 76 | // Used by gin framework 77 | // https://github.com/gin-gonic/gin/blob/d510595aa58c2417373d89a8d8ffa21cf58673cb/utils.go#L140 78 | os.Setenv("PORT", os.Getenv("AppPort")) 79 | } 80 | -------------------------------------------------------------------------------- /internal/app/pkg/utils/http.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package utils 6 | 7 | import ( 8 | "bytes" 9 | "fmt" 10 | "io/ioutil" 11 | "net/http" 12 | ) 13 | 14 | // Request do a generic http requests 15 | func Request(method string, url string, body string, token string) (string, error) { 16 | 17 | client := &http.Client{} 18 | req, err := http.NewRequest(method, url, bytes.NewBufferString(body)) 19 | 20 | if err != nil { 21 | return "", err 22 | } 23 | 24 | req.Header.Add("Authorization", fmt.Sprintf("token %s", token)) 25 | 26 | resp, err := client.Do(req) 27 | 28 | if err != nil { 29 | return "", err 30 | } 31 | 32 | defer resp.Body.Close() 33 | 34 | bodyByte, err := ioutil.ReadAll(resp.Body) 35 | 36 | if err != nil { 37 | return "", err 38 | } 39 | 40 | return string(bodyByte), nil 41 | } 42 | -------------------------------------------------------------------------------- /internal/app/response/annotation.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package response 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Annotation struct 12 | type Annotation struct { 13 | Path string `json:"path"` 14 | StartLine int `json:"start_line"` 15 | EndLine int `json:"end_line"` 16 | StartColumn int `json:"start_column"` 17 | EndColumn int `json:"end_column"` 18 | AnnotationLevel string `json:"annotation_level"` 19 | Message string `json:"message"` 20 | Title string `json:"title"` 21 | RawDetails string `json:"raw_details"` 22 | } 23 | 24 | // Annotations struct 25 | type Annotations []Annotation 26 | 27 | // LoadFromJSON update object from json 28 | func (e *Annotation) LoadFromJSON(data []byte) (bool, error) { 29 | err := json.Unmarshal(data, &e) 30 | if err != nil { 31 | return false, err 32 | } 33 | return true, nil 34 | } 35 | 36 | // ConvertToJSON convert object to json 37 | func (e *Annotation) ConvertToJSON() (string, error) { 38 | data, err := json.Marshal(&e) 39 | if err != nil { 40 | return "", err 41 | } 42 | return string(data), nil 43 | } 44 | 45 | // LoadFromJSON update object from json 46 | func (e *Annotations) LoadFromJSON(data []byte) (bool, error) { 47 | err := json.Unmarshal(data, &e) 48 | if err != nil { 49 | return false, err 50 | } 51 | return true, nil 52 | } 53 | 54 | // ConvertToJSON convert object to json 55 | func (e *Annotations) ConvertToJSON() (string, error) { 56 | data, err := json.Marshal(&e) 57 | if err != nil { 58 | return "", err 59 | } 60 | return string(data), nil 61 | } 62 | -------------------------------------------------------------------------------- /internal/app/response/check_run.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package response 6 | 7 | import ( 8 | "encoding/json" 9 | "time" 10 | ) 11 | 12 | // CheckRun struct 13 | type CheckRun struct { 14 | ID int `json:"id"` 15 | NodeID string `json:"node_id"` 16 | HeadSha string `json:"head_sha"` 17 | ExternalID string `json:"external_id"` 18 | URL string `json:"url"` 19 | HTMLURL string `json:"html_url"` 20 | DetailsURL string `json:"details_url"` 21 | Status string `json:"status"` 22 | Conclusion string `json:"conclusion"` 23 | StartedAt time.Time `json:"started_at"` 24 | CompletedAt time.Time `json:"completed_at"` 25 | Output struct { 26 | Title string `json:"title"` 27 | Summary string `json:"summary"` 28 | Text string `json:"text"` 29 | AnnotationsCount int `json:"annotations_count"` 30 | AnnotationsURL string `json:"annotations_url"` 31 | } `json:"output"` 32 | Name string `json:"name"` 33 | CheckSuite struct { 34 | ID int `json:"id"` 35 | } `json:"check_suite"` 36 | App struct { 37 | ID int `json:"id"` 38 | NodeID string `json:"node_id"` 39 | Owner struct { 40 | Login string `json:"login"` 41 | ID int `json:"id"` 42 | NodeID string `json:"node_id"` 43 | AvatarURL string `json:"avatar_url"` 44 | GravatarID string `json:"gravatar_id"` 45 | URL string `json:"url"` 46 | HTMLURL string `json:"html_url"` 47 | FollowersURL string `json:"followers_url"` 48 | FollowingURL string `json:"following_url"` 49 | GistsURL string `json:"gists_url"` 50 | StarredURL string `json:"starred_url"` 51 | SubscriptionsURL string `json:"subscriptions_url"` 52 | OrganizationsURL string `json:"organizations_url"` 53 | ReposURL string `json:"repos_url"` 54 | EventsURL string `json:"events_url"` 55 | ReceivedEventsURL string `json:"received_events_url"` 56 | Type string `json:"type"` 57 | SiteAdmin bool `json:"site_admin"` 58 | } `json:"owner"` 59 | Name string `json:"name"` 60 | Description string `json:"description"` 61 | ExternalURL string `json:"external_url"` 62 | HTMLURL string `json:"html_url"` 63 | CreatedAt time.Time `json:"created_at"` 64 | UpdatedAt time.Time `json:"updated_at"` 65 | } `json:"app"` 66 | PullRequests []interface{} `json:"pull_requests"` 67 | } 68 | 69 | // CheckRuns struct 70 | type CheckRuns struct { 71 | TotalCount int `json:"total_count"` 72 | CheckRuns []CheckRun `json:"check_runs"` 73 | } 74 | 75 | // LoadFromJSON update object from json 76 | func (e *CheckRun) LoadFromJSON(data []byte) (bool, error) { 77 | err := json.Unmarshal(data, &e) 78 | if err != nil { 79 | return false, err 80 | } 81 | return true, nil 82 | } 83 | 84 | // ConvertToJSON convert object to json 85 | func (e *CheckRun) ConvertToJSON() (string, error) { 86 | data, err := json.Marshal(&e) 87 | if err != nil { 88 | return "", err 89 | } 90 | return string(data), nil 91 | } 92 | 93 | // LoadFromJSON update object from json 94 | func (e *CheckRuns) LoadFromJSON(data []byte) (bool, error) { 95 | err := json.Unmarshal(data, &e) 96 | if err != nil { 97 | return false, err 98 | } 99 | return true, nil 100 | } 101 | 102 | // ConvertToJSON convert object to json 103 | func (e *CheckRuns) ConvertToJSON() (string, error) { 104 | data, err := json.Marshal(&e) 105 | if err != nil { 106 | return "", err 107 | } 108 | return string(data), nil 109 | } 110 | -------------------------------------------------------------------------------- /internal/app/response/created_comment.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package response 6 | 7 | import ( 8 | "encoding/json" 9 | "time" 10 | ) 11 | 12 | // CreatedComment struct 13 | type CreatedComment struct { 14 | URL string `json:"url"` 15 | HTMLURL string `json:"html_url"` 16 | IssueURL string `json:"issue_url"` 17 | ID int `json:"id"` 18 | NodeID string `json:"node_id"` 19 | User struct { 20 | Login string `json:"login"` 21 | ID int `json:"id"` 22 | NodeID string `json:"node_id"` 23 | AvatarURL string `json:"avatar_url"` 24 | GravatarID string `json:"gravatar_id"` 25 | URL string `json:"url"` 26 | HTMLURL string `json:"html_url"` 27 | FollowersURL string `json:"followers_url"` 28 | FollowingURL string `json:"following_url"` 29 | GistsURL string `json:"gists_url"` 30 | StarredURL string `json:"starred_url"` 31 | SubscriptionsURL string `json:"subscriptions_url"` 32 | OrganizationsURL string `json:"organizations_url"` 33 | ReposURL string `json:"repos_url"` 34 | EventsURL string `json:"events_url"` 35 | ReceivedEventsURL string `json:"received_events_url"` 36 | Type string `json:"type"` 37 | SiteAdmin bool `json:"site_admin"` 38 | } `json:"user"` 39 | CreatedAt time.Time `json:"created_at"` 40 | UpdatedAt time.Time `json:"updated_at"` 41 | AuthorAssociation string `json:"author_association"` 42 | Body string `json:"body"` 43 | } 44 | 45 | // LoadFromJSON update object from json 46 | func (e *CreatedComment) LoadFromJSON(data []byte) (bool, error) { 47 | err := json.Unmarshal(data, &e) 48 | if err != nil { 49 | return false, err 50 | } 51 | return true, nil 52 | } 53 | 54 | // ConvertToJSON convert object to json 55 | func (e *CreatedComment) ConvertToJSON() (string, error) { 56 | data, err := json.Marshal(&e) 57 | if err != nil { 58 | return "", err 59 | } 60 | return string(data), nil 61 | } 62 | -------------------------------------------------------------------------------- /internal/app/response/label.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package response 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Label struct 12 | type Label struct { 13 | ID int `json:"id"` 14 | NodeID string `json:"node_id"` 15 | URL string `json:"url"` 16 | Name string `json:"name"` 17 | Description string `json:"description"` 18 | Color string `json:"color"` 19 | Default bool `json:"default"` 20 | } 21 | 22 | // LoadFromJSON update object from json 23 | func (e *Label) LoadFromJSON(data []byte) (bool, error) { 24 | err := json.Unmarshal(data, &e) 25 | if err != nil { 26 | return false, err 27 | } 28 | return true, nil 29 | } 30 | 31 | // ConvertToJSON convert object to json 32 | func (e *Label) ConvertToJSON() (string, error) { 33 | data, err := json.Marshal(&e) 34 | if err != nil { 35 | return "", err 36 | } 37 | return string(data), nil 38 | } 39 | -------------------------------------------------------------------------------- /internal/app/sender/check_run.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package sender 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // CheckRun struct 12 | type CheckRun struct { 13 | Name string `json:"name,omitempty"` 14 | HeadSha string `json:"head_sha,omitempty"` 15 | DetailsURL string `json:"details_url,omitempty"` 16 | Status string `json:"status,omitempty"` 17 | ExternalID string `json:"external_id,omitempty"` 18 | Conclusion string `json:"conclusion,omitempty"` 19 | StartedAt string `json:"started_at,omitempty"` 20 | CompletedAt string `json:"completed_at,omitempty"` 21 | Output Output `json:"output,omitempty"` 22 | Actions []Action `json:"actions,omitempty"` 23 | } 24 | 25 | // Output struct 26 | type Output struct { 27 | Title string `json:"title,omitempty"` 28 | Summary string `json:"summary,omitempty"` 29 | Text string `json:"text,omitempty"` 30 | Annotations []Annotation `json:"annotations,omitempty"` 31 | Images []Image `json:"images,omitempty"` 32 | } 33 | 34 | // Annotation struct 35 | type Annotation struct { 36 | Path string `json:"path,omitempty"` 37 | StartLine int `json:"start_line,omitempty"` 38 | EndLine int `json:"end_line,omitempty"` 39 | StartColumn int `json:"start_column,omitempty"` 40 | EndColumn int `json:"end_column,omitempty"` 41 | AnnotationLevel string `json:"annotation_level,omitempty"` 42 | Message string `json:"message,omitempty"` 43 | Title string `json:"title,omitempty"` 44 | RawDetails string `json:"raw_details,omitempty"` 45 | } 46 | 47 | // Image struct 48 | type Image struct { 49 | Alt string `json:"alt,omitempty"` 50 | ImageURL string `json:"image_url,omitempty"` 51 | Caption string `json:"caption,omitempty"` 52 | } 53 | 54 | // Action struct 55 | type Action struct { 56 | Label string `json:"label,omitempty"` 57 | Description string `json:"description,omitempty"` 58 | Identifier string `json:"identifier,omitempty"` 59 | } 60 | 61 | // LoadFromJSON update object from json 62 | func (e *CheckRun) LoadFromJSON(data []byte) (bool, error) { 63 | err := json.Unmarshal(data, &e) 64 | if err != nil { 65 | return false, err 66 | } 67 | return true, nil 68 | } 69 | 70 | // ConvertToJSON convert object to json 71 | func (e *CheckRun) ConvertToJSON() (string, error) { 72 | data, err := json.Marshal(&e) 73 | if err != nil { 74 | return "", err 75 | } 76 | return string(data), nil 77 | } 78 | -------------------------------------------------------------------------------- /internal/app/sender/comment.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package sender 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Comment struct 12 | type Comment struct { 13 | Body string `json:"body"` 14 | } 15 | 16 | // LoadFromJSON update object from json 17 | func (e *Comment) LoadFromJSON(data []byte) (bool, error) { 18 | err := json.Unmarshal(data, &e) 19 | if err != nil { 20 | return false, err 21 | } 22 | return true, nil 23 | } 24 | 25 | // ConvertToJSON convert object to json 26 | func (e *Comment) ConvertToJSON() (string, error) { 27 | data, err := json.Marshal(&e) 28 | if err != nil { 29 | return "", err 30 | } 31 | return string(data), nil 32 | } 33 | -------------------------------------------------------------------------------- /internal/app/sender/label.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package sender 6 | 7 | import ( 8 | "encoding/json" 9 | ) 10 | 11 | // Label struct 12 | type Label struct { 13 | Name string `json:"name"` 14 | Description string `json:"description"` 15 | Color string `json:"color"` 16 | } 17 | 18 | // LoadFromJSON update object from json 19 | func (e *Label) LoadFromJSON(data []byte) (bool, error) { 20 | err := json.Unmarshal(data, &e) 21 | if err != nil { 22 | return false, err 23 | } 24 | return true, nil 25 | } 26 | 27 | // ConvertToJSON convert object to json 28 | func (e *Label) ConvertToJSON() (string, error) { 29 | data, err := json.Marshal(&e) 30 | if err != nil { 31 | return "", err 32 | } 33 | return string(data), nil 34 | } 35 | -------------------------------------------------------------------------------- /plugin/base.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package plugin 6 | 7 | import ( 8 | "github.com/clivern/hamster/internal/app/event" 9 | "github.com/clivern/hamster/internal/app/pkg/logger" 10 | ) 11 | 12 | // RawListener Action 13 | func RawListener(raw event.Raw) (bool, error) { 14 | logger.Infof("Raw event listener fired [%v]!", raw) 15 | return true, nil 16 | } 17 | 18 | // StatusListener Action 19 | func StatusListener(status event.Status) (bool, error) { 20 | logger.Infof("Status event listener fired [%v]!", status) 21 | return true, nil 22 | } 23 | 24 | // WatchListener Action 25 | func WatchListener(watch event.Watch) (bool, error) { 26 | logger.Infof("Watch event listener fired [%v]!", watch) 27 | return true, nil 28 | } 29 | 30 | // IssuesListener Action 31 | func IssuesListener(issues event.Issues) (bool, error) { 32 | logger.Infof("Issues event listener fired [%v]!", issues) 33 | return true, nil 34 | } 35 | 36 | // IssueCommentListener Action 37 | func IssueCommentListener(issueComment event.IssueComment) (bool, error) { 38 | logger.Infof("IssueComment event listener fired [%v]!", issueComment) 39 | return true, nil 40 | } 41 | 42 | // CreateListener Action 43 | func CreateListener(create event.Create) (bool, error) { 44 | logger.Infof("Create event listener fired [%v]!", create) 45 | return true, nil 46 | } 47 | 48 | // LabelListener Action 49 | func LabelListener(label event.Label) (bool, error) { 50 | logger.Infof("Label event listener fired [%v]!", label) 51 | return true, nil 52 | } 53 | 54 | // DeleteListener Action 55 | func DeleteListener(delete event.Delete) (bool, error) { 56 | logger.Infof("Delete event listener fired [%v]!", delete) 57 | return true, nil 58 | } 59 | 60 | // MilestoneListener Action 61 | func MilestoneListener(milestone event.Milestone) (bool, error) { 62 | logger.Infof("Milestone event listener fired [%v]!", milestone) 63 | return true, nil 64 | } 65 | 66 | // PullRequestListener Action 67 | func PullRequestListener(pullRequest event.PullRequest) (bool, error) { 68 | logger.Infof("PullRequest event listener fired [%v]!", pullRequest) 69 | return true, nil 70 | } 71 | 72 | // PullRequestReviewListener Action 73 | func PullRequestReviewListener(pullRequestReview event.PullRequestReview) (bool, error) { 74 | logger.Infof("PullRequestReview event listener fired [%v]!", pullRequestReview) 75 | return true, nil 76 | } 77 | 78 | // PullRequestReviewCommentListener Action 79 | func PullRequestReviewCommentListener(pullRequestReviewComment event.PullRequestReviewComment) (bool, error) { 80 | logger.Infof("PullRequestReviewComment event listener fired [%v]!", pullRequestReviewComment) 81 | return true, nil 82 | } 83 | 84 | // CheckRunListener Action (Not Supported Yet) 85 | func CheckRunListener(checkRun event.CheckRun) (bool, error) { 86 | logger.Infof("CheckRun event listener fired [%v]!", checkRun) 87 | return true, nil 88 | } 89 | 90 | // CheckSuiteListener Action (Not Supported Yet) 91 | func CheckSuiteListener(checkSuite event.CheckSuite) (bool, error) { 92 | logger.Infof("CheckSuite event listener fired [%v]!", checkSuite) 93 | return true, nil 94 | } 95 | 96 | // CommitCommentListener Action (Not Supported Yet) 97 | func CommitCommentListener(commitComment event.CommitComment) (bool, error) { 98 | logger.Infof("CommitComment event listener fired [%v]!", commitComment) 99 | return true, nil 100 | } 101 | 102 | // DeploymentListener Action (Not Supported Yet) 103 | func DeploymentListener(deployment event.Deployment) (bool, error) { 104 | logger.Infof("Deployment event listener fired [%v]!", deployment) 105 | return true, nil 106 | } 107 | 108 | // DeploymentStatusListener Action (Not Supported Yet) 109 | func DeploymentStatusListener(deploymentStatus event.DeploymentStatus) (bool, error) { 110 | logger.Infof("DeploymentStatus event listener fired [%v]!", deploymentStatus) 111 | return true, nil 112 | } 113 | 114 | // ForkListener Action (Not Supported Yet) 115 | func ForkListener(fork event.Fork) (bool, error) { 116 | logger.Infof("Fork event listener fired [%v]!", fork) 117 | return true, nil 118 | } 119 | 120 | // GithubAppAuthorizationListener Action (Not Supported Yet) 121 | func GithubAppAuthorizationListener(githubAppAuthorization event.GithubAppAuthorization) (bool, error) { 122 | logger.Infof("GithubAppAuthorization event listener fired [%v]!", githubAppAuthorization) 123 | return true, nil 124 | } 125 | 126 | // GollumListener Action (Not Supported Yet) 127 | func GollumListener(gollum event.Gollum) (bool, error) { 128 | logger.Infof("Gollum event listener fired [%v]!", gollum) 129 | return true, nil 130 | } 131 | 132 | // InstallationListener Action (Not Supported Yet) 133 | func InstallationListener(installation event.Installation) (bool, error) { 134 | logger.Infof("Installation event listener fired [%v]!", installation) 135 | return true, nil 136 | } 137 | 138 | // InstallationRepositoriesListener Action (Not Supported Yet) 139 | func InstallationRepositoriesListener(installationRepositories event.InstallationRepositories) (bool, error) { 140 | logger.Infof("InstallationRepositories event listener fired [%v]!", installationRepositories) 141 | return true, nil 142 | } 143 | 144 | // MarketplacePurchaseListener Action (Not Supported Yet) 145 | func MarketplacePurchaseListener(marketplacePurchase event.MarketplacePurchase) (bool, error) { 146 | logger.Infof("MarketplacePurchase event listener fired [%v]!", marketplacePurchase) 147 | return true, nil 148 | } 149 | 150 | // MemberListener Action (Not Supported Yet) 151 | func MemberListener(member event.Member) (bool, error) { 152 | logger.Infof("Member event listener fired [%v]!", member) 153 | return true, nil 154 | } 155 | 156 | // MembershipListener Action (Not Supported Yet) 157 | func MembershipListener(membership event.Membership) (bool, error) { 158 | logger.Infof("Membership event listener fired [%v]!", membership) 159 | return true, nil 160 | } 161 | 162 | // OrgBlockListener Action (Not Supported Yet) 163 | func OrgBlockListener(orgBlock event.OrgBlock) (bool, error) { 164 | logger.Infof("OrgBlock event listener fired [%v]!", orgBlock) 165 | return true, nil 166 | } 167 | 168 | // OrganizationListener Action (Not Supported Yet) 169 | func OrganizationListener(organization event.Organization) (bool, error) { 170 | logger.Infof("Organization event listener fired [%v]!", organization) 171 | return true, nil 172 | } 173 | 174 | // PageBuildListener Action (Not Supported Yet) 175 | func PageBuildListener(pageBuild event.PageBuild) (bool, error) { 176 | logger.Infof("PageBuild event listener fired [%v]!", pageBuild) 177 | return true, nil 178 | } 179 | 180 | // ProjectListener Action (Not Supported Yet) 181 | func ProjectListener(project event.Project) (bool, error) { 182 | logger.Infof("Project event listener fired [%v]!", project) 183 | return true, nil 184 | } 185 | 186 | // ProjectCardListener Action (Not Supported Yet) 187 | func ProjectCardListener(projectCard event.ProjectCard) (bool, error) { 188 | logger.Infof("ProjectCard event listener fired [%v]!", projectCard) 189 | return true, nil 190 | } 191 | 192 | // ProjectColumnListener Action (Not Supported Yet) 193 | func ProjectColumnListener(projectColumn event.ProjectColumn) (bool, error) { 194 | logger.Infof("ProjectColumn event listener fired [%v]!", projectColumn) 195 | return true, nil 196 | } 197 | 198 | // PublicListener Action (Not Supported Yet) 199 | func PublicListener(public event.Public) (bool, error) { 200 | logger.Infof("Public event listener fired [%v]!", public) 201 | return true, nil 202 | } 203 | 204 | // PushListener Action (Not Supported Yet) 205 | func PushListener(push event.Push) (bool, error) { 206 | logger.Infof("Push event listener fired [%v]!", push) 207 | return true, nil 208 | } 209 | 210 | // ReleaseListener Action (Not Supported Yet) 211 | func ReleaseListener(release event.Release) (bool, error) { 212 | logger.Infof("Release event listener fired [%v]!", release) 213 | return true, nil 214 | } 215 | 216 | // RepositoryListener Action (Not Supported Yet) 217 | func RepositoryListener(repository event.Repository) (bool, error) { 218 | logger.Infof("Repository event listener fired [%v]!", repository) 219 | return true, nil 220 | } 221 | 222 | // RepositoryImportListener Action (Not Supported Yet) 223 | func RepositoryImportListener(repositoryImport event.RepositoryImport) (bool, error) { 224 | logger.Infof("RepositoryImport event listener fired [%v]!", repositoryImport) 225 | return true, nil 226 | } 227 | 228 | // RepositoryVulnerabilityAlertListener Action (Not Supported Yet) 229 | func RepositoryVulnerabilityAlertListener(repositoryVulnerabilityAlert event.RepositoryVulnerabilityAlert) (bool, error) { 230 | logger.Infof("RepositoryVulnerabilityAlert event listener fired [%v]!", repositoryVulnerabilityAlert) 231 | return true, nil 232 | } 233 | 234 | // TeamListener Action (Not Supported Yet) 235 | func TeamListener(team event.Team) (bool, error) { 236 | logger.Infof("Team event listener fired [%v]!", team) 237 | return true, nil 238 | } 239 | 240 | // TeamAddListener Action (Not Supported Yet) 241 | func TeamAddListener(teamAdd event.TeamAdd) (bool, error) { 242 | logger.Infof("TeamAdd event listener fired [%v]!", teamAdd) 243 | return true, nil 244 | } 245 | 246 | // IssuesTestCommandListener Command 247 | func IssuesTestCommandListener(command event.Command, issues event.Issues) (bool, error) { 248 | logger.Infof("IssuesTestCommandListener event listener fired [%v] [%v]!", command, issues) 249 | return true, nil 250 | } 251 | 252 | // IssueCommentTestCommandListener Command 253 | func IssueCommentTestCommandListener(command event.Command, issueComment event.IssueComment) (bool, error) { 254 | logger.Infof("IssueCommentTestCommandListener event listener fired! [%v] [%v]!", command, issueComment) 255 | return true, nil 256 | } 257 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /templates/index.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ .title }} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 59 | 60 | 61 |
62 |
63 | 64 |
65 | {{ .title }} 66 |
67 |
68 |
69 | 70 | -------------------------------------------------------------------------------- /templates/login.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ .title }} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 59 | 60 | 61 |
62 | 63 |
64 | 65 |
66 | {{ .title }} 67 |
68 | 71 |
72 |
73 | 74 | -------------------------------------------------------------------------------- /var/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore --------------------------------------------------------------------------------