Skip to content

Commit f683af5

Browse files
committed
Initial commit with support for GitHub actions
1 parent d136b83 commit f683af5

33 files changed

Lines changed: 2941 additions & 1 deletion

.editorconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Override for Makefile
2+
[{Makefile, makefile, GNUmakefile}]
3+
indent_style = tab
4+
indent_size = 4

.github/actions/check/Dockerfile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
FROM golang:1.11.4-stretch
2+
3+
RUN go get -u honnef.co/go/tools/cmd/staticcheck
4+
RUN go get -u golang.org/x/lint/golint
5+
RUN go get -u github.com/fzipp/gocyclo
6+
7+
COPY "entrypoint.sh" "/entrypoint.sh"
8+
RUN chmod +x /entrypoint.sh
9+
10+
ENTRYPOINT ["/entrypoint.sh"]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/sh
2+
3+
#GOPATH=/go
4+
#PATH=${GOPATH}/bin:/usr/local/go/bin:${PATH}
5+
6+
go vet ./...
7+
golint -set_exit_status ./...
8+
staticcheck ./...
9+
gocyclo -over 10 .
10+
go test -cover ./...

.github/main.workflow

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
workflow "check-and-release" {
2+
on = "push"
3+
resolves = ["release"]
4+
}
5+
6+
action "check" {
7+
uses = "./.github/actions/check"
8+
}
9+
10+
action "branch-filter" {
11+
needs = ["check"]
12+
uses = "actions/bin/filter@master"
13+
args = "tag v*"
14+
}
15+
16+
action "release" {
17+
needs = ["branch-filter"]
18+
uses = "docker://goreleaser/goreleaser:v0.97"
19+
args = "release"
20+
secrets = ["GITHUB_TOKEN"]
21+
}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@
1010

1111
# Output of the go coverage tool, specifically when used with LiteIDE
1212
*.out
13+
14+
dist/
15+
.todo

.goreleaser.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
before:
2+
hooks:
3+
- go mod download
4+
builds:
5+
- env:
6+
- CGO_ENABLED=0
7+
goos:
8+
- darwin
9+
- linux
10+
- windows
11+
goarch:
12+
- amd64
13+
- 386
14+
checksum:
15+
name_template: 'checksums.txt'
16+
snapshot:
17+
name_template: "{{ .Env.SNAPSHOT_VERSION }}"
18+
archive:
19+
name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}'
20+
replacements:
21+
darwin: Darwin
22+
linux: Linux
23+
windows: Windows
24+
386: i386
25+
amd64: x86_64
26+
format_overrides:
27+
- goos: windows
28+
format: zip
29+
brew:
30+
github:
31+
owner: nektos
32+
name: homebrew-tap
33+
folder: Formula
34+
homepage: https://github.com/nektos/act
35+
description: Run GitHub Actions locally
36+
test: |
37+
system "#{bin}/act --version"

CONTRIBUTING.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Contributing to Act
2+
3+
Help wanted! We'd love your contributions to Act. Please review the following guidelines before contributing. Also, feel free to propose changes to these guidelines by updating this file and submitting a pull request.
4+
5+
* [I have a question...](#questions)
6+
* [I found a bug...](#bugs)
7+
* [I have a feature request...](#features)
8+
* [I have a contribution to share...](#process)
9+
10+
## <a name="questions"></a> Have a Question?
11+
12+
Please don't open a GitHub issue for questions about how to use `act`, as the goal is to use issues for managing bugs and feature requests. Issues that are related to general support will be closed and redirected to our gitter room.
13+
14+
For all support related questions, please ask the question in our gitter room: [nektos/act](https://gitter.im/nektos/act).
15+
16+
## <a name="bugs"></a> Found a Bug?
17+
18+
If you've identified a bug in `act`, please [submit an issue](#issue) to our GitHub repo: [nektos/act](https://github.com/nektos/act/issues/new). Please also feel free to submit a [Pull Request](#pr) with a fix for the bug!
19+
20+
## <a name="features"></a> Have a Feature Request?
21+
22+
All feature requests should start with [submitting an issue](#issue) documenting the user story and acceptance criteria. Again, feel free to submit a [Pull Request](#pr) with a proposed implementation of the feature.
23+
24+
## <a name="process"></a> Ready to Contribute!
25+
26+
### <a name="issue"></a> Create an issue
27+
28+
Before submitting a new issue, please search the issues to make sure there isn't a similar issue doesn't already exist.
29+
30+
Assuming no existing issues exist, please ensure you include the following bits of information when submitting the issue to ensure we can quickly reproduce your issue:
31+
32+
* Version of `act`
33+
* Platform (Linux, OS X, Windows)
34+
* The complete `main.workflow` file used
35+
* The complete command that was executed
36+
* Any output from the command
37+
* Details of the expected results and how they differed from the actual results
38+
39+
We may have additional questions and will communicate through the GitHub issue, so please respond back to our questions to help reproduce and resolve the issue as quickly as possible.
40+
41+
New issues can be created with in our [GitHub repo](https://github.com/nektos/act/issues/new).
42+
43+
### <a name="pr"></a>Pull Requests
44+
45+
Pull requests should target the `master` branch. Please also reference the issue from the description of the pull request using [special keyword syntax](https://help.github.com/articles/closing-issues-via-commit-messages/) to auto close the issue when the PR is merged. For example, include the phrase `fixes #14` in the PR description to have issue #14 auto close.
46+
47+
### <a name="style"></a> Styleguide
48+
49+
When submitting code, please make every effort to follow existing conventions and style in order to keep the code as readable as possible. Here are a few points to keep in mind:
50+
51+
* Please run `go fmt ./...` before committing to ensure code aligns with go standards.
52+
* All dependencies must be defined in the `go.mod` file.
53+
* For details on the approved style, check out [Effective Go](https://golang.org/doc/effective_go.html).
54+
55+
Also, consider the original design principles:
56+
57+
* **Polyglot** - There will be no prescribed language or framework for developing the microservices. The only requirement will be that the service will be run inside a container and exposed via an HTTP endpoint.
58+
* **Cloud Provider** - At this point, the tool will assume AWS for the cloud provider and will not be written in a cloud agnostic manner. However, this does not preclude refactoring to add support for other providers at a later time.
59+
* **Declarative** - All resource administration will be handled in a declarative vs. imperative manner. A file will be used to declared the desired state of the resources and the tool will simply assert the actual state matches the desired state. The tool will accomplish this by generating CloudFormation templates.
60+
* **Stateless** - The tool will not maintain its own state. Rather, it will rely on the CloudFormation stacks to determine the state of the platform.
61+
* **Secure** - All security will be managed by AWS IAM credentials. No additional authentication or authorization mechanisms will be introduced.
62+
63+
### License
64+
65+
By contributing your code, you agree to license your contribution under the terms of the [MIT License](LICENSE.md).
66+
67+
All files are released with the MIT license.

Makefile

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
LATEST_VERSION := $(shell git tag -l --sort=creatordate | grep "^v[0-9]*.[0-9]*.[0-9]*$$" | tail -1 | cut -c 2-)
2+
ifeq "$(shell git tag -l v$(LATEST_VERSION) --points-at HEAD)" "v$(LATEST_VERSION)"
3+
### latest tag points to current commit, this is a release build
4+
VERSION ?= $(LATEST_VERSION)
5+
else
6+
### latest tag points to prior commit, this is a snapshot build
7+
MAJOR_VERSION := $(word 1, $(subst ., ,$(LATEST_VERSION)))
8+
MINOR_VERSION := $(word 2, $(subst ., ,$(LATEST_VERSION)))
9+
PATCH_VERSION := $(word 3, $(subst ., ,$(LATEST_VERSION)))
10+
VERSION ?= $(MAJOR_VERSION).$(MINOR_VERSION).$(shell echo $$(( $(PATCH_VERSION) + 1)) )-develop
11+
endif
12+
IS_SNAPSHOT = $(if $(findstring -, $(VERSION)),true,false)
13+
TAG_VERSION = v$(VERSION)
14+
15+
default: check
16+
17+
deps:
18+
@GO111MODULE=off go get honnef.co/go/tools/cmd/staticcheck
19+
@GO111MODULE=off go get golang.org/x/lint/golint
20+
@GO111MODULE=off go get github.com/fzipp/gocyclo
21+
22+
check:
23+
go vet ./...
24+
golint -set_exit_status ./...
25+
staticcheck ./...
26+
gocyclo -over 10 .
27+
go test -cover ./...
28+
29+
build: deps check
30+
@GO111MODULE=off go get github.com/goreleaser/goreleaser
31+
$(eval export SNAPSHOT_VERSION=$(VERSION))
32+
@goreleaser --snapshot --rm-dist
33+
34+
install: build
35+
@cp dist/$(shell go env GOOS)_$(shell go env GOARCH)/act /usr/local/bin/act
36+
@chmod 755 /usr/local/bin/act
37+
@act --version
38+
39+
installer:
40+
@GO111MODULE=off go get github.com/goreleaser/godownloader
41+
godownloader -r nektos/act -o install.sh
42+
43+
44+
promote:
45+
@echo "VERSION:$(VERSION) IS_SNAPSHOT:$(IS_SNAPSHOT) LATEST_VERSION:$(LATEST_VERSION)"
46+
ifeq (false,$(IS_SNAPSHOT))
47+
@echo "Unable to promote a non-snapshot"
48+
@exit 1
49+
endif
50+
ifneq ($(shell git status -s),)
51+
@echo "Unable to promote a dirty workspace"
52+
@exit 1
53+
endif
54+
$(eval NEW_VERSION := $(word 1,$(subst -, , $(TAG_VERSION))))
55+
git tag -a -m "releasing $(NEW_VERSION)" $(NEW_VERSION)
56+
git push origin $(NEW_VERSION)

README.md

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,57 @@
1-
# act
1+
[![Join the chat at https://gitter.im/nektos/act](https://badges.gitter.im/nektos/act.svg)](https://gitter.im/nektos/act?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Go Report Card](https://goreportcard.com/badge/github.com/nektos/act)](https://goreportcard.com/report/github.com/nektos/act)
2+
3+
# Overview
4+
Run your [GitHub Actions](https://developer.github.com/actions/) locally! Why would you want to do this? Two reasons:
5+
6+
* **Fast Feedback** - Rather than having to commit/push every time you want test out the changes you are making to your `main.workflow` file (or for any changes to embedded GitHub actions), you can use `act` to run the actions locally. The [environment variables](https://developer.github.com/actions/creating-github-actions/accessing-the-runtime-environment/#environment-variables) and [filesystem](https://developer.github.com/actions/creating-github-actions/accessing-the-runtime-environment/#filesystem) are all configured to match what GitHub provides.
7+
* **Local Task Runner** - I love [make](https://en.wikipedia.org/wiki/Make_(software)). However, I also hate repeating myself. With `act`, you can use the GitHub Actions defined in your `main.workflow` file to replace your `Makefile`!
8+
9+
# How Does It Work?
10+
When you run `act` it reads in your GitHub Actions from `.github/main.workflow` and determines the set of actions that need to be run. It uses the Docker API to either pull or build the necessary images, as defined in your `main.workflow` file and finally determines the execution path based on the dependencies that were defined. Once it has the execution path, it the uses the Docker API to run containers for each action based on the images prepared earlier. The [environment variables](https://developer.github.com/actions/creating-github-actions/accessing-the-runtime-environment/#environment-variables) and [filesystem](https://developer.github.com/actions/creating-github-actions/accessing-the-runtime-environment/#filesystem) are all configured to match what GitHub provides.
11+
12+
Let's see it in action with a [sample repo](https://github.com/cplee/github-actions-demo)!
13+
14+
![Demo](https://github.com/nektos/act/wiki/quickstart/act-quickstart.gif)
15+
16+
# Installation
17+
To install with [Homebrew](https://brew.sh/), run:
18+
19+
```brew install nektos/tap/act```
20+
21+
Alternatively, you can use the following:
22+
23+
```curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo sh```
24+
25+
# Commands
26+
27+
```
28+
# List the actions
29+
act -l
30+
31+
# Run the default (`push`) event:
32+
act
33+
34+
# Run a specific event:
35+
act pull-request
36+
37+
# Run a specific action:
38+
act -t test
39+
40+
# Run in dry-run mode:
41+
act -n
42+
```
43+
44+
# Support
45+
46+
Need help? Ask on [Gitter](https://gitter.im/nektos/act)!
47+
48+
# Contributing
49+
50+
Want to contribute to act? Awesome! Check out the [contributing guidelines](CONTRIBUTING.md) to get involved.
51+
52+
## Building from source
53+
54+
* Install Go tools 1.11+ - (https://golang.org/doc/install)
55+
* Clone this repo `git clone git@github.com:nektos/act.git`
56+
* Run unit tests with `make check`
57+
* Build and install: `make install`

actions/log.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package actions
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"io"
7+
"os"
8+
"strings"
9+
10+
"github.com/sirupsen/logrus"
11+
"golang.org/x/crypto/ssh/terminal"
12+
)
13+
14+
type actionLogFormatter struct {
15+
}
16+
17+
var formatter *actionLogFormatter
18+
19+
func init() {
20+
formatter = new(actionLogFormatter)
21+
}
22+
23+
const (
24+
//nocolor = 0
25+
red = 31
26+
green = 32
27+
yellow = 33
28+
blue = 36
29+
gray = 37
30+
)
31+
32+
func newActionLogger(actionName string, dryrun bool) *logrus.Entry {
33+
logger := logrus.New()
34+
logger.SetFormatter(formatter)
35+
logger.SetLevel(logrus.GetLevel())
36+
rtn := logger.WithFields(logrus.Fields{"action_name": actionName, "dryrun": dryrun})
37+
return rtn
38+
}
39+
40+
func (f *actionLogFormatter) Format(entry *logrus.Entry) ([]byte, error) {
41+
b := &bytes.Buffer{}
42+
43+
if f.isColored(entry) {
44+
f.printColored(b, entry)
45+
} else {
46+
f.print(b, entry)
47+
}
48+
49+
b.WriteByte('\n')
50+
return b.Bytes(), nil
51+
}
52+
53+
func (f *actionLogFormatter) printColored(b *bytes.Buffer, entry *logrus.Entry) {
54+
var levelColor int
55+
switch entry.Level {
56+
case logrus.DebugLevel, logrus.TraceLevel:
57+
levelColor = gray
58+
case logrus.WarnLevel:
59+
levelColor = yellow
60+
case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel:
61+
levelColor = red
62+
default:
63+
levelColor = blue
64+
}
65+
66+
entry.Message = strings.TrimSuffix(entry.Message, "\n")
67+
actionName := entry.Data["action_name"]
68+
69+
if entry.Data["dryrun"] == true {
70+
fmt.Fprintf(b, "\x1b[%dm*DRYRUN* \x1b[%dm[%s] \x1b[0m%s", green, levelColor, actionName, entry.Message)
71+
} else {
72+
fmt.Fprintf(b, "\x1b[%dm[%s] \x1b[0m%s", levelColor, actionName, entry.Message)
73+
}
74+
}
75+
76+
func (f *actionLogFormatter) print(b *bytes.Buffer, entry *logrus.Entry) {
77+
entry.Message = strings.TrimSuffix(entry.Message, "\n")
78+
actionName := entry.Data["action_name"]
79+
80+
if entry.Data["dryrun"] == true {
81+
fmt.Fprintf(b, "*DRYRUN* [%s] %s", actionName, entry.Message)
82+
} else {
83+
fmt.Fprintf(b, "[%s] %s", actionName, entry.Message)
84+
}
85+
}
86+
87+
func (f *actionLogFormatter) isColored(entry *logrus.Entry) bool {
88+
89+
isColored := checkIfTerminal(entry.Logger.Out)
90+
91+
if force, ok := os.LookupEnv("CLICOLOR_FORCE"); ok && force != "0" {
92+
isColored = true
93+
} else if ok && force == "0" {
94+
isColored = false
95+
} else if os.Getenv("CLICOLOR") == "0" {
96+
isColored = false
97+
}
98+
99+
return isColored
100+
}
101+
102+
func checkIfTerminal(w io.Writer) bool {
103+
switch v := w.(type) {
104+
case *os.File:
105+
return terminal.IsTerminal(int(v.Fd()))
106+
default:
107+
return false
108+
}
109+
}

0 commit comments

Comments
 (0)