Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Dean Karn authored May 21, 2023
2 parents bb56096 + 336e0a0 commit c29986c
Show file tree
Hide file tree
Showing 28 changed files with 5,320 additions and 45 deletions.
27 changes: 14 additions & 13 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,37 @@ on:

name: Test
jobs:
lint:
name: Lint
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2

- name: Run linter
uses: golangci/golangci-lint-action@v2
- uses: actions/setup-go@v3
with:
go-version: 1.20.x
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.35.2
version: latest

test:
name: Test
strategy:
matrix:
go-version: [1.14.x, 1.15.x]
go-version: [1.17.x, 1.18.x, 1.20.x]
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Install Go
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}

- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Restore cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-v1-go-${{ hashFiles('**/go.sum') }}
Expand All @@ -46,7 +47,7 @@ jobs:
run: go test -race -covermode=atomic -coverprofile="coverage.out" ./...

- name: Upload coverage report to Coveralls
if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.15.x'
if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.18.x'
uses: shogo82148/actions-goveralls@v1
with:
path-to-profile: coverage.out
16 changes: 0 additions & 16 deletions .golangci.yml

This file was deleted.

15 changes: 2 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
GOPATH=$(shell go env GOPATH)

all: lint test

linters-install:
@echo "+ $@"
@$(GOPATH)/bin/golangci-lint --version >/dev/null 2>&1 || { \
echo "Install golangci-lint..."; \
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin; \
}

lint: linters-install
@echo "+ $@"
$(GOPATH)/bin/golangci-lint run ./...
golangci-lint run --timeout 5m

test:
@echo "+ $@"
GO111MODULE=on go test -covermode=atomic -race ./...
go test -covermode=atomic -race ./...

.PHONY: test lint linters-install
.DEFAULT_GOAL := all
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Library webhooks
================
<img align="right" src="https://raw.githubusercontent.com/go-playground/webhooks/v6/logo.png">![Project status](https://img.shields.io/badge/version-6.0.1-green.svg)
<img align="right" src="https://raw.githubusercontent.com/go-playground/webhooks/v6/logo.png">![Project status](https://img.shields.io/badge/version-6.1.0-green.svg)
[![Test](https://github.com/go-playground/webhooks/workflows/Test/badge.svg?branch=master)](https://github.com/go-playground/webhooks/actions)
[![Coverage Status](https://coveralls.io/repos/go-playground/webhooks/badge.svg?branch=master&service=github)](https://coveralls.io/github/go-playground/webhooks?branch=master)
[![Go Report Card](https://goreportcard.com/badge/go-playground/webhooks)](https://goreportcard.com/report/go-playground/webhooks)
Expand Down
179 changes: 179 additions & 0 deletions gitea/gitea.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package gitea

import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
)

// parse errors
var (
ErrEventNotSpecifiedToParse = errors.New("no Event specified to parse")
ErrInvalidHTTPMethod = errors.New("invalid HTTP Method")
ErrMissingGiteaEventHeader = errors.New("missing X-Gitea-Event Header")
ErrMissingGiteaSignatureHeader = errors.New("missing X-Gitea-Signature Header")
ErrEventNotFound = errors.New("event not defined to be parsed")
ErrParsingPayload = errors.New("error parsing payload")
ErrHMACVerificationFailed = errors.New("HMAC verification failed")
)

// Gitea hook types
// https://github.com/go-gitea/gitea/blob/bf7b083cfe47cc922090ce7922b89f7a5030a44d/models/webhook/hooktask.go#L31
const (
CreateEvent Event = "create"
DeleteEvent Event = "delete"
ForkEvent Event = "fork"
IssuesEvent Event = "issues"
IssueAssignEvent Event = "issue_assign"
IssueLabelEvent Event = "issue_label"
IssueMilestoneEvent Event = "issue_milestone"
IssueCommentEvent Event = "issue_comment"
PushEvent Event = "push"
PullRequestEvent Event = "pull_request"
PullRequestAssignEvent Event = "pull_request_assign"
PullRequestLabelEvent Event = "pull_request_label"
PullRequestMilestoneEvent Event = "pull_request_milestone"
PullRequestCommentEvent Event = "pull_request_comment"
PullRequestReviewEvent Event = "pull_request_review"
PullRequestSyncEvent Event = "pull_request_sync"
RepositoryEvent Event = "repository"
ReleaseEvent Event = "release"
)

// Option is a configuration option for the webhook
type Option func(*Webhook) error

// Options is a namespace var for configuration options
var Options = WebhookOptions{}

// WebhookOptions is a namespace for configuration option methods
type WebhookOptions struct{}

// Secret registers the GitLab secret
func (WebhookOptions) Secret(secret string) Option {
return func(hook *Webhook) error {
hook.secret = secret
return nil
}
}

// Webhook instance contains all methods needed to process events
type Webhook struct {
secret string
}

// Event defines a GitLab hook event type by the X-Gitlab-Event Header
type Event string

// New creates and returns a WebHook instance denoted by the Provider type
func New(options ...Option) (*Webhook, error) {
hook := new(Webhook)
for _, opt := range options {
if err := opt(hook); err != nil {
return nil, errors.New("Error applying Option")
}
}
return hook, nil
}

// Parse verifies and parses the events specified and returns the payload object or an error
func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error) {
defer func() {
_, _ = io.Copy(ioutil.Discard, r.Body)
_ = r.Body.Close()
}()

if len(events) == 0 {
return nil, ErrEventNotSpecifiedToParse
}
if r.Method != http.MethodPost {
return nil, ErrInvalidHTTPMethod
}

event := r.Header.Get("X-Gitea-Event")
if len(event) == 0 {
return nil, ErrMissingGiteaEventHeader
}

giteaEvent := Event(event)

var found bool
for _, evt := range events {
if evt == giteaEvent {
found = true
break
}
}
// event not defined to be parsed
if !found {
return nil, ErrEventNotFound
}

payload, err := ioutil.ReadAll(r.Body)
if err != nil || len(payload) == 0 {
return nil, ErrParsingPayload
}

// If we have a Secret set, we should check the MAC
if len(hook.secret) > 0 {
signature := r.Header.Get("X-Gitea-Signature")
if len(signature) == 0 {
return nil, ErrMissingGiteaSignatureHeader
}
sig256 := hmac.New(sha256.New, []byte(hook.secret))
_, _ = io.Writer(sig256).Write([]byte(payload))
expectedMAC := hex.EncodeToString(sig256.Sum(nil))

if !hmac.Equal([]byte(signature), []byte(expectedMAC)) {
return nil, ErrHMACVerificationFailed
}
}

// https://github.com/go-gitea/gitea/blob/33fca2b537d36cf998dd27425b2bb8ed5b0965f3/services/webhook/payloader.go#L27
switch giteaEvent {
case CreateEvent:
var pl CreatePayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case DeleteEvent:
var pl DeletePayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case ForkEvent:
var pl ForkPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case PushEvent:
var pl PushPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case IssuesEvent, IssueAssignEvent, IssueLabelEvent, IssueMilestoneEvent:
var pl IssuePayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case IssueCommentEvent, PullRequestCommentEvent:
var pl IssueCommentPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case PullRequestEvent, PullRequestAssignEvent, PullRequestLabelEvent, PullRequestMilestoneEvent, PullRequestReviewEvent, PullRequestSyncEvent:
var pl PullRequestPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case RepositoryEvent:
var pl RepositoryPayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
case ReleaseEvent:
var pl ReleasePayload
err = json.Unmarshal([]byte(payload), &pl)
return pl, err
default:
return nil, fmt.Errorf("unknown event %s", giteaEvent)
}
}
Loading

0 comments on commit c29986c

Please sign in to comment.