diff --git a/.editorconfig b/.editorconfig index deec24a..2849b4e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,8 +2,8 @@ root = true [*] indent_style = space -indent_size = 2 -tab_width = 2 +indent_size = 4 +tab_width = 4 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true diff --git a/internal/app/poll/poller.go b/internal/app/poll/poller.go index e4e1d97..186b769 100644 --- a/internal/app/poll/poller.go +++ b/internal/app/poll/poller.go @@ -7,6 +7,7 @@ import ( "context" "errors" "fmt" + "strings" "sync" "sync/atomic" @@ -147,6 +148,11 @@ func (p *Poller) runTaskWithRecover(ctx context.Context, task *runnerv1.Task) { log.WithError(err).Error("panic in runTaskWithRecover") } }() + // verify owner and repo + if matchAllowedRepo(task.Context.Fields["repository"].GetStringValue(), p.cfg.Runner.AllowedRepos) { + log.WithError(errors.New("allowed repos not match")).Error("allowed repos not match") + return + } if err := p.runner.Run(ctx, task); err != nil { log.WithError(err).Error("failed to run task") @@ -187,3 +193,31 @@ func (p *Poller) fetchTask(ctx context.Context) (*runnerv1.Task, bool) { return resp.Msg.Task, true } + +func matchAllowedRepo(targetRepo string, allowedRepos []string) bool { + if len(allowedRepos) == 0 { + return true + } + + parts := strings.Split(targetRepo, "/") + if len(parts) != 2 { + log.Errorf("Invalid repository format: %s", targetRepo) + return false + } + + targetOwner, targetRepoName := parts[0], parts[1] + + for _, allowedRepo := range allowedRepos { + parts := strings.Split(allowedRepo, "/") + if len(parts) != 2 { + log.Warnf("Invalid allowed repository format: %s", allowedRepo) + continue + } + allowedOwner, allowedRepoName := parts[0], parts[1] + if (allowedOwner == "*" || allowedOwner == targetOwner) && + (allowedRepoName == "*" || allowedRepoName == targetRepoName) { + return true + } + } + return false +} diff --git a/internal/pkg/config/config.example.yaml b/internal/pkg/config/config.example.yaml index 2e3c3fb..e4ed364 100644 --- a/internal/pkg/config/config.example.yaml +++ b/internal/pkg/config/config.example.yaml @@ -42,6 +42,13 @@ runner: - "ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04" - "ubuntu-20.04:docker://docker.gitea.com/runner-images:ubuntu-20.04" + # for global runner + allowed_repos: + - "org1/repo1" + - "org1/repo2" + - "org2/*" + - "user1/*" + cache: # Enable cache server to use actions/cache. enabled: true @@ -70,7 +77,7 @@ container: # And other options to be used when the container is started (eg, --add-host=my.gitea.url:host-gateway). options: # The parent directory of a job's working directory. - # NOTE: There is no need to add the first '/' of the path as act_runner will add it automatically. + # NOTE: There is no need to add the first '/' of the path as act_runner will add it automatically. # If the path starts with '/', the '/' will be trimmed. # For example, if the parent directory is /path/to/my/dir, workdir_parent should be path/to/my/dir # If it's empty, /workspace will be used. diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index afc34b9..88e772c 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -31,6 +31,7 @@ type Runner struct { FetchTimeout time.Duration `yaml:"fetch_timeout"` // FetchTimeout specifies the timeout duration for fetching resources. FetchInterval time.Duration `yaml:"fetch_interval"` // FetchInterval specifies the interval duration for fetching resources. Labels []string `yaml:"labels"` // Labels specify the labels of the runner. Labels are declared on each startup + AllowedRepos []string `yaml:"allowed_repos"` // AllowedRepos specify the repositories that the runner is allowed to run jobs for. } // Cache represents the configuration for caching.