mirror of
https://gitea.com/gitea/runner.git
synced 2026-11-14 03:43:42 +00:00
466 files changed
+94680
-62523
No files matched your search
@@ -1,14 +0,0 @@
|
|||||||
FROM golangci/golangci-lint:v1.12.5
|
|
||||||
|
|
||||||
RUN apt-get install git
|
|
||||||
|
|
||||||
LABEL "com.github.actions.name"="Check"
|
|
||||||
LABEL "com.github.actions.description"="Run static analysis and unit tests"
|
|
||||||
LABEL "com.github.actions.icon"="check-circle"
|
|
||||||
LABEL "com.github.actions.color"="green"
|
|
||||||
|
|
||||||
COPY "entrypoint.sh" "/entrypoint.sh"
|
|
||||||
RUN chmod +x /entrypoint.sh
|
|
||||||
|
|
||||||
ENV GOFLAGS -mod=vendor
|
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
FROM golangci/golangci-lint:v1.12.5
|
|
||||||
|
|
||||||
LABEL "com.github.actions.name"="Check"
|
|
||||||
LABEL "com.github.actions.description"="Run integration tests"
|
|
||||||
LABEL "com.github.actions.icon"="check-circle"
|
|
||||||
LABEL "com.github.actions.color"="green"
|
|
||||||
|
|
||||||
COPY "entrypoint.sh" "/entrypoint.sh"
|
|
||||||
RUN chmod +x /entrypoint.sh
|
|
||||||
|
|
||||||
ENV GOFLAGS -mod=vendor
|
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
go test -cover ./actions
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
workflow "check-and-release" {
|
|
||||||
on = "push"
|
|
||||||
resolves = ["release"]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "check" {
|
|
||||||
uses = "./.github/actions/check"
|
|
||||||
}
|
|
||||||
|
|
||||||
action "release-filter" {
|
|
||||||
needs = ["check"]
|
|
||||||
uses = "actions/bin/filter@master"
|
|
||||||
args = "tag 'v*'"
|
|
||||||
}
|
|
||||||
|
|
||||||
# only release on `v*` tags
|
|
||||||
action "release" {
|
|
||||||
needs = ["release-filter"]
|
|
||||||
uses = "docker://goreleaser/goreleaser:v0.98"
|
|
||||||
args = "release"
|
|
||||||
secrets = ["GITHUB_TOKEN"]
|
|
||||||
}
|
|
||||||
|
|
||||||
# local action for `make build`
|
|
||||||
action "build" {
|
|
||||||
uses = "docker://goreleaser/goreleaser:v0.98"
|
|
||||||
args = "--snapshot --rm-dist"
|
|
||||||
secrets = ["SNAPSHOT_VERSION"]
|
|
||||||
}
|
|
||||||
|
|
||||||
# local action for `make vendor`
|
|
||||||
action "vendor" {
|
|
||||||
uses = "docker://golang:1.11.4"
|
|
||||||
args = "go mod vendor"
|
|
||||||
}
|
|
||||||
|
|
||||||
action "integration-tests" {
|
|
||||||
needs = ["check"]
|
|
||||||
uses = "./.github/actions/integration"
|
|
||||||
}
|
|
||||||
|
|
||||||
# local release
|
|
||||||
action "local-release" {
|
|
||||||
needs = ["integration-tests"]
|
|
||||||
uses = "docker://goreleaser/goreleaser:v0.98"
|
|
||||||
args = "release"
|
|
||||||
secrets = ["GITHUB_TOKEN"]
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
name: basic
|
|
||||||
on: push
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
action:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: node:10.16-jessie
|
|
||||||
env:
|
|
||||||
NODE_ENV: development
|
|
||||||
steps:
|
|
||||||
- run: env
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [build]
|
|
||||||
steps:
|
|
||||||
- run: cp $GITHUB_EVENT_PATH $HOME/foo.json
|
|
||||||
- run: ls $HOME
|
|
||||||
- run: cat $HOME/foo.json
|
|
||||||
- uses: docker://alpine:3.8
|
|
||||||
with:
|
|
||||||
args: uname -a
|
|
||||||
local-action:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: ./.github/workflows/docker-url
|
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
FROM golangci/golangci-lint:v1.23.6
|
||||||
|
|
||||||
|
RUN apt-get install git
|
||||||
|
|
||||||
|
COPY "entrypoint.sh" "/entrypoint.sh"
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
ENV GOFLAGS -mod=vendor
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
name: Check
|
||||||
|
description: Run static analysis and unit tests
|
||||||
|
branding:
|
||||||
|
icon: check-circle
|
||||||
|
color: green
|
||||||
|
runs:
|
||||||
|
using: 'docker'
|
||||||
|
image: 'Dockerfile'
|
||||||
File renamed without changes.
@@ -0,0 +1,7 @@
|
|||||||
|
FROM golangci/golangci-lint:v1.23.6
|
||||||
|
|
||||||
|
COPY "entrypoint.sh" "/entrypoint.sh"
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
ENV GOFLAGS -mod=vendor
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
name: Check
|
||||||
|
description: Run integration tests
|
||||||
|
branding:
|
||||||
|
icon: check-circle
|
||||||
|
color: green
|
||||||
|
runs:
|
||||||
|
using: 'docker'
|
||||||
|
image: 'Dockerfile'
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
go test -cover ./runner
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
name: push
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: ./.github/workflows/check
|
||||||
|
- uses: ./.github/workflows/integration
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
name: tag
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: ./.github/workflows/check
|
||||||
|
- uses: ./.github/workflows/integration
|
||||||
|
- uses: goreleaser/goreleaser-action@v1
|
||||||
|
- name: Run GoReleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v1
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
args: release --rm-dist
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -21,7 +21,7 @@ test:
|
|||||||
go test -cover -short ./...
|
go test -cover -short ./...
|
||||||
|
|
||||||
check:
|
check:
|
||||||
$(ACT) -ra check
|
$(ACT) -rj ci
|
||||||
|
|
||||||
build: check
|
build: check
|
||||||
$(eval export SNAPSHOT_VERSION=$(VERSION))
|
$(eval export SNAPSHOT_VERSION=$(VERSION))
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
package actions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/howeyc/gopass"
|
|
||||||
)
|
|
||||||
|
|
||||||
var secretCache map[string]string
|
|
||||||
|
|
||||||
type actionEnvironmentApplier struct {
|
|
||||||
*Action
|
|
||||||
}
|
|
||||||
|
|
||||||
type Action struct{}
|
|
||||||
|
|
||||||
func newActionEnvironmentApplier(action *Action) environmentApplier {
|
|
||||||
return &actionEnvironmentApplier{action}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (action *actionEnvironmentApplier) applyEnvironment(env map[string]string) {
|
|
||||||
for envKey, envValue := range action.Env {
|
|
||||||
env[envKey] = envValue
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, secret := range action.Secrets {
|
|
||||||
if secretVal, ok := os.LookupEnv(secret); ok {
|
|
||||||
env[secret] = secretVal
|
|
||||||
} else {
|
|
||||||
if secretCache == nil {
|
|
||||||
secretCache = make(map[string]string)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := secretCache[secret]; !ok {
|
|
||||||
fmt.Printf("Provide value for '%s': ", secret)
|
|
||||||
val, err := gopass.GetPasswdMasked()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("abort")
|
|
||||||
}
|
|
||||||
|
|
||||||
secretCache[secret] = string(val)
|
|
||||||
}
|
|
||||||
env[secret] = secretCache[secret]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,255 +0,0 @@
|
|||||||
package runner
|
|
||||||
|
|
||||||
import (
|
|
||||||
"archive/tar"
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
|
||||||
"github.com/nektos/act/pkg/container"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (runner *runnerImpl) newRunExecutor(run *model.Run) common.Executor {
|
|
||||||
action := runner.workflowConfig.GetAction(actionName)
|
|
||||||
if action == nil {
|
|
||||||
return common.NewErrorExecutor(fmt.Errorf("Unable to find action named '%s'", actionName))
|
|
||||||
}
|
|
||||||
|
|
||||||
executors := make([]common.Executor, 0)
|
|
||||||
image, err := runner.addImageExecutor(action, &executors)
|
|
||||||
if err != nil {
|
|
||||||
return common.NewErrorExecutor(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = runner.addRunExecutor(action, image, &executors)
|
|
||||||
if err != nil {
|
|
||||||
return common.NewErrorExecutor(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return common.NewPipelineExecutor(executors...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (runner *runnerImpl) addImageExecutor(action *Action, executors *[]common.Executor) (string, error) {
|
|
||||||
var image string
|
|
||||||
logger := newActionLogger(action.Identifier, runner.config.Dryrun)
|
|
||||||
log.Debugf("Using '%s' for action '%s'", action.Uses, action.Identifier)
|
|
||||||
|
|
||||||
in := container.DockerExecutorInput{
|
|
||||||
Ctx: runner.config.Ctx,
|
|
||||||
Logger: logger,
|
|
||||||
Dryrun: runner.config.Dryrun,
|
|
||||||
}
|
|
||||||
switch uses := action.Uses.(type) {
|
|
||||||
|
|
||||||
case *model.UsesDockerImage:
|
|
||||||
image = uses.Image
|
|
||||||
|
|
||||||
pull := runner.config.ForcePull
|
|
||||||
if !pull {
|
|
||||||
imageExists, err := container.ImageExistsLocally(runner.config.Ctx, image)
|
|
||||||
log.Debugf("Image exists? %v", imageExists)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("unable to determine if image already exists for image %q", image)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !imageExists {
|
|
||||||
pull = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if pull {
|
|
||||||
*executors = append(*executors, container.NewDockerPullExecutor(container.NewDockerPullExecutorInput{
|
|
||||||
DockerExecutorInput: in,
|
|
||||||
Image: image,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
case *model.UsesPath:
|
|
||||||
contextDir := filepath.Join(runner.config.WorkingDir, uses.String())
|
|
||||||
sha, _, err := common.FindGitRevision(contextDir)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("Unable to determine git revision: %v", err)
|
|
||||||
sha = "latest"
|
|
||||||
}
|
|
||||||
image = fmt.Sprintf("%s:%s", filepath.Base(contextDir), sha)
|
|
||||||
|
|
||||||
*executors = append(*executors, container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{
|
|
||||||
DockerExecutorInput: in,
|
|
||||||
ContextDir: contextDir,
|
|
||||||
ImageTag: image,
|
|
||||||
}))
|
|
||||||
|
|
||||||
case *model.UsesRepository:
|
|
||||||
image = fmt.Sprintf("%s:%s", filepath.Base(uses.Repository), uses.Ref)
|
|
||||||
cloneURL := fmt.Sprintf("https://github.com/%s", uses.Repository)
|
|
||||||
|
|
||||||
cloneDir := filepath.Join(os.TempDir(), "act", action.Uses.String())
|
|
||||||
*executors = append(*executors, common.NewGitCloneExecutor(common.NewGitCloneExecutorInput{
|
|
||||||
URL: cloneURL,
|
|
||||||
Ref: uses.Ref,
|
|
||||||
Dir: cloneDir,
|
|
||||||
Logger: logger,
|
|
||||||
Dryrun: runner.config.Dryrun,
|
|
||||||
}))
|
|
||||||
|
|
||||||
contextDir := filepath.Join(cloneDir, uses.Path)
|
|
||||||
*executors = append(*executors, container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{
|
|
||||||
DockerExecutorInput: in,
|
|
||||||
ContextDir: contextDir,
|
|
||||||
ImageTag: image,
|
|
||||||
}))
|
|
||||||
|
|
||||||
default:
|
|
||||||
return "", fmt.Errorf("unable to determine executor type for image '%s'", action.Uses)
|
|
||||||
}
|
|
||||||
|
|
||||||
return image, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (runner *runnerImpl) addRunExecutor(action *Action, image string, executors *[]common.Executor) error {
|
|
||||||
logger := newActionLogger(action.Identifier, runner.config.Dryrun)
|
|
||||||
log.Debugf("Using '%s' for action '%s'", action.Uses, action.Identifier)
|
|
||||||
|
|
||||||
in := container.DockerExecutorInput{
|
|
||||||
Ctx: runner.config.Ctx,
|
|
||||||
Logger: logger,
|
|
||||||
Dryrun: runner.config.Dryrun,
|
|
||||||
}
|
|
||||||
|
|
||||||
env := make(map[string]string)
|
|
||||||
for _, applier := range []environmentApplier{newActionEnvironmentApplier(action), runner} {
|
|
||||||
applier.applyEnvironment(env)
|
|
||||||
}
|
|
||||||
env["GITHUB_ACTION"] = action.Identifier
|
|
||||||
|
|
||||||
ghReader, err := runner.createGithubTarball()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
envList := make([]string, 0)
|
|
||||||
for k, v := range env {
|
|
||||||
envList = append(envList, fmt.Sprintf("%s=%s", k, v))
|
|
||||||
}
|
|
||||||
|
|
||||||
var cmd, entrypoint []string
|
|
||||||
if action.Args != nil {
|
|
||||||
cmd = []string{
|
|
||||||
"/bin/sh",
|
|
||||||
"-c",
|
|
||||||
action.Args,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if action.Runs != nil {
|
|
||||||
entrypoint = action.Runs.Split()
|
|
||||||
}
|
|
||||||
*executors = append(*executors, container.NewDockerRunExecutor(container.NewDockerRunExecutorInput{
|
|
||||||
DockerExecutorInput: in,
|
|
||||||
Cmd: cmd,
|
|
||||||
Entrypoint: entrypoint,
|
|
||||||
Image: image,
|
|
||||||
WorkingDir: "/github/workspace",
|
|
||||||
Env: envList,
|
|
||||||
Name: runner.createContainerName(action.Identifier),
|
|
||||||
Binds: []string{
|
|
||||||
fmt.Sprintf("%s:%s", runner.config.WorkingDir, "/github/workspace"),
|
|
||||||
fmt.Sprintf("%s:%s", runner.tempDir, "/github/home"),
|
|
||||||
fmt.Sprintf("%s:%s", "/var/run/docker.sock", "/var/run/docker.sock"),
|
|
||||||
},
|
|
||||||
Content: map[string]io.Reader{"/github": ghReader},
|
|
||||||
ReuseContainers: runner.config.ReuseContainers,
|
|
||||||
}))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (runner *runnerImpl) applyEnvironment(env map[string]string) {
|
|
||||||
repoPath := runner.config.WorkingDir
|
|
||||||
|
|
||||||
workflows := runner.workflowConfig.GetWorkflows(runner.config.EventName)
|
|
||||||
if len(workflows) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
workflowName := workflows[0].Identifier
|
|
||||||
|
|
||||||
env["HOME"] = "/github/home"
|
|
||||||
env["GITHUB_ACTOR"] = "nektos/act"
|
|
||||||
env["GITHUB_EVENT_PATH"] = "/github/workflow/event.json"
|
|
||||||
env["GITHUB_WORKSPACE"] = "/github/workspace"
|
|
||||||
env["GITHUB_WORKFLOW"] = workflowName
|
|
||||||
env["GITHUB_EVENT_NAME"] = runner.config.EventName
|
|
||||||
|
|
||||||
_, rev, err := common.FindGitRevision(repoPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Warningf("unable to get git revision: %v", err)
|
|
||||||
} else {
|
|
||||||
env["GITHUB_SHA"] = rev
|
|
||||||
}
|
|
||||||
|
|
||||||
repo, err := common.FindGithubRepo(repoPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Warningf("unable to get git repo: %v", err)
|
|
||||||
} else {
|
|
||||||
env["GITHUB_REPOSITORY"] = repo
|
|
||||||
}
|
|
||||||
|
|
||||||
ref, err := common.FindGitRef(repoPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Warningf("unable to get git ref: %v", err)
|
|
||||||
} else {
|
|
||||||
log.Infof("using github ref: %s", ref)
|
|
||||||
env["GITHUB_REF"] = ref
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (runner *runnerImpl) createGithubTarball() (io.Reader, error) {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
tw := tar.NewWriter(&buf)
|
|
||||||
var files = []struct {
|
|
||||||
Name string
|
|
||||||
Mode int64
|
|
||||||
Body string
|
|
||||||
}{
|
|
||||||
{"workflow/event.json", 0644, runner.eventJSON},
|
|
||||||
}
|
|
||||||
for _, file := range files {
|
|
||||||
log.Debugf("Writing entry to tarball %s len:%d", file.Name, len(runner.eventJSON))
|
|
||||||
hdr := &tar.Header{
|
|
||||||
Name: file.Name,
|
|
||||||
Mode: file.Mode,
|
|
||||||
Size: int64(len(runner.eventJSON)),
|
|
||||||
}
|
|
||||||
if err := tw.WriteHeader(hdr); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if _, err := tw.Write([]byte(runner.eventJSON)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := tw.Close(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &buf, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (runner *runnerImpl) createContainerName(actionName string) string {
|
|
||||||
containerName := regexp.MustCompile("[^a-zA-Z0-9]").ReplaceAllString(actionName, "-")
|
|
||||||
|
|
||||||
prefix := fmt.Sprintf("%s-", trimToLen(filepath.Base(runner.config.WorkingDir), 10))
|
|
||||||
suffix := ""
|
|
||||||
containerName = trimToLen(containerName, 30-(len(prefix)+len(suffix)))
|
|
||||||
return fmt.Sprintf("%s%s%s", prefix, containerName, suffix)
|
|
||||||
}
|
|
||||||
|
|
||||||
func trimToLen(s string, l int) string {
|
|
||||||
if len(s) > l {
|
|
||||||
return s[:l]
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
FROM alpine:3.8
|
|
||||||
Vendored
-21
@@ -1,21 +0,0 @@
|
|||||||
workflow "build-and-deploy" {
|
|
||||||
on = "push"
|
|
||||||
resolves = ["deploy"]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "build" {
|
|
||||||
uses = "./action1"
|
|
||||||
args = "echo 'build'"
|
|
||||||
}
|
|
||||||
|
|
||||||
action "test" {
|
|
||||||
uses = "docker://ubuntu:18.04"
|
|
||||||
args = "env"
|
|
||||||
needs = ["build"]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "deploy" {
|
|
||||||
uses = "./action2"
|
|
||||||
runs = ["/bin/sh", "-c", "cat $GITHUB_EVENT_PATH"]
|
|
||||||
needs = ["test"]
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
FROM alpine:3.8
|
|
||||||
COPY foobar /foo/bar
|
|
||||||
Vendored
-8
@@ -1,8 +0,0 @@
|
|||||||
workflow "test" {
|
|
||||||
on = "push"
|
|
||||||
resolves = ["test-action"]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "test-action" {
|
|
||||||
uses = "./buildfail-action"
|
|
||||||
}
|
|
||||||
-9
@@ -1,9 +0,0 @@
|
|||||||
workflow "detect-event" {
|
|
||||||
on = "pull_request"
|
|
||||||
resolves = ["build"]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "build" {
|
|
||||||
uses = "./action1"
|
|
||||||
args = "echo 'build'"
|
|
||||||
}
|
|
||||||
Vendored
-17
@@ -1,17 +0,0 @@
|
|||||||
workflow "test" {
|
|
||||||
on = "push"
|
|
||||||
resolves = [
|
|
||||||
"test-action-repo",
|
|
||||||
"test-action-ref",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "test-action-repo" {
|
|
||||||
uses = "docker://alpine:3.9"
|
|
||||||
runs = ["sh", "-c", "echo $GITHUB_REPOSITORY | grep '^nektos/act$'"]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "test-action-ref" {
|
|
||||||
uses = "docker://alpine:3.9"
|
|
||||||
runs = ["sh", "-c", "echo $GITHUB_REF | grep '^refs/'"]
|
|
||||||
}
|
|
||||||
Vendored
-13
@@ -1,13 +0,0 @@
|
|||||||
workflow "test" {
|
|
||||||
on = "push"
|
|
||||||
resolves = ["test-action"]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "test-action" {
|
|
||||||
uses = "docker://alpine:3.9"
|
|
||||||
runs = ["sh", "-c", "echo $IN | grep $OUT"]
|
|
||||||
env = {
|
|
||||||
IN = "foo"
|
|
||||||
OUT = "bar"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
-14
@@ -1,14 +0,0 @@
|
|||||||
workflow "New workflow" {
|
|
||||||
on = "push"
|
|
||||||
resolves = ["branch-ref","commit-ref"]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "branch-ref" {
|
|
||||||
uses = "actions/docker/cli@master"
|
|
||||||
args = "version"
|
|
||||||
}
|
|
||||||
|
|
||||||
action "commit-ref" {
|
|
||||||
uses = "actions/docker/cli@c08a5fc9e0286844156fefff2c141072048141f6"
|
|
||||||
args = "version"
|
|
||||||
}
|
|
||||||
Vendored
-19
@@ -1,19 +0,0 @@
|
|||||||
workflow "buildwf" {
|
|
||||||
on = "push"
|
|
||||||
resolves = ["build"]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "build" {
|
|
||||||
uses = "./action1"
|
|
||||||
args = "echo 'build'"
|
|
||||||
}
|
|
||||||
|
|
||||||
workflow "deploywf" {
|
|
||||||
on = "release"
|
|
||||||
resolves = ["deploy"]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "deploy" {
|
|
||||||
uses = "./action2"
|
|
||||||
runs = ["/bin/sh", "-c", "cat $GITHUB_EVENT_PATH"]
|
|
||||||
}
|
|
||||||
Vendored
-13
@@ -1,13 +0,0 @@
|
|||||||
workflow "test" {
|
|
||||||
on = "push"
|
|
||||||
resolves = ["test-action"]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "test-action" {
|
|
||||||
uses = "docker://alpine:3.9"
|
|
||||||
runs = ["sh", "-c", "echo $IN | grep $OUT"]
|
|
||||||
env = {
|
|
||||||
IN = "foo"
|
|
||||||
OUT = "foo"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
-9
@@ -1,9 +0,0 @@
|
|||||||
workflow "New workflow" {
|
|
||||||
on = "push"
|
|
||||||
resolves = ["filter-version-before-deploy"]
|
|
||||||
}
|
|
||||||
|
|
||||||
action "filter-version-before-deploy" {
|
|
||||||
uses = "actions/bin/filter@master"
|
|
||||||
args = "tag z?[0-9]+\\.[0-9]+\\.[0-9]+"
|
|
||||||
}
|
|
||||||
@@ -21,7 +21,6 @@ github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BU
|
|||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/engine v0.0.0-20181106193140-f5749085e9cb h1:PyjxRdW1mqCmSoxy/6uP01P7CGbsD+woX+oOWbaUPwQ=
|
github.com/docker/engine v0.0.0-20181106193140-f5749085e9cb h1:PyjxRdW1mqCmSoxy/6uP01P7CGbsD+woX+oOWbaUPwQ=
|
||||||
github.com/docker/engine v0.0.0-20181106193140-f5749085e9cb/go.mod h1:3CPr2caMgTHxxIAZgEMd3uLYPDlRvPqCpyeRf6ncPcY=
|
github.com/docker/engine v0.0.0-20181106193140-f5749085e9cb/go.mod h1:3CPr2caMgTHxxIAZgEMd3uLYPDlRvPqCpyeRf6ncPcY=
|
||||||
github.com/docker/engine v1.13.1 h1:Cks33UT9YBW5Xyc3MtGDq2IPgqfJtJ+qkFaxc2b0Euc=
|
|
||||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk=
|
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk=
|
||||||
|
|||||||
+26
-15
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -182,20 +183,19 @@ func findGitDirectory(fromFile string) (string, error) {
|
|||||||
|
|
||||||
// NewGitCloneExecutorInput the input for the NewGitCloneExecutor
|
// NewGitCloneExecutorInput the input for the NewGitCloneExecutor
|
||||||
type NewGitCloneExecutorInput struct {
|
type NewGitCloneExecutorInput struct {
|
||||||
URL string
|
URL string
|
||||||
Ref string
|
Ref string
|
||||||
Dir string
|
Dir string
|
||||||
Logger *log.Entry
|
|
||||||
Dryrun bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGitCloneExecutor creates an executor to clone git repos
|
// NewGitCloneExecutor creates an executor to clone git repos
|
||||||
func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor {
|
func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
input.Logger.Infof("git clone '%s' # ref=%s", input.URL, input.Ref)
|
logger := Logger(ctx)
|
||||||
input.Logger.Debugf(" cloning %s to %s", input.URL, input.Dir)
|
logger.Infof("git clone '%s' # ref=%s", input.URL, input.Ref)
|
||||||
|
logger.Debugf(" cloning %s to %s", input.URL, input.Dir)
|
||||||
|
|
||||||
if input.Dryrun {
|
if Dryrun(ctx) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,15 +206,26 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor {
|
|||||||
|
|
||||||
r, err := git.PlainOpen(input.Dir)
|
r, err := git.PlainOpen(input.Dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
var progressWriter io.Writer
|
||||||
|
if entry, ok := logger.(*log.Entry); ok {
|
||||||
|
progressWriter = entry.WriterLevel(log.DebugLevel)
|
||||||
|
} else if lgr, ok := logger.(*log.Logger); ok {
|
||||||
|
progressWriter = lgr.WriterLevel(log.DebugLevel)
|
||||||
|
} else {
|
||||||
|
log.Errorf("Unable to get writer from logger (type=%T)", logger)
|
||||||
|
progressWriter = os.Stdout
|
||||||
|
}
|
||||||
|
|
||||||
r, err = git.PlainClone(input.Dir, false, &git.CloneOptions{
|
r, err = git.PlainClone(input.Dir, false, &git.CloneOptions{
|
||||||
URL: input.URL,
|
URL: input.URL,
|
||||||
Progress: input.Logger.WriterLevel(log.DebugLevel),
|
Progress: progressWriter,
|
||||||
//ReferenceName: refName,
|
//ReferenceName: refName,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
input.Logger.Errorf("Unable to clone %v %s: %v", input.URL, refName, err)
|
logger.Errorf("Unable to clone %v %s: %v", input.URL, refName, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
os.Chmod(input.Dir, 0755)
|
||||||
}
|
}
|
||||||
|
|
||||||
w, err := r.Worktree()
|
w, err := r.Worktree()
|
||||||
@@ -227,13 +238,13 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor {
|
|||||||
Force: true,
|
Force: true,
|
||||||
})
|
})
|
||||||
if err != nil && err.Error() != "already up-to-date" {
|
if err != nil && err.Error() != "already up-to-date" {
|
||||||
input.Logger.Errorf("Unable to pull %s: %v", refName, err)
|
logger.Errorf("Unable to pull %s: %v", refName, err)
|
||||||
}
|
}
|
||||||
input.Logger.Debugf("Cloned %s to %s", input.URL, input.Dir)
|
logger.Debugf("Cloned %s to %s", input.URL, input.Dir)
|
||||||
|
|
||||||
hash, err := r.ResolveRevision(plumbing.Revision(input.Ref))
|
hash, err := r.ResolveRevision(plumbing.Revision(input.Ref))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
input.Logger.Errorf("Unable to resolve %s: %v", input.Ref, err)
|
logger.Errorf("Unable to resolve %s: %v", input.Ref, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,11 +254,11 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor {
|
|||||||
Force: true,
|
Force: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
input.Logger.Errorf("Unable to checkout %s: %v", refName, err)
|
logger.Errorf("Unable to checkout %s: %v", refName, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
input.Logger.Debugf("Checked out %s", input.Ref)
|
logger.Debugf("Checked out %s", input.Ref)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,8 @@ func NewDockerBuildExecutor(input NewDockerBuildExecutorInput) common.Executor {
|
|||||||
|
|
||||||
tags := []string{input.ImageTag}
|
tags := []string{input.ImageTag}
|
||||||
options := types.ImageBuildOptions{
|
options := types.ImageBuildOptions{
|
||||||
Tags: tags,
|
Tags: tags,
|
||||||
|
Remove: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
buildContext, err := createBuildContext(input.ContextDir, "Dockerfile")
|
buildContext, err := createBuildContext(input.ContextDir, "Dockerfile")
|
||||||
|
|||||||
@@ -19,27 +19,28 @@ func TestImageExistsLocally(t *testing.T) {
|
|||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip("skipping integration test")
|
t.Skip("skipping integration test")
|
||||||
}
|
}
|
||||||
|
ctx := context.Background()
|
||||||
// to help make this test reliable and not flaky, we need to have
|
// to help make this test reliable and not flaky, we need to have
|
||||||
// an image that will exist, and onew that won't exist
|
// an image that will exist, and onew that won't exist
|
||||||
|
|
||||||
exists, err := ImageExistsLocally(context.TODO(), "library/alpine:this-random-tag-will-never-exist")
|
exists, err := ImageExistsLocally(ctx, "library/alpine:this-random-tag-will-never-exist")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, false, exists)
|
assert.Equal(t, false, exists)
|
||||||
|
|
||||||
// pull an image
|
// pull an image
|
||||||
cli, err := client.NewClientWithOpts(client.FromEnv)
|
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
cli.NegotiateAPIVersion(context.TODO())
|
cli.NegotiateAPIVersion(context.Background())
|
||||||
|
|
||||||
// Chose alpine latest because it's so small
|
// Chose alpine latest because it's so small
|
||||||
// maybe we should build an image instead so that tests aren't reliable on dockerhub
|
// maybe we should build an image instead so that tests aren't reliable on dockerhub
|
||||||
reader, err := cli.ImagePull(context.TODO(), "alpine:latest", types.ImagePullOptions{})
|
reader, err := cli.ImagePull(ctx, "alpine:latest", types.ImagePullOptions{})
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
_, err = ioutil.ReadAll(reader)
|
_, err = ioutil.ReadAll(reader)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
exists, err = ImageExistsLocally(context.TODO(), "alpine:latest")
|
exists, err = ImageExistsLocally(ctx, "alpine:latest")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, true, exists)
|
assert.Equal(t, true, exists)
|
||||||
}
|
}
|
||||||
@@ -39,6 +39,7 @@ type ContainerSpec struct {
|
|||||||
Options string `yaml:"options"`
|
Options string `yaml:"options"`
|
||||||
Entrypoint string
|
Entrypoint string
|
||||||
Args string
|
Args string
|
||||||
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step is the structure of one step in a job
|
// Step is the structure of one step in a job
|
||||||
@@ -63,8 +64,8 @@ func (s *Step) GetEnv() map[string]string {
|
|||||||
rtnEnv[k] = v
|
rtnEnv[k] = v
|
||||||
}
|
}
|
||||||
for k, v := range s.With {
|
for k, v := range s.With {
|
||||||
envKey := fmt.Sprintf("INPUT_%s", strings.ToUpper(k))
|
envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(k), "_")
|
||||||
envKey = regexp.MustCompile("[^A-Z0-9]").ReplaceAllString(envKey, "_")
|
envKey = fmt.Sprintf("INPUT_%s", strings.ToUpper(envKey))
|
||||||
rtnEnv[envKey] = v
|
rtnEnv[envKey] = v
|
||||||
}
|
}
|
||||||
return rtnEnv
|
return rtnEnv
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
package runner
|
|
||||||
|
|
||||||
type environmentApplier interface {
|
|
||||||
applyEnvironment(map[string]string)
|
|
||||||
}
|
|
||||||
+18
-15
@@ -45,10 +45,13 @@ func (rc *RunContext) Close(ctx context.Context) error {
|
|||||||
|
|
||||||
// Executor returns a pipeline executor for all the steps in the job
|
// Executor returns a pipeline executor for all the steps in the job
|
||||||
func (rc *RunContext) Executor() common.Executor {
|
func (rc *RunContext) Executor() common.Executor {
|
||||||
|
rc.setupTempDir()
|
||||||
steps := make([]common.Executor, 0)
|
steps := make([]common.Executor, 0)
|
||||||
steps = append(steps, rc.setupTempDir())
|
|
||||||
|
|
||||||
for _, step := range rc.Run.Job().Steps {
|
for i, step := range rc.Run.Job().Steps {
|
||||||
|
if step.ID == "" {
|
||||||
|
step.ID = fmt.Sprintf("%d", i)
|
||||||
|
}
|
||||||
steps = append(steps, rc.newStepExecutor(step))
|
steps = append(steps, rc.newStepExecutor(step))
|
||||||
}
|
}
|
||||||
return common.NewPipelineExecutor(steps...).Finally(rc.Close)
|
return common.NewPipelineExecutor(steps...).Finally(rc.Close)
|
||||||
@@ -64,17 +67,16 @@ func mergeMaps(maps ...map[string]string) map[string]string {
|
|||||||
return rtnMap
|
return rtnMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RunContext) setupTempDir() common.Executor {
|
func (rc *RunContext) setupTempDir() error {
|
||||||
return func(ctx context.Context) error {
|
var err error
|
||||||
var err error
|
tempBase := ""
|
||||||
tempBase := ""
|
if runtime.GOOS == "darwin" {
|
||||||
if runtime.GOOS == "darwin" {
|
tempBase = "/tmp"
|
||||||
tempBase = "/tmp"
|
|
||||||
}
|
|
||||||
rc.Tempdir, err = ioutil.TempDir(tempBase, "act-")
|
|
||||||
log.Debugf("Setup tempdir %s", rc.Tempdir)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
rc.Tempdir, err = ioutil.TempDir(tempBase, "act-")
|
||||||
|
os.Chmod(rc.Tempdir, 0755)
|
||||||
|
log.Debugf("Setup tempdir %s", rc.Tempdir)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RunContext) pullImage(containerSpec *model.ContainerSpec) common.Executor {
|
func (rc *RunContext) pullImage(containerSpec *model.ContainerSpec) common.Executor {
|
||||||
@@ -111,7 +113,7 @@ func (rc *RunContext) runContainer(containerSpec *model.ContainerSpec) common.Ex
|
|||||||
Image: containerSpec.Image,
|
Image: containerSpec.Image,
|
||||||
WorkingDir: "/github/workspace",
|
WorkingDir: "/github/workspace",
|
||||||
Env: envList,
|
Env: envList,
|
||||||
Name: rc.createContainerName(),
|
Name: containerSpec.Name,
|
||||||
Binds: []string{
|
Binds: []string{
|
||||||
fmt.Sprintf("%s:%s", rc.Config.Workdir, "/github/workspace"),
|
fmt.Sprintf("%s:%s", rc.Config.Workdir, "/github/workspace"),
|
||||||
fmt.Sprintf("%s:%s", rc.Tempdir, "/github/home"),
|
fmt.Sprintf("%s:%s", rc.Tempdir, "/github/home"),
|
||||||
@@ -155,8 +157,9 @@ func (rc *RunContext) createGithubTarball() (io.Reader, error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RunContext) createContainerName() string {
|
func (rc *RunContext) createContainerName(stepID string) string {
|
||||||
containerName := regexp.MustCompile("[^a-zA-Z0-9]").ReplaceAllString(rc.Run.String(), "-")
|
containerName := fmt.Sprintf("%s-%s", stepID, rc.Tempdir)
|
||||||
|
containerName = regexp.MustCompile("[^a-zA-Z0-9]").ReplaceAllString(containerName, "-")
|
||||||
|
|
||||||
prefix := fmt.Sprintf("%s-", trimToLen(filepath.Base(rc.Config.Workdir), 10))
|
prefix := fmt.Sprintf("%s-", trimToLen(filepath.Base(rc.Config.Workdir), 10))
|
||||||
suffix := ""
|
suffix := ""
|
||||||
|
|||||||
+33
-26
@@ -2,28 +2,29 @@ package runner
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nektos/act/pkg/model"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGraphEvent(t *testing.T) {
|
func TestGraphEvent(t *testing.T) {
|
||||||
runnerConfig := &Config{
|
planner, err := model.NewWorkflowPlanner("testdata/basic")
|
||||||
WorkflowPath: "multi.workflow",
|
|
||||||
WorkingDir: "testdata",
|
|
||||||
EventName: "push",
|
|
||||||
}
|
|
||||||
runner, err := NewRunner(runnerConfig)
|
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
graph, err := runner.GraphEvent("push")
|
plan := planner.PlanEvent("push")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.DeepEqual(t, graph, [][]string{{"build"}})
|
assert.Equal(t, len(plan.Stages), 2, "stages")
|
||||||
|
assert.Equal(t, len(plan.Stages[0].Runs), 1, "stage0.runs")
|
||||||
|
assert.Equal(t, len(plan.Stages[1].Runs), 1, "stage1.runs")
|
||||||
|
assert.Equal(t, plan.Stages[0].Runs[0].JobID, "build", "jobid")
|
||||||
|
assert.Equal(t, plan.Stages[1].Runs[0].JobID, "test", "jobid")
|
||||||
|
|
||||||
graph, err = runner.GraphEvent("release")
|
plan = planner.PlanEvent("release")
|
||||||
assert.NilError(t, err)
|
assert.Equal(t, len(plan.Stages), 0, "stages")
|
||||||
assert.DeepEqual(t, graph, [][]string{{"deploy"}})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunEvent(t *testing.T) {
|
func TestRunEvent(t *testing.T) {
|
||||||
@@ -36,30 +37,36 @@ func TestRunEvent(t *testing.T) {
|
|||||||
eventName string
|
eventName string
|
||||||
errorMessage string
|
errorMessage string
|
||||||
}{
|
}{
|
||||||
{"basic.workflow", "push", ""},
|
{"basic", "push", ""},
|
||||||
{"pipe.workflow", "push", ""},
|
{"fail", "push", "exit with `FAILURE`: 1"},
|
||||||
{"fail.workflow", "push", "exit with `FAILURE`: 1"},
|
{"runs-on", "push", ""},
|
||||||
{"buildfail.workflow", "push", "COPY failed"},
|
{"job-container", "push", ""},
|
||||||
{"regex.workflow", "push", "exit with `NEUTRAL`: 78"},
|
{"uses-docker-url", "push", ""},
|
||||||
{"gitref.workflow", "push", ""},
|
{"remote-action-docker", "push", ""},
|
||||||
{"env.workflow", "push", ""},
|
{"remote-action-js", "push", ""},
|
||||||
{"detect_event.workflow", "", ""},
|
{"local-action-docker-url", "push", ""},
|
||||||
|
{"local-action-dockerfile", "push", ""},
|
||||||
}
|
}
|
||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
for _, table := range tables {
|
for _, table := range tables {
|
||||||
table := table
|
table := table
|
||||||
t.Run(table.workflowPath, func(t *testing.T) {
|
t.Run(table.workflowPath, func(t *testing.T) {
|
||||||
runnerConfig := &RunnerConfig{
|
runnerConfig := &Config{
|
||||||
Ctx: context.Background(),
|
Workdir: "testdata",
|
||||||
WorkflowPath: table.workflowPath,
|
EventName: table.eventName,
|
||||||
WorkingDir: "testdata",
|
|
||||||
EventName: table.eventName,
|
|
||||||
}
|
}
|
||||||
runner, err := NewRunner(runnerConfig)
|
runner, err := New(runnerConfig)
|
||||||
assert.NilError(t, err, table.workflowPath)
|
assert.NilError(t, err, table.workflowPath)
|
||||||
|
|
||||||
err = runner.RunEvent()
|
planner, err := model.NewWorkflowPlanner(fmt.Sprintf("testdata/%s", table.workflowPath))
|
||||||
|
assert.NilError(t, err, table.workflowPath)
|
||||||
|
|
||||||
|
plan := planner.PlanEvent(table.eventName)
|
||||||
|
|
||||||
|
err = runner.NewPlanExecutor(plan)(ctx)
|
||||||
if table.errorMessage == "" {
|
if table.errorMessage == "" {
|
||||||
assert.NilError(t, err, table.workflowPath)
|
assert.NilError(t, err, table.workflowPath)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+54
-10
@@ -10,6 +10,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
"github.com/nektos/act/pkg/common"
|
||||||
|
"github.com/nektos/act/pkg/container"
|
||||||
"github.com/nektos/act/pkg/model"
|
"github.com/nektos/act/pkg/model"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@@ -18,6 +19,7 @@ func (rc *RunContext) newStepExecutor(step *model.Step) common.Executor {
|
|||||||
job := rc.Run.Job()
|
job := rc.Run.Job()
|
||||||
containerSpec := new(model.ContainerSpec)
|
containerSpec := new(model.ContainerSpec)
|
||||||
containerSpec.Env = rc.StepEnv(step)
|
containerSpec.Env = rc.StepEnv(step)
|
||||||
|
containerSpec.Name = rc.createContainerName(step.ID)
|
||||||
|
|
||||||
switch step.Type() {
|
switch step.Type() {
|
||||||
case model.StepTypeRun:
|
case model.StepTypeRun:
|
||||||
@@ -45,15 +47,26 @@ func (rc *RunContext) newStepExecutor(step *model.Step) common.Executor {
|
|||||||
)
|
)
|
||||||
|
|
||||||
case model.StepTypeUsesActionLocal:
|
case model.StepTypeUsesActionLocal:
|
||||||
|
containerSpec.Image = fmt.Sprintf("%s:%s", containerSpec.Name, "latest")
|
||||||
return common.NewPipelineExecutor(
|
return common.NewPipelineExecutor(
|
||||||
rc.setupAction(containerSpec, filepath.Join(rc.Config.Workdir, step.Uses)),
|
rc.setupAction(containerSpec, filepath.Join(rc.Config.Workdir, step.Uses)),
|
||||||
rc.pullImage(containerSpec),
|
rc.pullImage(containerSpec),
|
||||||
rc.runContainer(containerSpec),
|
rc.runContainer(containerSpec),
|
||||||
)
|
)
|
||||||
case model.StepTypeUsesActionRemote:
|
case model.StepTypeUsesActionRemote:
|
||||||
|
remoteAction := newRemoteAction(step.Uses)
|
||||||
|
cloneDir, err := ioutil.TempDir(rc.Tempdir, remoteAction.Repo)
|
||||||
|
if err != nil {
|
||||||
|
return common.NewErrorExecutor(err)
|
||||||
|
}
|
||||||
|
containerSpec.Image = fmt.Sprintf("%s:%s", remoteAction.Repo, remoteAction.Ref)
|
||||||
return common.NewPipelineExecutor(
|
return common.NewPipelineExecutor(
|
||||||
rc.cloneAction(step.Uses),
|
common.NewGitCloneExecutor(common.NewGitCloneExecutorInput{
|
||||||
rc.setupAction(containerSpec, step.Uses),
|
URL: remoteAction.CloneURL(),
|
||||||
|
Ref: remoteAction.Ref,
|
||||||
|
Dir: cloneDir,
|
||||||
|
}),
|
||||||
|
rc.setupAction(containerSpec, filepath.Join(cloneDir, remoteAction.Path)),
|
||||||
rc.pullImage(containerSpec),
|
rc.pullImage(containerSpec),
|
||||||
rc.runContainer(containerSpec),
|
rc.runContainer(containerSpec),
|
||||||
)
|
)
|
||||||
@@ -174,8 +187,8 @@ func (rc *RunContext) setupAction(containerSpec *model.ContainerSpec, actionDir
|
|||||||
}
|
}
|
||||||
|
|
||||||
for inputID, input := range action.Inputs {
|
for inputID, input := range action.Inputs {
|
||||||
envKey := fmt.Sprintf("INPUT_%s", strings.ToUpper(inputID))
|
envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(inputID), "_")
|
||||||
envKey = regexp.MustCompile("[^A-Z0-9]").ReplaceAllString(envKey, "_")
|
envKey = fmt.Sprintf("INPUT_%s", envKey)
|
||||||
if _, ok := containerSpec.Env[envKey]; !ok {
|
if _, ok := containerSpec.Env[envKey]; !ok {
|
||||||
containerSpec.Env[envKey] = input.Default
|
containerSpec.Env[envKey] = input.Default
|
||||||
}
|
}
|
||||||
@@ -183,23 +196,54 @@ func (rc *RunContext) setupAction(containerSpec *model.ContainerSpec, actionDir
|
|||||||
|
|
||||||
switch action.Runs.Using {
|
switch action.Runs.Using {
|
||||||
case model.ActionRunsUsingNode12:
|
case model.ActionRunsUsingNode12:
|
||||||
containerSpec.Image = "node:12"
|
containerSpec.Image = "node:12-alpine"
|
||||||
containerSpec.Args = action.Runs.Main
|
if strings.HasPrefix(actionDir, rc.Config.Workdir) {
|
||||||
|
containerSpec.Args = fmt.Sprintf("node /github/workspace/%s/%s", strings.TrimPrefix(actionDir, rc.Config.Workdir), action.Runs.Main)
|
||||||
|
} else if strings.HasPrefix(actionDir, rc.Tempdir) {
|
||||||
|
containerSpec.Args = fmt.Sprintf("node /github/home/%s/%s", strings.TrimPrefix(actionDir, rc.Tempdir), action.Runs.Main)
|
||||||
|
}
|
||||||
case model.ActionRunsUsingDocker:
|
case model.ActionRunsUsingDocker:
|
||||||
if strings.HasPrefix(action.Runs.Image, "docker://") {
|
if strings.HasPrefix(action.Runs.Image, "docker://") {
|
||||||
containerSpec.Image = strings.TrimPrefix(action.Runs.Image, "docker://")
|
containerSpec.Image = strings.TrimPrefix(action.Runs.Image, "docker://")
|
||||||
containerSpec.Entrypoint = strings.Join(action.Runs.Entrypoint, " ")
|
containerSpec.Entrypoint = strings.Join(action.Runs.Entrypoint, " ")
|
||||||
containerSpec.Args = strings.Join(action.Runs.Args, " ")
|
containerSpec.Args = strings.Join(action.Runs.Args, " ")
|
||||||
} else {
|
} else {
|
||||||
// TODO: docker build
|
contextDir := filepath.Join(actionDir, action.Runs.Main)
|
||||||
|
return container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{
|
||||||
|
ContextDir: contextDir,
|
||||||
|
ImageTag: containerSpec.Image,
|
||||||
|
})(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RunContext) cloneAction(action string) common.Executor {
|
type remoteAction struct {
|
||||||
return func(ctx context.Context) error {
|
Org string
|
||||||
return nil
|
Repo string
|
||||||
|
Path string
|
||||||
|
Ref string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ra *remoteAction) CloneURL() string {
|
||||||
|
return fmt.Sprintf("https://github.com/%s/%s", ra.Org, ra.Repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRemoteAction(action string) *remoteAction {
|
||||||
|
r := regexp.MustCompile(`^([^/@]+)/([^/@]+)(/([^@]*))?(@(.*))?$`)
|
||||||
|
matches := r.FindStringSubmatch(action)
|
||||||
|
|
||||||
|
ra := new(remoteAction)
|
||||||
|
ra.Org = matches[1]
|
||||||
|
ra.Repo = matches[2]
|
||||||
|
ra.Path = ""
|
||||||
|
ra.Ref = "master"
|
||||||
|
if len(matches) >= 5 {
|
||||||
|
ra.Path = matches[4]
|
||||||
}
|
}
|
||||||
|
if len(matches) >= 7 {
|
||||||
|
ra.Ref = matches[6]
|
||||||
|
}
|
||||||
|
return ra
|
||||||
}
|
}
|
||||||
File renamed without changes.
@@ -0,0 +1,4 @@
|
|||||||
|
name: 'action1'
|
||||||
|
runs:
|
||||||
|
using: 'docker'
|
||||||
|
image: 'Dockerfile'
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# Container image that runs your code
|
||||||
|
FROM alpine:3.10
|
||||||
|
|
||||||
|
# Copies your code file from your action repository to the filesystem path `/` of the container
|
||||||
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
|
||||||
|
# Code file to execute when the docker container starts up (`entrypoint.sh`)
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
name: 'Hello World'
|
||||||
|
description: 'Greet someone and record the time'
|
||||||
|
inputs:
|
||||||
|
who-to-greet: # id of input
|
||||||
|
description: 'Who to greet'
|
||||||
|
required: true
|
||||||
|
default: 'World'
|
||||||
|
outputs:
|
||||||
|
time: # id of output
|
||||||
|
description: 'The time we greeted you'
|
||||||
|
runs:
|
||||||
|
using: 'docker'
|
||||||
|
image: 'Dockerfile'
|
||||||
|
args:
|
||||||
|
- ${{ inputs.who-to-greet }}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh -l
|
||||||
|
|
||||||
|
echo "Hello $1"
|
||||||
|
time=$(date)
|
||||||
|
echo ::set-output name=time::$time
|
||||||
Vendored
+3
-3
@@ -8,9 +8,9 @@ inputs:
|
|||||||
default: World
|
default: World
|
||||||
runs:
|
runs:
|
||||||
using: docker
|
using: docker
|
||||||
image: docker://alpine:3.8
|
#image: docker://alpine:3.8
|
||||||
|
image: docker://node:12-alpine
|
||||||
env:
|
env:
|
||||||
TEST: enabled
|
TEST: enabled
|
||||||
args:
|
args:
|
||||||
- echo
|
- env
|
||||||
- ${INPUT_WHO_TO_GREET}
|
|
||||||
Vendored
+17
@@ -0,0 +1,17 @@
|
|||||||
|
name: basic
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: ./actions/action1
|
||||||
|
with:
|
||||||
|
args: echo 'build'
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [build]
|
||||||
|
steps:
|
||||||
|
- uses: docker://ubuntu:18.04
|
||||||
|
with:
|
||||||
|
args: echo ${GITHUB_REF} | grep nektos/act
|
||||||
Vendored
+12
@@ -0,0 +1,12 @@
|
|||||||
|
name: fail
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: node:10.16-jessie
|
||||||
|
env:
|
||||||
|
TEST_ENV: test-value
|
||||||
|
steps:
|
||||||
|
- run: echo ${TEST_ENV} | grep bazooka
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
name: job-container
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: node:10.16-jessie
|
||||||
|
env:
|
||||||
|
TEST_ENV: test-value
|
||||||
|
steps:
|
||||||
|
- run: echo ${TEST_ENV} | grep test-value
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
name: local-action-docker-url
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: ./actions/docker-url
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
name: local-action-dockerfile
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: ./actions/docker-local
|
||||||
|
with:
|
||||||
|
who-to-greet: 'Mona the Octocat'
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
name: remote-action-docker
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/hello-world-docker-action@master
|
||||||
|
with:
|
||||||
|
who-to-greet: 'Mona the Octocat'
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
name: remote-action-js
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/hello-world-javascript-action@master
|
||||||
|
with:
|
||||||
|
who-to-greet: 'Mona the Octocat'
|
||||||
Vendored
+8
@@ -0,0 +1,8 @@
|
|||||||
|
name: runs-on
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- run: echo ${GITHUB_ACTOR} | grep nektos/act
|
||||||
Loaded 50 of 466 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user