From 3e78964cffe6daa68629cdee3619717877bec5f5 Mon Sep 17 00:00:00 2001 From: Nathan Pierce Date: Wed, 30 Oct 2024 07:09:08 -0500 Subject: [PATCH] 0.9.0 --- .github/workflows/t1-failure-no-tag.yml | 2 - .github/workflows/t1-failure-no-template.yml | 2 - .github/workflows/t1-failure-tag-1-in-vm.yml | 2 - .../t1-with-tag-1-matrix-nodes-2.yml | 22 +++++++++++ .github/workflows/t1-with-tag-1.yml | 7 ++-- .github/workflows/t1-with-tag-2.yml | 2 - .github/workflows/t1-without-tag.yml | 2 - .github/workflows/t2-dual-without-tag.yml | 4 -- VERSION | 2 +- internal/config/config.go | 7 ++-- internal/database/database.go | 6 +-- internal/logging/logging.go | 8 +++- main.go | 27 ++++++------- plugins/handlers/github/README.md | 8 ++-- plugins/handlers/github/github.go | 7 +++- plugins/receivers/github/github.go | 39 ++++++++++++++----- trigger-test-runs.bash | 2 +- 17 files changed, 92 insertions(+), 57 deletions(-) create mode 100644 .github/workflows/t1-with-tag-1-matrix-nodes-2.yml diff --git a/.github/workflows/t1-failure-no-tag.yml b/.github/workflows/t1-failure-no-tag.yml index 9469480..6fa2f50 100644 --- a/.github/workflows/t1-failure-no-tag.yml +++ b/.github/workflows/t1-failure-no-tag.yml @@ -5,8 +5,6 @@ on: jobs: testJob: runs-on: [ - "self-hosted", - "anka", "anka-template:d792c6f6-198c-470f-9526-9c998efe7ab4", "anka-template-tag:not-a-tag", ] diff --git a/.github/workflows/t1-failure-no-template.yml b/.github/workflows/t1-failure-no-template.yml index 2be5bc8..4cd6f3b 100644 --- a/.github/workflows/t1-failure-no-template.yml +++ b/.github/workflows/t1-failure-no-template.yml @@ -5,8 +5,6 @@ on: jobs: testJob: runs-on: [ - "self-hosted", - "anka", "anka-template:c092c6f6-198c-470f-9526-9c998efe7ab5", "anka-template-tag:vanilla+port-forward-22+brew-git", ] diff --git a/.github/workflows/t1-failure-tag-1-in-vm.yml b/.github/workflows/t1-failure-tag-1-in-vm.yml index b3c5c5e..fb17c4d 100644 --- a/.github/workflows/t1-failure-tag-1-in-vm.yml +++ b/.github/workflows/t1-failure-tag-1-in-vm.yml @@ -5,8 +5,6 @@ on: jobs: testJob: runs-on: [ - "self-hosted", - "anka", "anka-template:d792c6f6-198c-470f-9526-9c998efe7ab4", "anka-template-tag:vanilla+port-forward-22+brew-git", ] diff --git a/.github/workflows/t1-with-tag-1-matrix-nodes-2.yml b/.github/workflows/t1-with-tag-1-matrix-nodes-2.yml new file mode 100644 index 0000000..168b995 --- /dev/null +++ b/.github/workflows/t1-with-tag-1-matrix-nodes-2.yml @@ -0,0 +1,22 @@ +name: 't1-with-tag-1-matrix-nodes-2' +on: + workflow_dispatch: + +jobs: + t1-with-tag-1-matrix-nodes-2: + strategy: + matrix: + node: ["1", "2"] + runs-on: [ + "anka-template:d792c6f6-198c-470f-9526-9c998efe7ab4", + "anka-template-tag:vanilla+port-forward-22+brew-git", + "unique-id:${{ github.run_id }}-${{ matrix.node }}", + ] + steps: + - uses: actions/checkout@v3 + - run: | + ls -laht + sw_vers + hostname + echo "123" + env diff --git a/.github/workflows/t1-with-tag-1.yml b/.github/workflows/t1-with-tag-1.yml index de2cb10..b4520f5 100644 --- a/.github/workflows/t1-with-tag-1.yml +++ b/.github/workflows/t1-with-tag-1.yml @@ -3,10 +3,8 @@ on: workflow_dispatch: jobs: - testJob: + t1-with-tag-1: runs-on: [ - "self-hosted", - "anka", "anka-template:d792c6f6-198c-470f-9526-9c998efe7ab4", "anka-template-tag:vanilla+port-forward-22+brew-git", ] @@ -16,4 +14,5 @@ jobs: ls -laht sw_vers hostname - echo "123" \ No newline at end of file + echo "123" + - run: whoami diff --git a/.github/workflows/t1-with-tag-2.yml b/.github/workflows/t1-with-tag-2.yml index 621912b..cc8beb9 100644 --- a/.github/workflows/t1-with-tag-2.yml +++ b/.github/workflows/t1-with-tag-2.yml @@ -5,8 +5,6 @@ on: jobs: testJob: runs-on: [ - "self-hosted", - "anka", "anka-template:d792c6f6-198c-470f-9526-9c998efe7ab4", "anka-template-tag:vanilla+port-forward-22", ] diff --git a/.github/workflows/t1-without-tag.yml b/.github/workflows/t1-without-tag.yml index fca87d5..2fa1c58 100644 --- a/.github/workflows/t1-without-tag.yml +++ b/.github/workflows/t1-without-tag.yml @@ -5,8 +5,6 @@ on: jobs: testJob: runs-on: [ - "self-hosted", - "anka", "anka-template:d792c6f6-198c-470f-9526-9c998efe7ab4", ] steps: diff --git a/.github/workflows/t2-dual-without-tag.yml b/.github/workflows/t2-dual-without-tag.yml index f362b92..e3d0ea6 100644 --- a/.github/workflows/t2-dual-without-tag.yml +++ b/.github/workflows/t2-dual-without-tag.yml @@ -5,8 +5,6 @@ on: jobs: testJob: runs-on: [ - "self-hosted", - "anka", "anka-template:d792c6f6-198c-470f-9526-9c998efe7ab4", ] steps: @@ -18,8 +16,6 @@ jobs: echo "123" testJob2: runs-on: [ - "self-hosted", - "anka", "anka-template:6abae54f-025d-4a27-b5eb-b985d5eddac9", ] steps: diff --git a/VERSION b/VERSION index 53a48a1..899f24f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.8.2 \ No newline at end of file +0.9.0 \ No newline at end of file diff --git a/internal/config/config.go b/internal/config/config.go index 346b60e..6828060 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -200,9 +200,10 @@ func GetPluginFromContext(ctx context.Context) Plugin { } type Globals struct { - RunOnce string - PullLock *sync.Mutex - PluginsPath string + RunOnce string + PullLock *sync.Mutex + PluginsPath string + DebugEnabled bool } func GetGlobalsFromContext(ctx context.Context) Globals { diff --git a/internal/database/database.go b/internal/database/database.go index 0609f79..e751f5e 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -26,9 +26,9 @@ func NewClient(ctx context.Context, config config.Database) (*Database, error) { Password: config.Password, // no password set DB: config.Database, // use default DB, }) - logging.DevDebug(ctx, fmt.Sprintf("created redis client: %v", rdb)) + logging.DevContext(ctx, fmt.Sprintf("created redis client: %v", rdb)) - logging.DevDebug(ctx, "pinging redis client") + logging.DevContext(ctx, "pinging redis client") ping := rdb.Ping(ctx) if ping.Err() != nil && ping.Err().Error() != "" { return nil, errors.New("error pinging redis client: " + ping.Err().Error()) @@ -38,7 +38,7 @@ func NewClient(ctx context.Context, config config.Database) (*Database, error) { return nil, err } - logging.DevDebug(ctx, fmt.Sprintf("pinged redis client: %s", pong)) + logging.DevContext(ctx, fmt.Sprintf("pinged redis client: %s", pong)) if pong != "PONG" { return nil, fmt.Errorf("unable to connect to Redis, received: %s", pong) diff --git a/internal/logging/logging.go b/internal/logging/logging.go index 4a8fd23..e6489d8 100644 --- a/internal/logging/logging.go +++ b/internal/logging/logging.go @@ -20,10 +20,14 @@ type ContextHandler struct { attrs []slog.Attr } +func IsDebugEnabled() bool { + return strings.ToUpper(os.Getenv("LOG_LEVEL")) == "DEBUG" || strings.ToUpper(os.Getenv("LOG_LEVEL")) == "DEV" +} + func New() *slog.Logger { logLevel := os.Getenv("LOG_LEVEL") var options *slog.HandlerOptions - if strings.ToUpper(logLevel) == "DEBUG" || strings.ToUpper(logLevel) == "DEV" { + if IsDebugEnabled() { handler := &ContextHandler{Handler: NewPrettyHandler(&slog.HandlerOptions{ Level: slog.LevelDebug, AddSource: true, @@ -101,7 +105,7 @@ func Panic(workerCtx context.Context, pluginCtx context.Context, errorMessage st panic(errorMessage) } -func DevDebug(pluginCtx context.Context, errorMessage string) { +func DevContext(pluginCtx context.Context, errorMessage string) { if strings.ToUpper(os.Getenv("LOG_LEVEL")) == "DEV" { logger := GetLoggerFromContext(pluginCtx) logger.DebugContext(pluginCtx, errorMessage) diff --git a/main.go b/main.go index be8af1f..8dbc07c 100644 --- a/main.go +++ b/main.go @@ -167,9 +167,10 @@ func main() { logger.InfoContext(parentCtx, "plugins path", slog.String("pluginsPath", pluginsPath)) parentCtx = context.WithValue(parentCtx, config.ContextKey("globals"), config.Globals{ - RunOnce: runOnce, - PullLock: &sync.Mutex{}, - PluginsPath: pluginsPath, + RunOnce: runOnce, + PullLock: &sync.Mutex{}, + PluginsPath: pluginsPath, + DebugEnabled: logging.IsDebugEnabled(), }) httpTransport := http.DefaultTransport @@ -364,14 +365,14 @@ func worker(parentCtx context.Context, logger *slog.Logger, loadedConfig config. if plugin.Repo == "" { logger.InfoContext(pluginCtx, "no repo set for plugin; assuming it's an organization level plugin") pluginCtx = context.WithValue(pluginCtx, config.ContextKey("isRepoSet"), false) - logging.DevDebug(pluginCtx, "set isRepoSet to false") + logging.DevContext(pluginCtx, "set isRepoSet to false") } else { pluginCtx = context.WithValue(pluginCtx, config.ContextKey("isRepoSet"), true) - logging.DevDebug(pluginCtx, "set isRepoSet to true") + logging.DevContext(pluginCtx, "set isRepoSet to true") } if plugin.PrivateKey == "" && loadedConfig.GlobalPrivateKey != "" { - logging.DevDebug(pluginCtx, "using global private key") + logging.DevContext(pluginCtx, "using global private key") plugin.PrivateKey = loadedConfig.GlobalPrivateKey } @@ -379,7 +380,7 @@ func worker(parentCtx context.Context, logger *slog.Logger, loadedConfig config. pluginCtx = logging.AppendCtx(pluginCtx, slog.String("pluginName", plugin.Name)) if !strings.Contains(plugin.Plugin, "_receiver") { - logging.DevDebug(pluginCtx, "plugin is not a receiver; loading the anka CLI") + logging.DevContext(pluginCtx, "plugin is not a receiver; loading the anka CLI") ankaCLI, err := anka.NewCLI(pluginCtx) if err != nil { pluginCancel() @@ -387,7 +388,7 @@ func worker(parentCtx context.Context, logger *slog.Logger, loadedConfig config. return } pluginCtx = context.WithValue(pluginCtx, config.ContextKey("ankacli"), ankaCLI) - logging.DevDebug(pluginCtx, "loaded the anka CLI") + logging.DevContext(pluginCtx, "loaded the anka CLI") } if databaseURL != "" || plugin.Database.URL != "" { @@ -398,7 +399,7 @@ func worker(parentCtx context.Context, logger *slog.Logger, loadedConfig config. databasePassword = plugin.Database.Password databaseDatabase = plugin.Database.Database } - logging.DevDebug(pluginCtx, "connecting to database") + logging.DevContext(pluginCtx, "connecting to database") databaseClient, err := database.NewClient(pluginCtx, config.Database{ URL: databaseURL, Port: databasePort, @@ -411,7 +412,7 @@ func worker(parentCtx context.Context, logger *slog.Logger, loadedConfig config. } logger.InfoContext(pluginCtx, "connected to database", slog.Any("database", databaseClient)) pluginCtx = context.WithValue(pluginCtx, config.ContextKey("database"), databaseClient) - logging.DevDebug(pluginCtx, "connected to database") + logging.DevContext(pluginCtx, "connected to database") } logger.InfoContext(pluginCtx, "starting plugin") @@ -419,13 +420,13 @@ func worker(parentCtx context.Context, logger *slog.Logger, loadedConfig config. for { select { case <-pluginCtx.Done(): - logging.DevDebug(pluginCtx, "plugin for loop::pluginCtx.Done()") + logging.DevContext(pluginCtx, "plugin for loop::pluginCtx.Done()") metricsData.SetStatus(pluginCtx, logger, "stopped") logger.WarnContext(pluginCtx, shutDownMessage) pluginCancel() return default: - logging.DevDebug(pluginCtx, "plugin for loop::default") + // logging.DevContext(pluginCtx, "plugin for loop::default") run.Plugin(workerCtx, pluginCtx, pluginCancel, logger, firstPluginStarted, metricsData) if workerCtx.Err() != nil || toRunOnce == "true" { pluginCancel() @@ -436,7 +437,7 @@ func worker(parentCtx context.Context, logger *slog.Logger, loadedConfig config. select { case <-time.After(time.Duration(plugin.SleepInterval) * time.Second): case <-pluginCtx.Done(): - logging.DevDebug(pluginCtx, "plugin for loop::default::pluginCtx.Done()") + logging.DevContext(pluginCtx, "plugin for loop::default::pluginCtx.Done()") break } } diff --git a/plugins/handlers/github/README.md b/plugins/handlers/github/README.md index ae53e3b..b55d717 100644 --- a/plugins/handlers/github/README.md +++ b/plugins/handlers/github/README.md @@ -37,15 +37,17 @@ plugins: - If you are attempting to register runners for an entire organization, do NOT set `repo` and make sure your Github App has `Self-hosted runners` > `Read and write` permissions. - If your Organization level runner is registered and your public repo jobs are not picking it up even though the labels are a perfect match, make sure the Runner groups (likely `Default`) has `Allow public repositories`. +--- + Next, in your workflow yml you need to add several labels to `runs-on`. Here is the list and an example: -1. `self-hosted` (required) -1. `anka` (required) 1. `anka-template:{UUID OF TEMPLATE HERE}` (required) 1. `anka-template-tag:{TAG NAME OF TEMPLATE HERE}` (optional; uses latest if not populated) +**WARNING/NOTE:** If you are using the same template/tag/labels in `runs-on` for multiple runs/jobs, you will need to ensure that each job has a unique `unique-id` label or else they will compete for the same runner. To do this, set `"unique-id:${{ github.run_id }}"`. If you are starting multiple jobs in the same run, each job will need a unique `unique-id` label like `"unique-id:${{ github.run_id }}-1"` changing 1 to 2, 3, etc, for each job. + (from [t1-with-tag-1.yml](.github/workflows/t1-with-tag-1.yml)) ``` @@ -56,8 +58,6 @@ on: jobs: testJob: runs-on: [ - "self-hosted", - "anka", "anka-template:d792c6f6-198c-470f-9526-9c998efe7ab4", "anka-template-tag:vanilla+port-forward-22+brew-git", ] diff --git a/plugins/handlers/github/github.go b/plugins/handlers/github/github.go index feb651b..bb53fc0 100644 --- a/plugins/handlers/github/github.go +++ b/plugins/handlers/github/github.go @@ -222,7 +222,7 @@ func CheckForCompletedJobs( // BE VERY CAREFUL when you use return here. You could orphan the job if you're not careful. checkForCompletedJobsMu.Lock() // do not use 'continue' in the loop or else the ranOnce won't happen - logger.DebugContext(pluginCtx, "CheckForCompletedJobs "+ctxPlugin.Name+" | runOnce "+fmt.Sprint(runOnce)) + // logging.DevContext(pluginCtx, "CheckForCompletedJobs "+ctxPlugin.Name+" | runOnce "+fmt.Sprint(runOnce)) select { case <-failureChannel: // logger.ErrorContext(pluginCtx, "CheckForCompletedJobs"+ctxPlugin.Name+" failureChannel") @@ -773,7 +773,6 @@ func Run( // Install runner globals := config.GetGlobalsFromContext(pluginCtx) - logger.InfoContext(pluginCtx, "installing github runner inside of vm") installRunnerPath := filepath.Join(globals.PluginsPath, "handlers", "github", "install-runner.bash") registerRunnerPath := filepath.Join(globals.PluginsPath, "handlers", "github", "register-runner.bash") startRunnerPath := filepath.Join(globals.PluginsPath, "handlers", "github", "start-runner.bash") @@ -789,6 +788,7 @@ func Run( } return } + logger.DebugContext(pluginCtx, "copying install-runner.bash, register-runner.bash, and start-runner.bash to vm") err = ankaCLI.AnkaCopy(pluginCtx, installRunnerPath, registerRunnerPath, @@ -812,6 +812,7 @@ func Run( default: } + logger.DebugContext(pluginCtx, "installing github runner inside of vm") installRunnerErr = ankaCLI.AnkaRun(pluginCtx, "./install-runner.bash") if installRunnerErr != nil { logger.ErrorContext(pluginCtx, "error executing install-runner.bash", "err", installRunnerErr) @@ -829,6 +830,7 @@ func Run( return default: } + logger.DebugContext(pluginCtx, "registering github runner inside of vm") registerRunnerErr = ankaCLI.AnkaRun(pluginCtx, "./register-runner.bash", vm.Name, *runnerRegistration.Token, repositoryURL, strings.Join(workflowJob.Labels, ","), ctxPlugin.RunnerGroup, @@ -850,6 +852,7 @@ func Run( return default: } + logger.DebugContext(pluginCtx, "starting github runner inside of vm") startRunnerErr = ankaCLI.AnkaRun(pluginCtx, "./start-runner.bash") if startRunnerErr != nil { logger.ErrorContext(pluginCtx, "error executing start-runner.bash", "err", startRunnerErr) diff --git a/plugins/receivers/github/github.go b/plugins/receivers/github/github.go index 59bc304..ddbdcff 100644 --- a/plugins/receivers/github/github.go +++ b/plugins/receivers/github/github.go @@ -3,7 +3,6 @@ package github import ( "context" "encoding/json" - "fmt" "log/slog" "net/http" "os" @@ -32,11 +31,11 @@ func NewServer(port string) *Server { } } -func exists_in_array_exact(array_to_search_in []string, desired []string) bool { +func exists_in_array_partial(array_to_search_in []string, desired []string) bool { for _, desired_string := range desired { found := false for _, item := range array_to_search_in { - if item == desired_string { + if strings.Contains(item, desired_string) { found = true break } @@ -69,7 +68,8 @@ func InQueue(pluginCtx context.Context, logger *slog.Logger, jobID int64, queue continue } if *workflowJobEvent.WorkflowJob.ID == jobID { - return true, fmt.Errorf("WorkflowJob.ID %d already in queue", jobID) + // logger.WarnContext(pluginCtx, "WorkflowJob.ID already in queue", "WorkflowJob.ID", jobID) + return true, nil } } return false, nil @@ -203,9 +203,11 @@ func Run( "workflowJob.Action", *workflowJob.Action, "workflowJob.WorkflowJob.Labels", workflowJob.WorkflowJob.Labels, "workflowJob.WorkflowJob.ID", *workflowJob.WorkflowJob.ID, + "workflowJob.WorkflowJob.Name", *workflowJob.WorkflowJob.Name, + "workflowJob.WorkflowJob.RunID", *workflowJob.WorkflowJob.RunID, ) if *workflowJob.Action == "queued" { - if exists_in_array_exact(workflowJob.WorkflowJob.Labels, []string{"self-hosted", "anka"}) { + if exists_in_array_partial(workflowJob.WorkflowJob.Labels, []string{"anka-template"}) { // make sure it doesn't already exist inQueue, err := InQueue(pluginCtx, logger, *workflowJob.WorkflowJob.ID, "anklet/jobs/github/queued/"+ctxPlugin.Owner) if err != nil { @@ -228,11 +230,20 @@ func Run( logger.ErrorContext(pluginCtx, "error pushing job to queue", "error", push.Err()) return } - logger.InfoContext(pluginCtx, "job pushed to queued queue", "json", string(wrappedPayloadJSON)) + logger.InfoContext(pluginCtx, "job pushed to queued queue", + "workflowJob.ID", *workflowJob.WorkflowJob.ID, + "workflowJob.Name", *workflowJob.WorkflowJob.Name, + "workflowJob.RunID", *workflowJob.WorkflowJob.RunID, + "html_url", *workflowJob.WorkflowJob.HTMLURL, + "status", *workflowJob.WorkflowJob.Status, + "conclusion", workflowJob.WorkflowJob.Conclusion, + "started_at", workflowJob.WorkflowJob.StartedAt, + "completed_at", workflowJob.WorkflowJob.CompletedAt, + ) } } } else if *workflowJob.Action == "completed" { - if exists_in_array_exact(workflowJob.WorkflowJob.Labels, []string{"self-hosted", "anka"}) { + if exists_in_array_partial(workflowJob.WorkflowJob.Labels, []string{"anka-template"}) { queues := []string{} // get all keys from database for the main queue and service queues as well as completed @@ -242,7 +253,6 @@ func Run( return } queues = append(queues, queuedKeys...) - results := make(chan bool, len(queues)) var wg sync.WaitGroup for _, queue := range queues { @@ -289,7 +299,16 @@ func Run( logger.ErrorContext(pluginCtx, "error pushing job to queue", "error", push.Err()) return } - logger.InfoContext(pluginCtx, "job pushed to completed queue", "json", string(wrappedPayloadJSON)) + logger.InfoContext(pluginCtx, "job pushed to completed queue", + "workflowJob.ID", *workflowJob.WorkflowJob.ID, + "workflowJob.Name", *workflowJob.WorkflowJob.Name, + "workflowJob.RunID", *workflowJob.WorkflowJob.RunID, + "html_url", *workflowJob.WorkflowJob.HTMLURL, + "status", *workflowJob.WorkflowJob.Status, + "conclusion", workflowJob.WorkflowJob.Conclusion, + "started_at", workflowJob.WorkflowJob.StartedAt, + "completed_at", workflowJob.WorkflowJob.CompletedAt, + ) } } @@ -414,7 +433,7 @@ func Run( doneWithHooks = true break } - if !exists_in_array_exact(workflowJobEvent.WorkflowJob.Labels, []string{"self-hosted", "anka"}) { + if !exists_in_array_partial(workflowJobEvent.WorkflowJob.Labels, []string{"anka-template"}) { continue } allHooks = append(allHooks, map[string]interface{}{ diff --git a/trigger-test-runs.bash b/trigger-test-runs.bash index dc36215..36928e4 100755 --- a/trigger-test-runs.bash +++ b/trigger-test-runs.bash @@ -12,7 +12,7 @@ TRIGGER_RUN_COUNT="${4:-10}" for ((i=1; i<=TRIGGER_RUN_COUNT; i++)); do echo "Triggering run $i" - WORKFLOW_FILES=$(ls ./.github/workflows/*.yml | grep -v "check-pr") + WORKFLOW_FILES=$(ls ./.github/workflows/*.yml | grep -v "check-pr") # | grep -E "matrix|t1-with-tag-1" for FILE in $WORKFLOW_FILES; do WORKFLOW_ID=$(basename $FILE) curl \