From 544fef0d3e020a09843387fcd949cdec6e773755 Mon Sep 17 00:00:00 2001 From: Volker Schukai <volker.schukai@schukai.com> Date: Sat, 20 Apr 2024 16:15:45 +0200 Subject: [PATCH] chore: move from devenv to flake.nix #53 --- Taskfile.yml => .back/Taskfile.yml | 0 .back/scripts/hello.nix | 5 + .envrc | 5 +- .gitignore | 1 + .gitlab-ci.yml | 2 +- .golangci.yaml | 9 + .idea/.gitignore | 10 - .idea/aws.xml | 17 - .idea/go.imports.xml | 6 - .idea/inspectionProfiles/Project_Default.xml | 7 + .idea/job-queues.iml | 5 +- .idea/markdown.xml | 9 - .idea/misc.xml | 16 +- .idea/workspace.xml | 211 +++++ README.md | 54 +- database-6_test.go | 9 +- database.go | 4 +- database_test.go | 1 + devenv.lock | 190 ----- devenv.nix | 765 ------------------- devenv.yaml | 7 - errors.go | 5 + event-bus_test.go | 8 +- flake.lock | 126 +++ flake.nix | 93 +++ go.mod | 3 +- go.sum | 17 +- job-generic.go | 2 +- job-syncer.go | 4 +- job.go | 2 +- logger.go | 2 +- manager.go | 80 +- nix/scripts/build-cover-report.nix | 45 ++ nix/scripts/check-code.nix | 51 ++ nix/scripts/common.nix | 144 ++++ nix/scripts/go-task.nix | 43 ++ nix/scripts/run-ci-tests.nix | 38 + nix/scripts/run-extended-tests.nix | 40 + nix/scripts/run-tests.nix | 66 ++ queue.go | 10 +- runnable-fileoperation.go | 2 +- runnable-mail_test.go | 3 +- runnable-sftp_test.go | 5 +- schedule-time.go | 14 +- schedule-time_test.go | 39 + scheduler-inotify.go | 2 +- stat.go | 10 +- worker.go | 4 +- 48 files changed, 1104 insertions(+), 1087 deletions(-) rename Taskfile.yml => .back/Taskfile.yml (100%) create mode 100644 .back/scripts/hello.nix create mode 100644 .golangci.yaml delete mode 100644 .idea/.gitignore delete mode 100644 .idea/aws.xml delete mode 100644 .idea/go.imports.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 .idea/markdown.xml create mode 100644 .idea/workspace.xml delete mode 100644 devenv.lock delete mode 100644 devenv.nix delete mode 100644 devenv.yaml create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/scripts/build-cover-report.nix create mode 100644 nix/scripts/check-code.nix create mode 100644 nix/scripts/common.nix create mode 100644 nix/scripts/go-task.nix create mode 100644 nix/scripts/run-ci-tests.nix create mode 100644 nix/scripts/run-extended-tests.nix create mode 100644 nix/scripts/run-tests.nix create mode 100644 schedule-time_test.go diff --git a/Taskfile.yml b/.back/Taskfile.yml similarity index 100% rename from Taskfile.yml rename to .back/Taskfile.yml diff --git a/.back/scripts/hello.nix b/.back/scripts/hello.nix new file mode 100644 index 0000000..44bc156 --- /dev/null +++ b/.back/scripts/hello.nix @@ -0,0 +1,5 @@ +{ pkgs }: + +pkgs.writeShellScriptBin "hello-world" '' + echo "Hello, world!" +'' diff --git a/.envrc b/.envrc index 6de8a8a..80ce713 100644 --- a/.envrc +++ b/.envrc @@ -1,3 +1,2 @@ -source_url "https://raw.githubusercontent.com/cachix/devenv/d1f7b48e35e6dee421cfd0f51481d17f77586997/direnvrc" "sha256-YBzqskFZxmNb3kYVoKD9ZixoPXJh1C9ZvTLGFRkauZ0=" - -use devenv \ No newline at end of file +watch_file $(find . -name "*.nix" -printf '"%p" ') +use flake diff --git a/.gitignore b/.gitignore index 35183b1..b2e5998 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ smell.go /.attach_* .direnv/ .direnv/ +.back diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 35965c4..7da94d7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -37,7 +37,7 @@ test: tags: - nixos script: - - devenv shell test-lib + - nix develop --command run-ci-tests cache: - key: nixos diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..d876c9e --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,9 @@ +run: + concurrency: 4 + timeout: 5m + issues-exit-code: 2 + tests: false + +output: + show-stats: true + diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index a9d7db9..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml -# GitHub Copilot persisted chat sessions -/copilot/chatSessions diff --git a/.idea/aws.xml b/.idea/aws.xml deleted file mode 100644 index ec328d0..0000000 --- a/.idea/aws.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="accountSettings"> - <option name="activeProfile" value="profile:default" /> - <option name="activeRegion" value="eu-west-1" /> - <option name="recentlyUsedProfiles"> - <list> - <option value="profile:default" /> - </list> - </option> - <option name="recentlyUsedRegions"> - <list> - <option value="eu-west-1" /> - </list> - </option> - </component> -</project> \ No newline at end of file diff --git a/.idea/go.imports.xml b/.idea/go.imports.xml deleted file mode 100644 index be62eaf..0000000 --- a/.idea/go.imports.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="GoImports"> - <option name="optimizeImportsOnTheFly" value="false" /> - </component> -</project> \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..9c69411 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,7 @@ +<component name="InspectionProjectProfileManager"> + <profile version="1.0"> + <option name="myName" value="Project Default" /> + <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="TsLint" enabled="true" level="WARNING" enabled_by_default="true" /> + </profile> +</component> \ No newline at end of file diff --git a/.idea/job-queues.iml b/.idea/job-queues.iml index 9b4b749..25ed3f6 100644 --- a/.idea/job-queues.iml +++ b/.idea/job-queues.iml @@ -3,10 +3,7 @@ <component name="Go" enabled="true" /> <component name="NewModuleRootManager" inherit-compiler-output="true"> <exclude-output /> - <content url="file://$MODULE_DIR$"> - <excludeFolder url="file://$MODULE_DIR$/.devenv" /> - <excludeFolder url="file://$MODULE_DIR$/.direnv" /> - </content> + <content url="file://$MODULE_DIR$" /> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> </component> diff --git a/.idea/markdown.xml b/.idea/markdown.xml deleted file mode 100644 index ec0b30f..0000000 --- a/.idea/markdown.xml +++ /dev/null @@ -1,9 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="MarkdownSettings"> - <enabledExtensions> - <entry key="MermaidLanguageExtension" value="false" /> - <entry key="PlantUMLLanguageExtension" value="true" /> - </enabledExtensions> - </component> -</project> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 639900d..7aa94ca 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,20 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> - <component name="ProjectRootManager"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK"> <output url="file://$PROJECT_DIR$/out" /> </component> + <component name="accountSettings"> + <option name="activeProfile" value="profile:default" /> + <option name="activeRegion" value="eu-west-1" /> + <option name="recentlyUsedProfiles"> + <list> + <option value="profile:default" /> + </list> + </option> + <option name="recentlyUsedRegions"> + <list> + <option value="eu-west-1" /> + </list> + </option> + </component> </project> \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..1250234 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,211 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="AutoImportSettings"> + <option name="autoReloadType" value="SELECTIVE" /> + </component> + <component name="ChangeListManager"> + <list default="true" id="9979eb22-471e-4f2f-b624-fd3edb5e8c6e" name="Changes" comment=""> + <change afterPath="$PROJECT_DIR$/.back/scripts/hello.nix" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/.golangci.yaml" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/.idea/inspectionProfiles/Project_Default.xml" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/flake.lock" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/flake.nix" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/nix/scripts/build-cover-report.nix" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/nix/scripts/check-code.nix" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/nix/scripts/common.nix" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/nix/scripts/go-task.nix" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/nix/scripts/run-ci-tests.nix" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/nix/scripts/run-extended-tests.nix" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/nix/scripts/run-tests.nix" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/schedule-time_test.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/.envrc" beforeDir="false" afterPath="$PROJECT_DIR$/.envrc" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/.gitlab-ci.yml" beforeDir="false" afterPath="$PROJECT_DIR$/.gitlab-ci.yml" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/.idea/.gitignore" beforeDir="false" /> + <change beforePath="$PROJECT_DIR$/.idea/aws.xml" beforeDir="false" /> + <change beforePath="$PROJECT_DIR$/.idea/go.imports.xml" beforeDir="false" /> + <change beforePath="$PROJECT_DIR$/.idea/job-queues.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/job-queues.iml" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/.idea/markdown.xml" beforeDir="false" /> + <change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/Taskfile.yml" beforeDir="false" afterPath="$PROJECT_DIR$/.back/Taskfile.yml" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/database-6_test.go" beforeDir="false" afterPath="$PROJECT_DIR$/database-6_test.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/database.go" beforeDir="false" afterPath="$PROJECT_DIR$/database.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/database_test.go" beforeDir="false" afterPath="$PROJECT_DIR$/database_test.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/devenv.lock" beforeDir="false" /> + <change beforePath="$PROJECT_DIR$/devenv.nix" beforeDir="false" /> + <change beforePath="$PROJECT_DIR$/devenv.yaml" beforeDir="false" /> + <change beforePath="$PROJECT_DIR$/errors.go" beforeDir="false" afterPath="$PROJECT_DIR$/errors.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/event-bus_test.go" beforeDir="false" afterPath="$PROJECT_DIR$/event-bus_test.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/go.mod" beforeDir="false" afterPath="$PROJECT_DIR$/go.mod" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/go.sum" beforeDir="false" afterPath="$PROJECT_DIR$/go.sum" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/job-generic.go" beforeDir="false" afterPath="$PROJECT_DIR$/job-generic.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/job-syncer.go" beforeDir="false" afterPath="$PROJECT_DIR$/job-syncer.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/job.go" beforeDir="false" afterPath="$PROJECT_DIR$/job.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/logger.go" beforeDir="false" afterPath="$PROJECT_DIR$/logger.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/manager.go" beforeDir="false" afterPath="$PROJECT_DIR$/manager.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/queue.go" beforeDir="false" afterPath="$PROJECT_DIR$/queue.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/runnable-fileoperation.go" beforeDir="false" afterPath="$PROJECT_DIR$/runnable-fileoperation.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/runnable-mail_test.go" beforeDir="false" afterPath="$PROJECT_DIR$/runnable-mail_test.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/runnable-sftp_test.go" beforeDir="false" afterPath="$PROJECT_DIR$/runnable-sftp_test.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/schedule-time.go" beforeDir="false" afterPath="$PROJECT_DIR$/schedule-time.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/scheduler-inotify.go" beforeDir="false" afterPath="$PROJECT_DIR$/scheduler-inotify.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/stat.go" beforeDir="false" afterPath="$PROJECT_DIR$/stat.go" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/worker.go" beforeDir="false" afterPath="$PROJECT_DIR$/worker.go" afterDir="false" /> + </list> + <option name="SHOW_DIALOG" value="false" /> + <option name="HIGHLIGHT_CONFLICTS" value="true" /> + <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" /> + <option name="LAST_RESOLUTION" value="IGNORE" /> + </component> + <component name="ComposerSettings"> + <execution /> + </component> + <component name="FileTemplateManagerImpl"> + <option name="RECENT_TEMPLATES"> + <list> + <option value="Go File" /> + </list> + </option> + </component> + <component name="GOROOT" url="file:///nix/store/fqzds43dcw7164rm1h51n54l2ipxi1qj-go-1.21.9/share/go" /> + <component name="Git.Settings"> + <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" /> + </component> + <component name="PhpWorkspaceProjectConfiguration" interpreter_name="PHP 8.2" /> + <component name="ProjectColorInfo"><![CDATA[{ + "customColor": "", + "associatedIndex": 8 +}]]></component> + <component name="ProjectId" id="2fGcSxoYpsPbNVbRh8sUxQtBiHv" /> + <component name="ProjectViewState"> + <option name="flattenModules" value="true" /> + <option name="hideEmptyMiddlePackages" value="true" /> + <option name="showLibraryContents" value="true" /> + <option name="showVisibilityIcons" value="true" /> + <option name="sortByType" value="true" /> + <option name="sortKey" value="BY_TYPE" /> + </component> + <component name="PropertiesComponent"><![CDATA[{ + "keyToString": { + "DefaultGoTemplateProperty": "Go File", + "Go Test.TestScheduleJob in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug", + "Go Test.TestStructure in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug", + "Go Test.TestTimeFunctionSame in gitlab.schukai.com/oss/libraries/go/services/job-queues.executor": "Debug", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.go.formatter.settings.were.checked": "true", + "RunOnceActivity.go.migrated.go.modules.settings": "true", + "SHARE_PROJECT_CONFIGURATION_FILES": "true", + "git-widget-placeholder": "master", + "go.import.settings.migrated": "true", + "go.sdk.automatically.set": "true", + "last_opened_file_path": "/home/vs/workspaces/oss/go-libs/job-queues/nix/scripts", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "settings.editor.selected.configurable": "http.proxy", + "vue.rearranger.settings.migration": "true" + } +}]]></component> + <component name="RecentsManager"> + <key name="CopyFile.RECENT_KEYS"> + <recent name="$PROJECT_DIR$/nix/scripts" /> + <recent name="$PROJECT_DIR$/system/scripts" /> + </key> + <key name="MoveFile.RECENT_KEYS"> + <recent name="$PROJECT_DIR$/.back" /> + </key> + </component> + <component name="RunManager" selected="Go Test.TestStructure in gitlab.schukai.com/oss/libraries/go/services/job-queues"> + <configuration default="true" type="GoApplicationRunConfiguration" factoryName="Go Application"> + <module name="job-queues" /> + <working_directory value="$PROJECT_DIR$" /> + <go_parameters value="-i" /> + <kind /> + <directory value="$PROJECT_DIR$" /> + <filePath value="$PROJECT_DIR$" /> + <method v="2" /> + </configuration> + <configuration name="TestScheduleJob in gitlab.schukai.com/oss/libraries/go/services/job-queues" type="GoTestRunConfiguration" factoryName="Go Test" temporary="true" nameIsGenerated="true"> + <module name="job-queues" /> + <working_directory value="$PROJECT_DIR$" /> + <kind value="PACKAGE" /> + <package value="gitlab.schukai.com/oss/libraries/go/services/job-queues" /> + <directory value="$PROJECT_DIR$" /> + <filePath value="$PROJECT_DIR$" /> + <framework value="gotest" /> + <pattern value="^\QTestScheduleJob\E$" /> + <method v="2" /> + </configuration> + <configuration name="TestStructure in gitlab.schukai.com/oss/libraries/go/services/job-queues" type="GoTestRunConfiguration" factoryName="Go Test" temporary="true" nameIsGenerated="true"> + <module name="job-queues" /> + <working_directory value="$PROJECT_DIR$" /> + <kind value="PACKAGE" /> + <package value="gitlab.schukai.com/oss/libraries/go/services/job-queues" /> + <directory value="$PROJECT_DIR$" /> + <filePath value="$PROJECT_DIR$" /> + <framework value="gotest" /> + <pattern value="^\QTestStructure\E$" /> + <method v="2" /> + </configuration> + <configuration name="TestTimeFunctionSame in gitlab.schukai.com/oss/libraries/go/services/job-queues" type="GoTestRunConfiguration" factoryName="Go Test" temporary="true" nameIsGenerated="true"> + <module name="job-queues" /> + <working_directory value="$PROJECT_DIR$" /> + <kind value="PACKAGE" /> + <package value="gitlab.schukai.com/oss/libraries/go/services/job-queues" /> + <directory value="$PROJECT_DIR$" /> + <filePath value="$PROJECT_DIR$" /> + <framework value="gotest" /> + <pattern value="^\QTestTimeFunctionSame\E$" /> + <method v="2" /> + </configuration> + <configuration default="true" type="GoTestRunConfiguration" factoryName="Go Test"> + <module name="job-queues" /> + <working_directory value="$PROJECT_DIR$" /> + <go_parameters value="-i" /> + <kind /> + <directory value="$PROJECT_DIR$" /> + <filePath value="$PROJECT_DIR$" /> + <framework value="gotest" /> + <method v="2" /> + </configuration> + <recent_temporary> + <list> + <item itemvalue="Go Test.TestStructure in gitlab.schukai.com/oss/libraries/go/services/job-queues" /> + <item itemvalue="Go Test.TestScheduleJob in gitlab.schukai.com/oss/libraries/go/services/job-queues" /> + <item itemvalue="Go Test.TestTimeFunctionSame in gitlab.schukai.com/oss/libraries/go/services/job-queues" /> + </list> + </recent_temporary> + </component> + <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" /> + <component name="TypeScriptGeneratedFilesManager"> + <option name="version" value="3" /> + </component> + <component name="VgoProject"> + <settings-migrated>true</settings-migrated> + </component> + <component name="XDebuggerManager"> + <breakpoint-manager> + <breakpoints> + <line-breakpoint enabled="true" type="DlvLineBreakpoint"> + <url>file://$PROJECT_DIR$/schedule-time.go</url> + <line>61</line> + <option name="timeStamp" value="7" /> + </line-breakpoint> + <line-breakpoint enabled="true" type="DlvLineBreakpoint"> + <url>file://$PROJECT_DIR$/schedule-time.go</url> + <line>53</line> + <option name="timeStamp" value="8" /> + </line-breakpoint> + <line-breakpoint enabled="true" type="DlvLineBreakpoint"> + <url>file://$PROJECT_DIR$/schedule-time.go</url> + <line>51</line> + <option name="timeStamp" value="9" /> + </line-breakpoint> + </breakpoints> + </breakpoint-manager> + </component> +</project> \ No newline at end of file diff --git a/README.md b/README.md index 6751e01..0b5b9c8 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,12 @@ ## Overview -These `jobQueue` library written in Go provides a simple interface for managing jobs and workers. -It is designed to be used in a distributed environment where multiple workers can be assigned to a job -queue. The library provides a `Manager` that can be used to manage workers, schedule jobs, and handle +These `jobQueue` library written in Go provides a simple interface for managing jobs and workers. +It is designed to be used in a distributed environment where multiple workers can be assigned to a job +queue. The library provides a `Manager` that can be used to manage workers, schedule jobs, and handle the state of the job queue. -Jobs can also be persisted to a database using Gorm. +Jobs can also be persisted to a database using Gorm. The library also provides a `Cron` instance for scheduling jobs. @@ -15,7 +15,7 @@ The library also provides a `Cron` instance for scheduling jobs. ### Prerequisites -- Go 1.22+ +- Go 1.22+ ### Installation @@ -32,43 +32,39 @@ import "gitlab.schukai.com/oss/libraries/go/services/job-queues" func main() { - var err error - - m := jobqueue.NewManager() - w := jobqueue.NewWorker("worker1") - _ = m.AddWorker(w) - - _ = m.Start() - - job := jobqueue.Job{ - ID: "job1", - } - scheduler := jobqueue.InstantScheduler{} - - _ = m.ScheduleJob(job, &scheduler) - -} - -``` +var err error +m := jobqueue.NewManager() +w := jobqueue.NewWorker("worker1") +_ = m.AddWorker(w) +_ = m.Start() +job := jobqueue.Job{ +ID: "job1", +} +scheduler := jobqueue.InstantScheduler{} -## Tests +_ = m.ScheduleJob(job, &scheduler) -Run tests using: +} -```bash -task test ``` +## Development + +| Command | Description | +|--------------------|--------------------------------------| +| ` task check-code` | Run linters and static code analysis | +| ` task run-tests` | Run tests | + ## License This project is licensed under the AGPL-3.0 License - see the [LICENSE.md](LICENSE.md) file for details. ## Contact -- schukai GmbH - [schukai.de](https://www.schukai.com) -- [info@schukai.com](mailto:info@schukai.com) +- schukai GmbH - [schukai.de](https://www.schukai.com) +- [info@schukai.com](mailto:info@schukai.com) diff --git a/database-6_test.go b/database-6_test.go index 0e72761..731920f 100644 --- a/database-6_test.go +++ b/database-6_test.go @@ -7,7 +7,7 @@ package jobqueue import ( "fmt" "github.com/stretchr/testify/assert" - "gorm.io/driver/mysql" + "gorm.io/driver/sqlite" "gorm.io/gorm" "testing" "time" @@ -20,8 +20,11 @@ func TestWriteToDB6(t *testing.T) { // docker run --name mysql-test -e MYSQL_ROOT_PASSWORD=my-secret-pw -e MYSQL_DATABASE=testdb -p 3306:3306 -d mysql:latest && \ // docker logs -f mysql-test - dsn := "root:my-secret-pw@tcp(localhost:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local" - db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) + //dsn := "root:my-secret-pw@tcp(localhost:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local" + //db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) + + db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) + assert.NoError(t, err) manager := NewManager() manager.SetDB(db) diff --git a/database.go b/database.go index 170cc06..8e09113 100644 --- a/database.go +++ b/database.go @@ -153,7 +153,7 @@ func update(job *JobPersistence, db *gorm.DB) error { } } - for i, _ := range job.Logs { + for i := range job.Logs { job.Logs[i].LogID = 0 _ = tx.Create(&job.Logs[i]) // no error handling, if it fails, it fails @@ -206,7 +206,7 @@ func save(job *JobPersistence, db *gorm.DB) error { } } - for i, _ := range job.Logs { + for i := range job.Logs { job.Logs[i].LogID = 0 _ = tx.Create(&job.Logs[i]) // no error handling, if it fails, it fails diff --git a/database_test.go b/database_test.go index 1300fa3..7ee5f23 100644 --- a/database_test.go +++ b/database_test.go @@ -42,6 +42,7 @@ func TestDeleteJob(t *testing.T) { db.Model(&JobPersistence{}).Where("id = ?", "testJobID").Count(&count) assert.Equal(t, int64(0), count) } + func TestResetLogs(t *testing.T) { db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{}) assert.Nil(t, err) diff --git a/devenv.lock b/devenv.lock deleted file mode 100644 index 6414869..0000000 --- a/devenv.lock +++ /dev/null @@ -1,190 +0,0 @@ -{ - "nodes": { - "devenv": { - "locked": { - "dir": "src/modules", - "lastModified": 1713353943, - "narHash": "sha256-1gDYT+Hhqpnt+CDYL1h2huE07c6BCod6qlsaFNTPcn8=", - "owner": "cachix", - "repo": "devenv", - "rev": "5b933eb8522b61873e859c9c68de16330d8f5d8b", - "type": "github" - }, - "original": { - "dir": "src/modules", - "owner": "cachix", - "repo": "devenv", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1713145326, - "narHash": "sha256-m7+IWM6mkWOg22EC5kRUFCycXsXLSU7hWmHdmBfmC3s=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "53a2c32bc66f5ae41a28d7a9a49d321172af621e", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-23.11", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-stable": { - "locked": { - "lastModified": 1710695816, - "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "614b4613980a522ba49f0d194531beddbb7220d3", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-23.11", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1713145326, - "narHash": "sha256-m7+IWM6mkWOg22EC5kRUFCycXsXLSU7hWmHdmBfmC3s=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "53a2c32bc66f5ae41a28d7a9a49d321172af621e", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "ref": "nixos-23.11", - "type": "indirect" - } - }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": "flake-compat", - "flake-utils": "flake-utils", - "gitignore": "gitignore", - "nixpkgs": [ - "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" - }, - "locked": { - "lastModified": 1712897695, - "narHash": "sha256-nMirxrGteNAl9sWiOhoN5tIHyjBbVi5e2tgZUgZlK3Y=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "40e6053ecb65fcbf12863338a6dcefb3f55f1bf8", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, - "root": { - "inputs": { - "devenv": "devenv", - "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks", - "version": "version" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "version": { - "inputs": { - "nixpkgs": "nixpkgs_2" - }, - "locked": { - "lastModified": 1704542622, - "narHash": "sha256-HnFuaOXHoxv8tpBvMsEjfhcl/hFNxEY7GbBqoyJ1U8U=", - "ref": "refs/heads/master", - "rev": "6b4f85fe6d934429cf3055bbcd8cf15014730118", - "revCount": 114, - "type": "git", - "url": "https://gitlab.schukai.com/oss/utilities/version.git" - }, - "original": { - "type": "git", - "url": "https://gitlab.schukai.com/oss/utilities/version.git" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/devenv.nix b/devenv.nix deleted file mode 100644 index 06f21d3..0000000 --- a/devenv.nix +++ /dev/null @@ -1,765 +0,0 @@ -{ pkgs ? import <nixpkgs> {}, inputs, phps, lib, config, modulesPath, ... }: - -{ - # https://devenv.sh/packages/ - packages = with pkgs; [ - inputs.version.defaultPackage."${builtins.currentSystem}" - appimage-run - blackbox - blackbox-terminal - coreutils-full - dbeaver - glibc.static - dbeaver - delve - dialog - drill - eza - fd - fd - feh - gcc12 - gdlv - git - glab - gnugrep - gnumake - gnused - go-licenses - gosec - go-task - gum - httpie - hurl - jq - libffi - logrotate - meld - memcached - netcat - nixfmt - nodePackages.mermaid-cli - openssh - procps - ranger - unixtools.xxd - unzip - util-linux - wget - zlib - ]; - - # https://devenv.sh/languages/ - # languages.nix.enable = true; - languages = { go = { enable = true; }; }; - - difftastic.enable = true; - - scripts.run-sshd.exec = '' - set -x - - cd ${config.devenv.root}/docker/sftp-server - ${pkgs.docker-client}/bin/docker docker build -t jobqueue-sftp-server . - cd - - - - - ${pkgs.coreutils}/bin/chmod 700 ${config.devenv.root}/.config/temp_rsa_key - ${pkgs.coreutils}/bin/chmod 700 ${config.devenv.root}/.config/temp_ed25518_key - - ${pkgs.coreutils}/bin/mkdir -p ${config.devenv.root}/.devenv/chroot/home/demo/.ssh - ${pkgs.coreutils}/bin/cat ${config.devenv.root}/.config/demo_ssh_key.pub > ${config.devenv.root}/.devenv/chroot/home/demo/.ssh/authorized_keys - ${pkgs.coreutils}/bin/chmod 700 ${config.devenv.root}/.devenv/chroot/home/demo/.ssh - ${pkgs.coreutils}/bin/chmod 600 ${config.devenv.root}/.devenv/chroot/home/demo/.ssh/authorized_keys - - - ${pkgs.coreutils}/bin/cat <<EOF > ${config.devenv.root}/.config/sshd_config - -AuthorizedKeysCommand ${pkgs.coreutils}/bin/cat ${config.devenv.root}/.devenv/chroot/home/demo/.ssh/authorized_keys -AuthorizedKeysCommandUser nobody - -Match User root - ChrootDirectory ${config.devenv.root}/.devenv/chroot - ForceCommand internal-sftp - PasswordAuthentication no - PermitTunnel no - AllowAgentForwarding no - AllowTcpForwarding no - X11Forwarding no - PermitRootLogin no - AllowUsers demo root -EOF - - ${pkgs.openssh}/bin/sshd -D -e -o \ - HostKey=${config.devenv.root}/.config/temp_rsa_key \ - -f ${config.devenv.root}/.config/sshd_config \ - -o HostKey=${config.devenv.root}/.config/temp_ed25518_key \ - -o Port=''${1:-2222} \ - -o AuthorizedKeysFile=${config.devenv.root}/.devenv/chroot/home/demo/.ssh/authorized_keys \ - -o PidFile=${config.devenv.root}/.devenv/sshd.pid - ''; - - scripts.draw-graph.exec = '' - echo -e "Enter Meirmaid graph definition. ''${RED}End with Ctrl+D''${RESET}\n" - diagram=$(${pkgs.gum}/bin/gum write --placeholder "Enter Meirmaid graph definition. End with Ctrl+D") - - tmpOutput=$(mktemp).png - - echo "$diagram" | ${pkgs.nodePackages.mermaid-cli}/bin/mmdc -i - -o "$tmpOutput" - ${pkgs.feh}/bin/feh $tmpOutput - - # should delte the file, but does not work ask with gum - ${pkgs.gum}/bin/gum confirm "Delete temporary file?" - if [ $? -eq 0 ]; then - rm "$tmpOutput" - else - echo "not deleting; file is at $tmpOutput" - fi - ''; - - scripts.get-go-default-packages.exec = '' - #!${pkgs.bash}/bin/bash - echo $(awk -F ' ' '/^module / { print $2 }' go.mod) - ''; - - # This script is executed when the app is built - # You can use it to build the app - scripts.test-lib.exec = '' - #!${pkgs.bash}/bin/bash - set -x - -${pkgs.gosec}/bin/gosec ${config.devenv.root} -${pkgs.go}/bin/go test -mod=mod -tags 'runOnTask,osusergo,netgo' -a -ldflags "-extldflags '-static' -s -w" -cover -v ${config.devenv.root} -${pkgs.go}/bin/go test -mod=mod -tags 'runOnTask,osusergo,netgo' -a -ldflags "-extldflags '-static' -s -w" -bench -v ${config.devenv.root} -${pkgs.go}/bin/go test -mod=mod -tags 'runOnTask,osusergo,netgo' -a -ldflags "-extldflags '-static' -s -w" -race -v ${config.devenv.root} - - ''; - - # This scritp is used to deploy the app to the gitlab registry - # It is used by the gitlab-ci.yml file - # The environment variables are set in the gitlab project settings - scripts.deploy-lib.exec = '' - #!${pkgs.bash}/bin/bash - - PATH="''${PATH}":${pkgs.coreutils}/bin - PATH="''${PATH}":${pkgs.jq}/bin/ - PATH="''${PATH}":${pkgs.curl}/bin/ - PATH="''${PATH}":${pkgs.moreutils}/bin/ - PATH="''${PATH}":${pkgs.gnutar}/bin - PATH="''${PATH}":${pkgs.gzip}/bin/ - PATH="''${PATH}":${pkgs.eza}/bin/ - PATH="''${PATH}":${pkgs.git}/bin/ - PATH="''${PATH}":${ - inputs.version.defaultPackage."${builtins.currentSystem}" - }/bin/ - - export PATH - - if [[ -f .env-gitlab-ci ]]; then - source .env-gitlab-ci - rm .env-gitlab-ci - fi - - set -x - ## if $HOME not set, set it to current directory - if [[ -z "''${HOME}" ]]; then - HOME=$(pwd) - fi - - export HOME - - git config user.email "''${GITLAB_USER_EMAIL}" - git config user.name "''${GITLAB_USER_NAME:-"Gitlab CI"}" - git config pull.rebase true - git config http.sslVerify "false" - git remote set-url origin https://pad:''${GITLAB_TOKEN}@''${CI_REPOSITORY_URL#*@} - - git fetch --all --tags --unshallow - git reset --hard origin/master - git checkout $CI_COMMIT_REF_NAME - git pull origin $CI_COMMIT_REF_NAME - - if [ ! -z "''${CI_PROJECT_DIR}" ]; then - echo "CI_PROJECT_DIR is set, using it as project root." - project_root=$(realpath "''${CI_PROJECT_DIR}")/ - elif [ ! -z "''${DEVENV_ROOT}" ]; then - echo "DEVENV_ROOT is set, using it as project root." - project_root=$(realpath "''${DEVENV_ROOT}")/ - else - echo "Error: DEVENV_ROOT or CI_PROJECT_DIR environment variables are not set." - exit 1 - fi - - if [ ! -d "''${project_root}" ]; then - echo "Error: Project root directory does not seem to be valid." - echo "Check the DEVENV_ROOT or CI_PROJECT_DIR environment variables." - exit 1 - fi - - if [ -z "'CI_JOB_TOKEN" ]; then - echo "Error: CI_JOB_TOKEN variable is not set." - exit 1 - fi - - git --no-pager log --decorate=short --pretty=oneline - gitVersion=v$(version predict) - git tag -a $gitVersion -m"chore: bump version" - git --no-pager log --decorate=short --pretty=oneline - git push -o ci.skip origin ''${CI_COMMIT_REF_NAME} --tags - - echo "done" - - ''; - - enterShell = '' - -cat <<'EOF' > CONTRIBUTING.md -# Contributing to schukai GmbH Projects - -## Code of Conduct - -Be a human, not an asshole. Common sense and basic human decency apply. - -## Getting Started - -### Setting up the Project - -1. Fork the project on GitLab. -2. Clone your fork locally. Replace `[your-username]` with your GitLab username and `[project-name]` with the actual project name: - ```bash - git clone $(git config --get remote.origin.url) - ``` -3. Add the upstream repository. Replace `[original-username]` and `[project-name]` with the original repository's username and project name: - ```bash - git remote add upstream https://gitlab.schukai.com/[original-username]/[project-name].git - ``` - -### Making Changes - -1. Create a new branch: - ```bash - git checkout -b new-feature-branch - ``` -2. Make your changes. -3. Commit your changes: - ```bash - git commit -m "Description of change" - ``` - -### Submitting a Merge Request - -1. Push your changes to your fork: - ```bash - git push origin new-feature-branch - ``` -2. Navigate to the original project repository on `gitlab.schukai.com`. -3. Open a Merge Request and provide a clear description of the changes. - -## Coding Guidelines - -- Follow the coding style used in the project. -- Write unit tests for new features. -- Ensure that all tests pass before submitting a Merge Request. - -## Reporting Issues - -If you find an issue, please create a new issue on `gitlab.schukai.com`. - -## Additional Resources - -- [GitLab Flow](https://docs.gitlab.com/ee/topics/gitlab_flow.html) -- [GitLab Merge Request Guidelines](https://docs.gitlab.com/ee/user/project/merge_requests/) - -Thank you for your contribution! - -EOF - -cat <<'EOF' > LICENSE -Copyright (C) 2023 schukai GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published -by the Free Software Foundation, either version 3 of the License. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see <https://www.gnu.org/licenses/>. - -EOF - -cat <<'EOF' > Taskfile.yml - -# THIS FILE IS AUTOGENERATED BY THE DEVENVSHELL -# DO NOT EDIT THIS FILE MANUALLY -# INSTEAD EDIT THE DEVENVSHELL CONFIGURATION FILE devenv.nix -# AND OPEN A SHELL WITH THE COMMAND devenv shell -# -# Information about the task runner can be found here: -# https://taskfile.dev - -version: '3' - -tasks: - default: - cmds: - - task --list - silent: true - - test: - desc: Execute unit tests in Go. - env: - TEST_BY_TASK: true - cmds: - - docker pull atmoz/sftp:alpine - - docker pull axllent/mailpit - - echo "Execute unit tests in Go." - - test-lib - - test-fuzz: - desc: Conduct fuzzing tests.# - env: - TEST_BY_TASK: true - cmds: - - echo "Conduct fuzzing tests." - - go test -tags=runOnTask -v -fuzztime=30s -fuzz=Fuzz ./... - - add-licenses: - desc: Attach license headers to Go files. - cmds: - - echo "Attach license headers to Go files." - - go install github.com/google/addlicense@latest - - addlicense -c "schukai GmbH" -s -l "AGPL-3.0" ./*.go - silent: true - - check-licenses: - desc: Check license headers of Go files. - silent: true - cmds: - - go-licenses save "$(get-go-default-packages)" --ignore "gitlab.schukai.com" --force --save_path ''${DEVENV_ROOT}/licenses/ - - check: - desc: Confirm repository status. - cmds: - - git diff-index --quiet HEAD || (echo "There are uncommitted changes after running make. Please commit or stash them before running make."; exit 1) - silent: true - - commit: - desc: Commit changes to the repository. - aliases: - - c - - ci - - git-commit - cmds: - - do-git-commit -EOF - -cat <<'EOF' > .gitlab-ci.yml - -# THIS FILE IS AUTOGENERATED BY THE DEVENVSHELL -# DO NOT EDIT THIS FILE MANUALLY -# INSTEAD EDIT THE DEVENVSHELL CONFIGURATION FILE devenv.nix -# AND OPEN A SHELL WITH THE COMMAND devenv shell -# - -image: docker-registry.schukai.com:443/nixos-ci-devenv:latest - -# services: -# - docker:dind - -variables: - # The repo name as used in - # https://github.com/nix-community/NUR/blob/master/repos.json - NIXOS_VERSION: "23.05" - NIXPKGS_ALLOW_UNFREE: "1" - NIXPKGS_ALLOW_INSECURE: "1" - GIT_DEPTH: 10 - -stages: - - test - - deploy - -before_script: - - echo > .env-gitlab-ci - - variables=("HOME=$HOME" "CI_COMMIT_REF_NAME=$CI_COMMIT_REF_NAME" "CI_REPOSITORY_URL=$CI_REPOSITORY_URL" "GITLAB_TOKEN=$GITLAB_TOKEN" "CI_JOB_TOKEN=$CI_JOB_TOKEN" "GITLAB_USER_EMAIL=$GITLAB_USER_EMAIL" "GITLAB_USER_NAME=\"$GITLAB_USER_NAME\"" "CI_REGISTRY_USER=$CI_REGISTRY_USER" "CI_PROJECT_ID=$CI_PROJECT_ID" "CI_PROJECT_DIR=$CI_PROJECT_DIR" "CI_API_V4_URL=$CI_API_V4_URL" "CI_PROJECT_NAME=$CI_PROJECT_NAME" "CI_COMMIT_SHORT_SHA=$CI_COMMIT_SHORT_SHA"); for var in "''${variables[@]}"; do echo "$var" >> .env-gitlab-ci; done - - cat .env-gitlab-ci - - env - - nix shell nixpkgs#docker-client -c docker info - -after_script: - - if [ -f .env-gitlab-ci ]; then rm .env-gitlab-ci; fi - -test: - stage: test - tags: - - nixos - script: - - devenv shell test-lib - - cache: - - key: nixos - paths: - - /nix/store - - artifacts: - paths: - - dist - -deploy: - stage: deploy - tags: - - nixos - script: - - devenv shell -c deploy-lib - - when: on_success - - cache: - - key: nixos - paths: - - /nix/store - -EOF - - ''; - - scripts.do-git-commit.exec = '' - #!/usr/bin/env bash - - # Define colors if the terminal supports it - if [ -t 1 ]; then - RED='\033[0;31m' - GREEN='\033[0;32m' - RESET='\033[0m' - BOLD='\033[1m' - else - RED="" - GREEN="" - RESET="" - fi - - step=1 - - reset - clear - - # create random log file - LOGFILE="$(mktemp)" - if [ $? -ne 0 ]; then - echo -e "''${RED}✖ Could not create temporary log file. Exiting.''${RESET}" - exit 1 - fi - - log_and_display() { - echo -e "''${GREEN}==> $step. $1''${RESET}" | tee -a $LOGFILE - step=$((step + 1)) - } - - log_error_and_display() { - echo -e "''${RED}==> $step. $1''${RESET}" | tee -a $LOGFILE - } - - printLogfileAndExit() { - exit_code=$1 - echo -e "\n\n========================================\n\n\n" - - echo -e "\n\n''${BOLD}Git and GitLab Automation Script''${RESET}\n\nI have performed the following actions:\n\n" - cat "$LOGFILE" - - # Optional: Remove log file - rm -f "$LOGFILE" - - if [ $exit_code -eq 0 ]; then - echo -e "\n''${GREEN}✔''${RESET} All actions were successful" | tee -a $LOGFILE - elif [ $exit_code -eq -1 ]; then - echo -e "\n''${RED}✖''${RESET} The script was manually cancelled" | tee -a $LOGFILE - exit_code=0 - else - echo -e "\n''${RED}✖''${RESET} Some actions failed" | tee -a $LOGFILE - fi - - exit $exit_code - } - - print_headline() { - local title=$1 - local underline=$(printf '─%.0s' $(seq 1 ''${#title})) - echo -e "\n\n''${BOLD}''${title}\n''${underline}''${RESET}\n" - } - - do_cancel() { - echo -e "''${RED}==> ✖ Cancelled.''${RESET}" | tee -a $LOGFILE - printLogfileAndExit -1 - } - - # Function for unified logging and display - log_action() { - if [ $? -eq 0 ]; then - echo -e " ''${GREEN}✔''${RESET} $1: Successful" | tee -a $LOGFILE - else - echo -e " ''${RED}✖''${RESET} $1: Failed" | tee -a $LOGFILE - printLogfileAndExit 1 - fi - } - - print_what_to_do() { - echo -e "\n\nWhat do you want to do?\n" - } - - git_status=$(git status --porcelain) - if [[ -z "$git_status" ]]; then - log_error_and_display "No changes to commit. Exiting." - printLogfileAndExit 0 - fi - - print_headline "Choose commit type" - selection=$(gum choose "feat: (new feature for the user, not a new feature for build script)" "fix: (bug fix for the user, not a fix to a build script)" "chore: (updating grunt tasks etc.; no production code change)" "docs: (changes to the documentation)" "style: (formatting, missing semi colons, etc; no production code change)" "refactor: (refactoring production code, eg. renaming a variable)" "test: (adding missing tests, refactoring tests; no production code change)" "Cancel") - - commit_type=$(echo "$selection" | awk -F':' '{print $1}') - - if [[ "$commit_type" == "Cancel" ]]; then - do_cancel - fi - - log_and_display "You chose the commit type: $commit_type" - - # NEXT STEP ISSUE HANDLING ############################################################################################################ - #log_and_display "Issue handling" - - gitlabIssues=() - while IFS= read -r line; do - if [[ $line =~ ^# ]]; then - id=$(echo "$line" | awk '{print substr($1, 2)}') - title=$(echo "$line" | awk -F'about' '{print $1}' | awk '{$1=$2=""; print substr($0, 3)}') - gitlabIssues+=("$id > $title") - fi - done < <(gum spin --spinner dot --show-output --title "Ask gitlab ..." -- glab issue list --output-format=details) - - ## if issues are available, ask if user wants to use an existing issue or create a new one - createOption="Create new issue" - existingOption="Use existing issue" - cancelOption="Cancel" - - print_headline "Choose issue handling" - if [ ''${#gitlabIssues[@]} -eq 0 ]; then - log_and_display "There are no issues available." - - print_what_to_do - choice=$(gum choose "$createOption" "$cancelOption") - - else - log_and_display "There are ''${#gitlabIssues[@]} issues available." - print_what_to_do - choice=$(gum choose "$createOption" "$existingOption" "$cancelOption") - fi - - if [[ "$choice" == "$cancelOption" ]]; then - do_cancel - fi - - ## array of issue ids - work_on_issue_ids=() - - issue_text="" - - if [[ "$choice" == "$createOption" ]]; then - print_headline "Create new issue" - issue_text=$(gum input --placeholder "Enter issue title") - echo -e "Enter issue description. ''${RED}End with Ctrl+D''${RESET}\n" - issue_description=$(gum write --placeholder "Enter issue description. End with Ctrl+D") - - if [[ -z "$issue_text" ]]; then - log_error_and_display "Issue title is empty. Exiting." - printLogfileAndExit 1 - fi - - log_and_display "You entered the issue title: $issue_text" - log_and_display "You entered the issue description: $issue_description" - echo -e "\n" - - gum confirm "Do you want to create this issue?" - # gum confirm exits with status 0 if confirmed and status 1 if cancelled. - if [ $? -eq 1 ]; then - do_cancel - fi - - issue_output=$(glab issue create -t"$issue_text" --no-editor --description "$issue_description") - issue_id=$(echo "$issue_output" | grep -oP '(?<=/issues/)\d+') - - work_on_issue_ids+=("$issue_id") - - log_action "glab issue with id $issue_id created" - - else - - print_headline "Use existing issue" - echo -e "Select issue with arrow keys and press tab or space to select. Press enter to confirm.\n" - issue_ids=$(gum choose --no-limit "''${gitlabIssues[@]}") - - # assign issue_ids to work_on_issue_ids. iterate over lines and take integer from beginning of line - while IFS= read -r line; do - work_on_issue_ids+=($(echo "$line" | grep -oP '^\d+')) - done <<<"$issue_ids" - - fi - - if [ ''${#work_on_issue_ids[@]} -eq 0 ]; then - log_and_display "No issue selected. Exiting." - printLogfileAndExit 0 - fi - - # NEXT STEP COMMIT MESSAGE ############################################################################################################ - # print work_on_issue_ids - work_on_issue_ids_string="" - for i in "''${work_on_issue_ids[@]}"; do - work_on_issue_ids_string+="#$i " - done - - log_and_display "You chose to work on the following issues: ''${work_on_issue_ids_string}" - - - print_headline "Check for changes to commit" - - # ' ' = unmodified - # M = modified - # T = file type changed (regular file, symbolic link or submodule) - # A = added - # D = deleted - # R = renamed - # C = copied (if config option status.renames is set to "copies") - # U = updated but unmerged - # https://man.freebsd.org/cgi/man.cgi?query=git-status&sektion=1&manpath=freebsd-release-ports - - count_all_changes=$(echo "$git_status" | wc -l) - count_staged_changes=$(echo "$git_status" | grep -c '^M') - count_new_staged_files=$(echo "$git_status" | grep -c '^A') - count_staged_changes=$((count_staged_changes + count_new_staged_files)) - - - - git_options_all="All $count_all_changes changes" - git_options_staged="Only the $count_staged_changes staged changes" - git_options_select_files="Select files" - git_options_cancel="Cancel" - - git_options_array=() - if [[ $count_all_changes -gt 0 ]]; then - git_options_array+=("$git_options_all") - fi - - if [[ $count_staged_changes -gt 0 ]]; then - git_options_array+=("$git_options_staged") - fi - - git_options_array+=( "$git_options_select_files" ) - git_options_array+=( "$git_options_cancel" ) - - - selection=$(gum choose "''${git_options_array[@]}") - if [[ "$selection" == "$git_options_cancel" ]]; then - do_cancel - fi - - if [[ "$selection" == "$git_options_all" ]]; then - git add -A - echo "1" - elif [[ "$selection" == "$git_options_select_files" ]]; then - - files=() - while IFS= read -r line; do - files+=("$line") - done <<<"$git_status" - - selected_files=$(gum choose --no-limit "''${files[@]}") - - # no files selected - if [[ -z "$selected_files" ]]; then - log_and_display "No files selected. Exiting." - printLogfileAndExit 0 - fi - - # add selected files - while IFS= read -r line; do - ## git proclimne could have letter, ? or ! at the beginning of the line - file=$(echo "$line" | awk '{print $2}') - if [[ -z "$file" || ! -f "$file" ]]; then - log_and_display "No file found in line: $line" - continue - fi - - git add "$file" - done <<<"$selected_files" - - fi - - ## count staged changes again and print - count_staged_changes=$(echo "$git_status" | grep -c '^M') - count_new_staged_files=$(echo "$git_status" | grep -c '^A') - count_staged_changes=$((count_staged_changes + count_new_staged_files)) - - log_and_display "You have $count_staged_changes staged changes to commit." - - # NEXT STEP COMMIT MESSAGE ############################################################################################################ - - print_headline "Enter commit message" - commit_message=$(gum input --placeholder "Enter commit message" --value "$commit_type: $issue_text $work_on_issue_ids_string") - - if [[ -z "$commit_message" ]]; then - log_error_and_display "Commit message is empty. Exiting." - printLogfileAndExit 1 - fi - - log_and_display "You entered the commit message: $commit_message" - - gum confirm "Do you want to commit with this message?" - if [ $? -eq 1 ]; then - do_cancel - fi - - # NEXT STEP COMMIT #################################################################################################################### - print_headline "Committing changes" - - if ! git commit -m "$commit_message" ; then - log_error_and_display "Commit failed. Exiting." - printLogfileAndExit 1 - fi - - log_and_display "Commit successful." - - # NEXT STEP PUSH ###################################################################################################################### - - print_headline "Pushing changes" - - if ! git push ; then - log_error_and_display "Push failed. Exiting." - printLogfileAndExit 1 - fi - - log_and_display "Push successful." - - # Close issue ###################################################################################################################### - - print_headline "Closing issues" - - for issue_id in "''${work_on_issue_ids[@]}"; do - - gum confirm "Do you want to close issue #$issue_id?" - if [ $? -eq 1 ]; then - continue - fi - - if ! glab issue close "$issue_id" ; then - log_error_and_display "Closing issue $issue_id failed. Exiting." - else - log_and_display "Closing issue $issue_id successful." - fi - done - - printLogfileAndExit 0 - ''; - - -} diff --git a/devenv.yaml b/devenv.yaml deleted file mode 100644 index 1fd1de9..0000000 --- a/devenv.yaml +++ /dev/null @@ -1,7 +0,0 @@ -inputs: - nixpkgs: - url: github:nixos/nixpkgs/nixos-23.11 - - version: - url: git+https://gitlab.schukai.com/oss/utilities/version.git - flake: true diff --git a/errors.go b/errors.go index b231eec..d04724a 100644 --- a/errors.go +++ b/errors.go @@ -57,4 +57,9 @@ var ( ErrFailedToCreate = fmt.Errorf("failed to create") ErrFailedToQueryExistingJob = fmt.Errorf("failed to query an existing job") ErrFailedToSaveJob = fmt.Errorf("failed to save a job") + ErrScheduleTimeIsInThePast = fmt.Errorf("scheduled time is in the past") + ErrParameterIsNil = fmt.Errorf("parameter is nil") + ErrJobIDEmpty = fmt.Errorf("job ID is empty") + ErrManagerNotInitialized = fmt.Errorf("manager is not initialized") + ErrJobSyncerNotInitialized = fmt.Errorf("JobSyncer is not initialized") ) diff --git a/event-bus_test.go b/event-bus_test.go index dfedcf6..7617b49 100644 --- a/event-bus_test.go +++ b/event-bus_test.go @@ -13,7 +13,7 @@ func TestSubscribeAndPublish(t *testing.T) { eb := NewEventBus() jobAddedCh := make(chan interface{}, 1) - defer close(jobAddedCh) + defer close(jobAddedCh) eb.Subscribe(JobAdded, jobAddedCh) jobData := "New Job Data" @@ -37,7 +37,7 @@ func TestUnsubscribe(t *testing.T) { jobAddedCh := make(chan interface{}, 1) defer close(jobAddedCh) - + eb.Subscribe(JobAdded, jobAddedCh) eb.Unsubscribe(JobAdded, jobAddedCh) @@ -59,8 +59,8 @@ func TestMultipleSubscribers(t *testing.T) { jobAddedCh2 := make(chan interface{}, 1) eb.Subscribe(JobAdded, jobAddedCh1) eb.Subscribe(JobAdded, jobAddedCh2) - defer close(jobAddedCh1) - defer close(jobAddedCh2) + defer close(jobAddedCh1) + defer close(jobAddedCh2) jobData := "New Job Data" eb.Publish(JobAdded, jobData) diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..77c6c65 --- /dev/null +++ b/flake.lock @@ -0,0 +1,126 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "git-commit": { + "inputs": { + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1, + "narHash": "sha256-8hXrOA8SKy//ctoL1poIhJwuT7G4rvVu7FguROzEoDg=", + "path": "./git-commit", + "type": "path" + }, + "original": { + "path": "./git-commit", + "type": "path" + } + }, + "gitlab-commit": { + "inputs": { + "git-commit": "git-commit", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1704993617, + "narHash": "sha256-++u7I3KCDgP+JhW70k5tiLfBESWVSKdVK7aei0G+mR8=", + "ref": "refs/heads/master", + "rev": "e63b1d6ae5526158fa2a1f4cd53b0ea4f4c93573", + "revCount": 18, + "type": "git", + "url": "https://gitlab.schukai.com/schukai/entwicklung/nix-flakes" + }, + "original": { + "type": "git", + "url": "https://gitlab.schukai.com/schukai/entwicklung/nix-flakes" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1704874635, + "narHash": "sha256-YWuCrtsty5vVZvu+7BchAxmcYzTMfolSPP5io8+WYCg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3dc440faeee9e889fe2d1b4d25ad0f430d449356", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-23.11", + "type": "indirect" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1713344939, + "narHash": "sha256-jpHkAt0sG2/J7ueKnG7VvLLkBYUMQbXQ2L8OBpVG53s=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e402c3eb6d88384ca6c52ef1c53e61bdc9b84ddd", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-23.11", + "type": "indirect" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1713344939, + "narHash": "sha256-jpHkAt0sG2/J7ueKnG7VvLLkBYUMQbXQ2L8OBpVG53s=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "e402c3eb6d88384ca6c52ef1c53e61bdc9b84ddd", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "gitlab-commit": "gitlab-commit", + "nixpkgs": "nixpkgs_3" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..1dad0b8 --- /dev/null +++ b/flake.nix @@ -0,0 +1,93 @@ +{ + description = "Development environment"; + + inputs = { + nixpkgs = {url = "github:nixos/nixpkgs/nixos-23.11";}; + flake-utils = {url = "github:numtide/flake-utils";}; + gitlab-commit = {url = "git+https://gitlab.schukai.com/schukai/entwicklung/nix-flakes";}; + }; + + outputs = { + self, + nixpkgs, + flake-utils, + gitlab-commit, + }: + flake-utils.lib.eachDefaultSystem (system: let + inherit (nixpkgs.lib) optional; + pkgs' = import nixpkgs {inherit system;}; + + script-task = pkgs'.callPackage ./nix/scripts/go-task.nix {}; + script-run-tests = pkgs'.callPackage ./nix/scripts/run-tests.nix {}; + script-run-extended-tests = pkgs'.callPackage ./nix/scripts/run-extended-tests.nix {}; + script-run-ci-tests = pkgs'.callPackage ./nix/scripts/run-ci-tests.nix {}; + script-check-code = pkgs'.callPackage ./nix/scripts/check-code.nix {}; + script-build-cover-report = pkgs'.callPackage ./nix/scripts/build-cover-report.nix {}; + + import-gitlab-commit = gitlab-commit.packages.${system}.git-commit; + +# ciJobToken = builtins.getEnv "CI_JOB_TOKEN"; +# gitCommit = +# if ciJobToken == "" +# then (builtins.getFlake "git+https://gitlab.schukai.com/schukai/entwicklung/nix-flakes").packages.${builtins.currentSystem}.git-commit +# else ""; + + + + in { + devShells = { + default = let + in + pkgs'.mkShell { + nativeBuildInputs = with pkgs'; [ + script-run-tests + script-run-extended-tests + script-run-ci-tests + script-check-code + script-build-cover-report + script-task + import-gitlab-commit + + alejandra + blackbox + blackbox-terminal + coreutils-full + delve + dialog + drill + fd + feh + gcc12 + gdlv + git + glab + gnugrep + gnumake + gnused + go + go-licenses + golangci-lint + gosec + gum + jq + niv + libffi + logrotate + meld + memcached + netcat + ranger + unixtools.xxd + unzip + util-linux + vhs + wget + zlib + ]; + shellHook = '' + echo "Welcome to your development environment." + ''; + }; + }; + }); +} diff --git a/go.mod b/go.mod index 2164807..d586c3e 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( gorm.io/driver/mysql v1.5.6 gorm.io/driver/sqlite v1.5.5 gorm.io/gorm v1.25.9 + gotest.tools/v3 v3.5.1 ) require ( @@ -30,6 +31,7 @@ require ( github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/kr/fs v0.1.0 // indirect @@ -52,5 +54,4 @@ require ( golang.org/x/sys v0.19.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.6.0 // indirect - gotest.tools/v3 v3.5.1 // indirect ) diff --git a/go.sum b/go.sum index 8821dbc..c8d7124 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= @@ -29,6 +31,7 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -45,7 +48,9 @@ github.com/lufia/plan9stats v0.0.0-20240408141607-282e7b5d6b74 h1:1KuuSOy4ZNgW0K github.com/lufia/plan9stats v0.0.0-20240408141607-282e7b5d6b74/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -66,6 +71,7 @@ github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhV github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -87,6 +93,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= @@ -116,6 +124,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -134,10 +144,13 @@ golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -150,6 +163,7 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= @@ -159,8 +173,7 @@ gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkD gorm.io/driver/sqlite v1.5.5 h1:7MDMtUZhV065SilG62E0MquljeArQZNfJnjd9i9gx3E= gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE= gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= -gorm.io/gorm v1.25.8 h1:WAGEZ/aEcznN4D03laj8DKnehe1e9gYQAjW8xyPRdeo= -gorm.io/gorm v1.25.8/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8= gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/job-generic.go b/job-generic.go index 79c5f57..3a2efc3 100644 --- a/job-generic.go +++ b/job-generic.go @@ -10,7 +10,7 @@ import ( type GenericJob interface { GetID() JobID - + GetDependencies() []JobID GetPriority() Priority diff --git a/job-syncer.go b/job-syncer.go index 250705b..c7349ca 100644 --- a/job-syncer.go +++ b/job-syncer.go @@ -56,7 +56,7 @@ func (js *JobSyncer) Wait(timeout time.Duration) error { } } -func (js *JobSyncer) Sync(job GenericJob) { +func (js *JobSyncer) Sync(job GenericJob) error { js.mu.Lock() defer js.mu.Unlock() @@ -70,6 +70,8 @@ func (js *JobSyncer) Sync(job GenericJob) { } }() + return nil + } func (js *JobSyncer) LastError() error { diff --git a/job.go b/job.go index 262cdc5..b24f4c4 100644 --- a/job.go +++ b/job.go @@ -119,7 +119,7 @@ func (j *Job[T]) GetPersistence() JobPersistence { job.Stats.JobID = job.ID - for i, _ := range job.Logs { + for i := range job.Logs { job.Logs[i].JobID = job.ID } diff --git a/logger.go b/logger.go index 9fe6a9a..b641e35 100644 --- a/logger.go +++ b/logger.go @@ -101,7 +101,7 @@ func Trace(msg string, keysAndValues ...interface{}) { type ZapAdapter struct { logger *zap.Logger - mu sync.Mutex + // mu sync.Mutex } func NewZapAdapter(logger *zap.Logger) *ZapAdapter { diff --git a/manager.go b/manager.go index cc5f5d1..405d327 100644 --- a/manager.go +++ b/manager.go @@ -137,6 +137,11 @@ func (m *Manager) GetActiveJobs() map[JobID]GenericJob { // DeleteJob removes a job from the active jobs and the database func (m *Manager) DeleteJob(id JobID) error { + + if m == nil { + return ErrManagerNotInitialized + } + m.mu.Lock() defer m.mu.Unlock() @@ -153,36 +158,54 @@ func (m *Manager) DeleteJob(id JobID) error { } if m.jobSyncer != nil { - err := m.jobSyncer.DeleteJob(job) - if err != nil { - return err - } + return m.jobSyncer.DeleteJob(job) } return nil } -func (m *Manager) WaitSync() { +func (m *Manager) WaitSync() error { + + if m == nil { + return ErrManagerNotInitialized + } + m.mu.Lock() defer m.mu.Unlock() if m.jobSyncer != nil { - _ = m.jobSyncer.Wait(2 * time.Second) + return m.jobSyncer.Wait(2 * time.Second) } + + return nil + } -func (m *Manager) Sync(job GenericJob) { +func (m *Manager) Sync(job GenericJob) error { + + if m == nil { + return ErrManagerNotInitialized + } + m.mu.Lock() defer m.mu.Unlock() if m.jobSyncer != nil { - m.jobSyncer.Sync(job) + return m.jobSyncer.Sync(job) } + + return nil + } // RemoveJob removes a job from the active jobs // If you want to remove a job from the active jobs and the database, use DeleteJob instead func (m *Manager) RemoveJob(id JobID) error { + + if m == nil { + return ErrManagerNotInitialized + } + m.mu.Lock() defer m.mu.Unlock() @@ -195,6 +218,11 @@ func (m *Manager) RemoveJob(id JobID) error { // ResetJobLogs deletes the logs of a job func (m *Manager) ResetJobLogs(id JobID) error { + + if m == nil { + return ErrManagerNotInitialized + } + m.mu.Lock() defer m.mu.Unlock() @@ -215,6 +243,11 @@ func (m *Manager) ResetJobLogs(id JobID) error { // ResetJobStats deletes the stats of a job func (m *Manager) ResetJobStats(id JobID) error { + + if m == nil { + return ErrManagerNotInitialized + } + m.mu.Lock() defer m.mu.Unlock() @@ -250,6 +283,10 @@ func cancelSchedulerByManager(scheduler CancelScheduler, id JobID) error { func (m *Manager) removeJobInternal(id JobID) error { + if m == nil { + return ErrManagerNotInitialized + } + scheduler := m.activeJobs[id].GetScheduler() if scheduler == nil { return ErrJobNotScheduled @@ -270,6 +307,11 @@ func (m *Manager) removeJobInternal(id JobID) error { } func (m *Manager) UpdateJob(job GenericJob) error { + + if m == nil { + return ErrManagerNotInitialized + } + m.mu.Lock() defer m.mu.Unlock() @@ -318,6 +360,10 @@ func (m *Manager) GetDB() *gorm.DB { // GetQueue returns the queue func (m *Manager) checkAndSetRunningState() error { + if m == nil { + return ErrManagerNotInitialized + } + m.state = ManagerStateStopped if m.workerMap == nil { @@ -340,6 +386,11 @@ func (m *Manager) checkAndSetRunningState() error { // AddWorker adds a worker to the manager func (m *Manager) AddWorker(worker Worker) error { + + if m == nil { + return ErrManagerNotInitialized + } + m.mu.Lock() defer m.mu.Unlock() @@ -369,6 +420,11 @@ func (m *Manager) AddWorker(worker Worker) error { // RemoveWorker removes a worker from the manager func (m *Manager) RemoveWorker(worker Worker) error { + + if m == nil { + return ErrManagerNotInitialized + } + m.mu.Lock() defer m.mu.Unlock() @@ -400,6 +456,10 @@ func (m *Manager) RemoveWorker(worker Worker) error { // Start starts the manager func (m *Manager) Start() error { + if m == nil { + return ErrManagerNotInitialized + } + m.mu.Lock() defer m.mu.Unlock() @@ -575,7 +635,7 @@ func (m *Manager) ScheduleJob(job GenericJob, scheduler Scheduler) error { m.activeJobs[job.GetID()] = job if m.jobSyncer != nil { - m.jobSyncer.Sync(job) + return m.jobSyncer.Sync(job) } return nil @@ -656,7 +716,7 @@ func (m *Manager) handleJobEvents() { } } - if assigned == true { + if assigned { break } diff --git a/nix/scripts/build-cover-report.nix b/nix/scripts/build-cover-report.nix new file mode 100644 index 0000000..80d8863 --- /dev/null +++ b/nix/scripts/build-cover-report.nix @@ -0,0 +1,45 @@ +{ pkgs, lib, ... }: +let + common = pkgs.callPackage ./common.nix {}; + + # Definieren eines schreibbaren Verzeichnisses + writableDir = pkgs.stdenv.mkDerivation { + name = "cover-report"; + buildCommand = '' + mkdir -p $out + ''; + }; + +in + pkgs.writeShellScriptBin "build-cover-report" '' + ${common} + + echo_header "Building cover report" + + download_test_images + setup_go_env + + echo_section "Building" + ${pkgs.go}/bin/go test -v -coverprofile=${writableDir}/coverage.out ./... + if [ $? -ne 0 ]; + then + echo_fail "Failed to run tests" + exit 1 + fi + + if ! ${pkgs.go}/bin/go tool cover -html=${writableDir}/coverage.out -o ${writableDir}/coverage.html + then + echo_fail "Failed to generate coverage report" + exit 1 + fi + echo_ok "Coverage report stored at ${writableDir}" + + echo_step "Opening coverage report in browser" + if ! ${pkgs.xdg-utils}/bin/xdg-open ${writableDir}/coverage.html > /dev/null 2>&1 + then + echo_fail "Failed to open coverage report in browser" + exit 1 + fi + + echo_ok "Report opened in browser" + '' diff --git a/nix/scripts/check-code.nix b/nix/scripts/check-code.nix new file mode 100644 index 0000000..2ee36b1 --- /dev/null +++ b/nix/scripts/check-code.nix @@ -0,0 +1,51 @@ +{ + pkgs, + lib, + ... +}: let + common = pkgs.callPackage ./common.nix {}; +in + pkgs.writeShellScriptBin "check-code" '' + + ${common} + + echo_header "Checking code" + cd_working_dir + + echo_step "Running go vet" + if ! ${pkgs.go}/bin/go vet . + then + echo_fail "go vet failed" + exit 1 + fi + + echo_step "Running go fmt" + if ! ${pkgs.go}/bin/go fmt . + then + echo_fail "go fmt failed" + exit 1 + fi + + echo_step "Running go mod tidy" + if ! ${pkgs.go}/bin/go mod tidy + then + echo_fail "go mod tidy failed" + exit 1 + fi + + echo_step "Running lint" + if ! ${pkgs.golangci-lint}/bin/golangci-lint run . + then + echo_fail "lint failed" + exit 1 + fi + + echo_step "Running gosec" + if ! ${pkgs.gosec}/bin/gosec . + then + echo_fail "gosec failed" + exit 1 + fi + + + '' diff --git a/nix/scripts/common.nix b/nix/scripts/common.nix new file mode 100644 index 0000000..93e91f4 --- /dev/null +++ b/nix/scripts/common.nix @@ -0,0 +1,144 @@ +{pkgs, ...}: '' + + if [ -t 1 ]; then + RED='\033[0;31m' + GREEN='\033[0;32m' + BLUE='\033[0;34m' + RESET='\033[0m' + BOLD='\033[1m' + else + RED="" + GREEN="" + BLUE="" + RESET="" + fi + + ## this function is used to change the working directory to the one specified in + ## the USER_WORKING_DIR environment variable. this is necessary if you want to edit + ## files in the repository. + cd_working_dir() { + + working_dir=$(echo $USER_WORKING_DIR) + if [ -z "$working_dir" ]; then + echo_fail "USER_WORKING_DIR is not set" + echo_hint "Please set the USER_WORKING_DIR environment variable" + exit 1 + fi + + if [ ! -d "$working_dir" ]; then + echo_fail "USER_WORKING_DIR does not exist" + echo_hint "Please set the USER_WORKING_DIR environment variable to a valid directory" + exit 1 + fi + + cd $working_dir + git_root=$(git rev-parse --show-toplevel) + + if [ -z "$git_root" ]; then + echo_fail "Not a git repository" + echo_hint "Please run this script in a git repository" + exit 1 + fi + + cd $git_root + + echo_ok "Changed directory to $working_dir" + } + + is_true() { + val="$1" + if [ "$val" = 'true' ] || [ "$val" = '1' ]; then + return 0 + else + return 1 + fi + } + + echo_header() { + ${pkgs.figlet}/bin/figlet -t -f doom -l "$1" + } + + echo_ok() { + echo -e "$GREEN✔$RESET $1" + } + + echo_delimiter() { + echo " " + } + + echo_section() { + echo -e "\n\n$BOLD$1$RESET" + } + + echo_text() { + echo -e "$1" + } + + echo_fail() { + echo -e "$RED✖ $1$RESET" + } + + echo_hint() { + echo -e "$BLUE→ $1$RESET" + } + + echo_step() { + echo -e "$BLUE•$RESET $1" + } + + convert_multiline_for_nix() { + printf "%s" " + }$1" | ${pkgs.gnused}/bin/sed 's/\\/\\\\/g; s/"/\\"/g; s/$/\\n/g' | tr -d '\n' + } + + if [ -z "$DEBUG_MODE" ]; then + DEBUG_MODE='false' + fi + + if [ -n "$CI_JOB_TOKEN" ]; then + CI_MODE='true' + fi + + if is_true "$DEBUG_MODE" || is_true "$CI_MODE"; then + set -x + fi + + download_test_images() { + + echo_step "Downloading docker images" + + if ! ${pkgs.docker}/bin/docker images | grep atmoz/sftp | grep alpine + then + echo_step "Downloading atmoz/sftp:alpine" + if ! ${pkgs.docker}/bin/docker pull atmoz/sftp:alpine + then + echo_fail "Failed to download atmoz/sftp:alpine" + exit 1 + fi + fi + + if ! ${pkgs.docker}/bin/docker images | grep axllent/mailpit + then + echo_step "Downloading atmoz/sftp:alpine" + if ! ${pkgs.docker}/bin/docker pull axllent/mailpit + then + echo_fail "Failed to download axllent/mailpit" + exit 1 + fi + fi + + } + + setup_go_env() { + echo_step "Changing directory to ${../..}" + cd ${../..} + + echo_step "Setting GO111MODULE=auto" + if ! ${pkgs.go}/bin/go env -w GO111MODULE=auto + then + echo_fail "Failed to set GO111MODULE=auto" + exit 1 + fi + } + +'' diff --git a/nix/scripts/go-task.nix b/nix/scripts/go-task.nix new file mode 100644 index 0000000..b0f8cad --- /dev/null +++ b/nix/scripts/go-task.nix @@ -0,0 +1,43 @@ +{ + pkgs, +}: let + taskfile = builtins.toFile "taskfile.yml" '' + version: '3' + + tasks: + default: + cmds: + - task --list + silent: true + + run-tests: + desc: Execute all tests. + env: + TEST_BY_TASK: true + cmds: + - run-tests + run-extended-tests: + desc: Execute all tests including cover, bench and race tests. + env: + TEST_BY_TASK: true + cmds: + - run-extended-tests + build-cover-report: + desc: Build coverage report. + aliases: + - cr + env: + TEST_BY_TASK: true + cmds: + - build-cover-report + check-code: + desc: Check code style, linting, and formatting. + env: + USER_WORKING_DIR: "{{.USER_WORKING_DIR}}" + cmds: + - check-code + ''; +in + pkgs.writeShellScriptBin "task" '' + ${pkgs.go-task}/bin/task -t "${taskfile}" "$@" + '' diff --git a/nix/scripts/run-ci-tests.nix b/nix/scripts/run-ci-tests.nix new file mode 100644 index 0000000..2a73fba --- /dev/null +++ b/nix/scripts/run-ci-tests.nix @@ -0,0 +1,38 @@ +{ + pkgs, + lib, + ... +}: let + common = pkgs.callPackage ./common.nix {}; +in + pkgs.writeShellScriptBin "run-ci-tests" '' + + ${common} + + echo_header "Running CI tests" + + download_test_images + setup_go_env + + echo_section "Running tests" + if ! ${pkgs.go}/bin/go test -tags "runOnTask" -cover ./... + then + echo_fail "Failed to run tests" + exit 1 + fi + + echo_section "Running tests" + if ! ${pkgs.go}/bin/go test -tags "runOnTask,bench" -bench ./... + then + echo_fail "Failed to run benchmarks" + exit 1 + fi + + echo_section "Running tests" + if ! ${pkgs.go}/bin/go test -tags "runOnTask,race" -race ./... + then + echo_fail "Failed to run race tests" + exit 1 + fi + + '' diff --git a/nix/scripts/run-extended-tests.nix b/nix/scripts/run-extended-tests.nix new file mode 100644 index 0000000..53b0ac9 --- /dev/null +++ b/nix/scripts/run-extended-tests.nix @@ -0,0 +1,40 @@ +{ + pkgs, + lib, + ... +}: let + common = pkgs.callPackage ./common.nix {}; +in + pkgs.writeShellScriptBin "run-extended-tests" '' + + ${common} + + echo_header "Running tests" + echo_step "Downloading docker images" + + download_test_images + setup_go_env + + echo_section "Running tests" + if ! ${pkgs.go}/bin/go test -tags "runOnTask" -cover ./... + then + echo_fail "Failed to run tests" + exit 1 + fi + + echo_section "Running tests" + if ! ${pkgs.go}/bin/go test -tags "runOnTask,bench" -bench ./... + then + echo_fail "Failed to run benchmarks" + exit 1 + fi + + echo_section "Running tests" + if ! ${pkgs.go}/bin/go test -tags "runOnTask,race" -race ./... + then + echo_fail "Failed to run race tests" + exit 1 + fi + + + '' diff --git a/nix/scripts/run-tests.nix b/nix/scripts/run-tests.nix new file mode 100644 index 0000000..5c79288 --- /dev/null +++ b/nix/scripts/run-tests.nix @@ -0,0 +1,66 @@ +{ + pkgs, + lib, + ... +}: let + common = pkgs.callPackage ./common.nix {}; +in + pkgs.writeShellScriptBin "run-tests" '' + + ${common} + + echo_header "Running tests" + + + selection=$(${pkgs.gum}/bin/gum choose "run specific test" "run all tests" "Cancel") + + if [[ "$selection" == "Cancel" ]]; then + echo_ok "Exiting." + exit 0 + fi + + download_test_images + setup_go_env + + if [[ "$selection" == "run all tests" ]]; then + echo_ok "Running all tests" + if ! ${pkgs.go}/bin/go test -v -failfast ./... + then + echo_fail "ERROR: Tests failed, check your Go!" + exit 1 + fi + echo_ok "All tests passed!" + exit 0 + fi + + test_files=$(${pkgs.findutils}/bin/find . -name "*_test.go") + + test_names="" + for file in $test_files; do + names=$(${pkgs.gnugrep}/bin/grep -oP 'func (Test\w+)' $file | ${pkgs.gawk}/bin/gawk '{print $2}') + test_names+="$names " + done + + if [[ -z "$test_names" ]]; then + echo_fail "No tests found!" + exit 1 + fi + + selected_tests=$(echo "$test_names" | ${pkgs.coreutils}/bin/tr ' ' '\n' | ${pkgs.gum}/bin/gum filter --no-limit ) + + if [[ -z "$selected_tests" ]]; then + echo_ok "No tests selected, exiting." + exit 0 + fi + + + if ! ${pkgs.go}/bin/go test -run "$(echo $selected_tests | tr '\n' "")" + then + echo_fail "ERROR: Tests failed, check your Go!" + exit 1 + fi + + echo_ok "All tests passed!" + + + '' diff --git a/queue.go b/queue.go index 4415df6..7bf6a35 100644 --- a/queue.go +++ b/queue.go @@ -86,9 +86,7 @@ func (q *Queue) Enqueue(job GenericJob) error { // Run topological sort on jobs in the ready queue readyJobList := []GenericJob{} - for _, readyJob := range q.readyQueue { - readyJobList = append(readyJobList, readyJob) - } + readyJobList = append(readyJobList, q.readyQueue...) currentReadyJobIDs := make(map[JobID]struct{}) for _, job := range readyJobList { @@ -96,9 +94,7 @@ func (q *Queue) Enqueue(job GenericJob) error { } var fullJobList []GenericJob - for _, job := range readyJobList { - fullJobList = append(fullJobList, job) - } + fullJobList = append(fullJobList, readyJobList...) for i := range q.processedJobs { id := q.processedJobs[i].ID @@ -154,7 +150,7 @@ func (q *Queue) ClearProcessedJobs() { } } -func (q *Queue) isDependency(id JobID) bool { +func (q *Queue) IsDependency(id JobID) bool { for _, deps := range q.pendingDependencies { for _, depID := range deps { if depID == id { diff --git a/runnable-fileoperation.go b/runnable-fileoperation.go index 333b8b2..d7eb1bf 100644 --- a/runnable-fileoperation.go +++ b/runnable-fileoperation.go @@ -43,7 +43,7 @@ func (f *FileOperationResult) GetResult() string { } func (f *FileOperationResult) GetError() (string, int) { - if f.Success == false { + if !f.Success { return "FileOperationResult failed", 1 } return "", 0 diff --git a/runnable-mail_test.go b/runnable-mail_test.go index c87f279..39208af 100644 --- a/runnable-mail_test.go +++ b/runnable-mail_test.go @@ -78,7 +78,8 @@ func startTestSMTPDockerImageAndContainer(t *testing.T, port string, ctx context Timeout: &timeout, Signal: "SIGKILL", } - newCtx, _ := context.WithTimeout(context.Background(), 60*time.Second) + newCtx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() if err := cli.ContainerStop(newCtx, resp.ID, stopOptions); err != nil { t.Errorf("ContainerStop returned error: %v", err) } diff --git a/runnable-sftp_test.go b/runnable-sftp_test.go index 2cb82dc..2e047c3 100644 --- a/runnable-sftp_test.go +++ b/runnable-sftp_test.go @@ -78,7 +78,10 @@ func startSFTPTestDockerImageAndContainer(t *testing.T, host string, port string Timeout: &timeout, Signal: "SIGKILL", } - newCtx, _ := context.WithTimeout(context.Background(), 60*time.Second) + + newCtx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + if err := cli.ContainerStop(newCtx, resp.ID, stopOptions); err != nil { t.Errorf("ContainerStop returned error: %v", err) } diff --git a/schedule-time.go b/schedule-time.go index f04c32d..0cca797 100644 --- a/schedule-time.go +++ b/schedule-time.go @@ -4,6 +4,7 @@ package jobqueue import ( + "errors" "fmt" "time" ) @@ -16,12 +17,17 @@ type TimeScheduler struct { } func (s *TimeScheduler) Schedule(job GenericJob, eventBus *EventBus) error { + + if job == nil { + return ErrParameterIsNil + } + if s.executed { return fmt.Errorf("%w: job %s already scheduled", ErrJobAlreadyScheduled, job.GetID()) } if s.Time.Before(time.Now()) { - return fmt.Errorf("%w: scheduled time is in the past", ErrInvalidTime) + return errors.Join(ErrScheduleTimeIsInThePast, ErrInvalidTime, fmt.Errorf("time: %s", s.Time)) } if s.jobs == nil { @@ -29,6 +35,10 @@ func (s *TimeScheduler) Schedule(job GenericJob, eventBus *EventBus) error { } id := job.GetID() + if id == "" { + return ErrJobIDEmpty + } + if _, ok := s.jobs[id]; ok { return fmt.Errorf("%w: job %s already scheduled", ErrJobAlreadyScheduled, id) } @@ -36,7 +46,7 @@ func (s *TimeScheduler) Schedule(job GenericJob, eventBus *EventBus) error { stopChan := make(StopChan) s.jobs[id] = stopChan - timer := time.NewTimer(s.Time.Sub(time.Now())) + timer := time.NewTimer(time.Until(s.Time)) go func() { select { diff --git a/schedule-time_test.go b/schedule-time_test.go new file mode 100644 index 0000000..635008d --- /dev/null +++ b/schedule-time_test.go @@ -0,0 +1,39 @@ +package jobqueue + +import ( + "gotest.tools/v3/assert" + "testing" + "time" +) + +func TestStructure(t *testing.T) { + + now := time.Now() + oneHourBefore := now.Add(-1 * time.Hour) + onHourAfter := now.Add(1 * time.Hour) + + ts := TimeScheduler{ + Time: oneHourBefore, + } + + err := ts.Schedule(nil, nil) + assert.ErrorIs(t, err, ErrParameterIsNil) + + job := &MockGenericJob{} + err = ts.Schedule(job, nil) + assert.ErrorIs(t, err, ErrScheduleTimeIsInThePast) + + ts.Time = onHourAfter + err = ts.Schedule(job, nil) + assert.ErrorIs(t, err, ErrJobIDEmpty) + + job.ID = "job-id" + err = ts.Schedule(job, nil) + assert.NilError(t, err) + time.Sleep(2 * time.Second) + err = ts.Cancel("job-id") + assert.NilError(t, err) + + //time.Sleep(200 * time.Second) + +} diff --git a/scheduler-inotify.go b/scheduler-inotify.go index e605dbf..2585f83 100644 --- a/scheduler-inotify.go +++ b/scheduler-inotify.go @@ -62,7 +62,7 @@ func (s *InotifyScheduler) Schedule(job GenericJob, eventBus *EventBus) error { } } - case _, _ = <-watcher.Errors: + case <-watcher.Errors: case <-stopChan: _ = watcher.Close() diff --git a/stat.go b/stat.go index 2179936..eb303cd 100644 --- a/stat.go +++ b/stat.go @@ -26,11 +26,11 @@ func StopResourceMonitoring() { } } -func resetResourceStatsForTesting() { - if mainResourceStats != nil { - StopResourceMonitoring() - } -} +//func resetResourceStatsForTesting() { +// if mainResourceStats != nil { +// StopResourceMonitoring() +// } +//} func GetCpuUsage() float64 { diff --git a/worker.go b/worker.go index c0a70de..604df3e 100644 --- a/worker.go +++ b/worker.go @@ -1,6 +1,8 @@ // Copyright 2023 schukai GmbH // SPDX-License-Identifier: AGPL-3.0 +// #nosec + package jobqueue import ( @@ -241,7 +243,7 @@ func (w *LocalWorker) run(jobChannel chan GenericJob, stopChan chan bool, cancel w.mu.Lock() defer w.mu.Unlock() if w.manager != nil { - w.manager.Sync(job) + _ = w.manager.Sync(job) } }() -- GitLab