{"id":18320884,"url":"https://github.com/bazaarvoice/super-simple-workflow","last_synced_at":"2026-01-24T15:07:02.435Z","repository":{"id":35964550,"uuid":"40254895","full_name":"bazaarvoice/super-simple-workflow","owner":"bazaarvoice","description":null,"archived":false,"fork":false,"pushed_at":"2018-03-02T13:07:55.000Z","size":1237,"stargazers_count":0,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-14T00:48:48.774Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bazaarvoice.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-05T16:01:08.000Z","updated_at":"2025-01-16T09:26:24.000Z","dependencies_parsed_at":"2022-09-10T21:01:48.509Z","dependency_job_id":null,"html_url":"https://github.com/bazaarvoice/super-simple-workflow","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/bazaarvoice/super-simple-workflow","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bazaarvoice%2Fsuper-simple-workflow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bazaarvoice%2Fsuper-simple-workflow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bazaarvoice%2Fsuper-simple-workflow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bazaarvoice%2Fsuper-simple-workflow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bazaarvoice","download_url":"https://codeload.github.com/bazaarvoice/super-simple-workflow/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bazaarvoice%2Fsuper-simple-workflow/sbom","scorecard":{"id":227557,"data":{"date":"2025-08-11","repo":{"name":"github.com/bazaarvoice/super-simple-workflow","commit":"3974ed181201cea424368474c236ff58a4bd0573"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 2/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 2 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T04:07:03.660Z","repository_id":35964550,"created_at":"2025-08-17T04:07:03.660Z","updated_at":"2025-08-17T04:07:03.660Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28730309,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T10:24:43.181Z","status":"ssl_error","status_checked_at":"2026-01-24T10:24:36.112Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T18:17:45.519Z","updated_at":"2026-01-24T15:07:02.419Z","avatar_url":"https://github.com/bazaarvoice.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Join the chat at https://gitter.im/super-simple-workflow/Lobby](https://badges.gitter.im/super-simple-workflow/Lobby.svg)](https://gitter.im/super-simple-workflow/Lobby?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n[![Build Status](https://travis-ci.org/bazaarvoice/super-simple-workflow.svg?branch=master)](https://travis-ci.org/bazaarvoice/super-simple-workflow)\n\nSimple Workflow is not simple. Let's really simplify it!\n\nFor a nice intro, check out the [blog post](http://blog.vvcephei.org/super-simple-workflow).\n\nGetting Started\n===============\n\nHere's how it works:\n\n1. Define an `InputParser` class that tells sswf how to serialize your workflow input.\n2. Define an Enum capturing all the potential steps of your workflow (extending `WorkflowStep`). These contain metadata about timeouts, etc.\n3. Define a `WorkflowDefinition` class:\n    * The `workflow` method returns a list of steps to execute. You get to look at the workflow input, but not the history. \n      The idea is that you define a workflow that's easy to predict and consists of a series of steps to completion.\n    * The `act` method specifies the behaviour for each step.\n4. Register and start your workflow using the `WorkflowManagement` class\n\nOne big thing that sticks out here is that your workflow is just a sequence of steps. There's no branching or conditional execution of steps.\nIn our experience, most workflows wind up being almost, if not entirely, linear. Deciding to just support that use case means that we can make it\ndrop-dead simple.\n\nIf you're thinking that you need branching because some states don't need to execute sometimes, you can achieve the same effect by just having\nthose states say `Success(\"Nothing to do!\")`. You would only really need branching if you wanted to do one of two totally different things based on the \nresult of some step.\n\nWorking example\n---------------\n\nRun the example with `sbt example/run` or through IDEA by running `ExampleWorkflowService`.\nNote that you must have AWS credentials in your env: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_KEY`.\n\nYour AWS credentials must have access to at least the following [SWF actions](http://docs.aws.amazon.com/amazonswf/latest/developerguide/swf-api-by-category.html):\n\n- PollForActivityTask\n- RespondActivityTaskCompleted\n- RecordActivityTaskHeartbeat\n- PollForDecisionTask\n- RespondDecisionTaskCompleted\n- RequestCancelWorkflowExecution\n- StartWorkflowExecution\n- SignalWorkflowExecution\n- TerminateWorkflowExecution\n- RegisterActivityTypef\n- RegisterWorkflowType\n- RegisterDomain\n- RequestCancelWorkflowExecution\n- TerminateWorkflowExecution\n- ListActivityTypes\n- DescribeWorkflowType\n- ListOpenWorkflowExecutions\n- ListClosedWorkflowExecutions\n- GetWorkflowExecutionHistory\n- DescribeDomain\n\nThe example code is in `sswf-java-example/src/main/java/example`. This is everything you'll need to do to get up and running!\n\n\nManaging Versions and Names of Things\n---------------------------\n\nWhen you're dealing with SSWF, you have to contend with domains, workflows, task lists, steps, and versions of workflows and steps.\nSo, what's the right way to think about and use these things?\n\n* A *Domain* is just a handy way to group workflows. You probably just want one domain per project, even if your project has several workflows.\n\n* A *Workflow* is the logical high-level task you're trying to accomplish. So, if you have an ETL job to do, that's your workflow. You may start out with\n  3 steps and then add more later, but it's still the same workflow.\n\n* But if you add more steps, then the old workflow workers (who were compiled against the 3-step version) won't have a clue what to do with the new steps\n  (read: `IllegalStateException`). This is where the `Workflow Version` comes in. Each worker is polling SWF for a specific version of the workflow, so \n  as long as you bump the version whenever you change the workflow, you'll be golden.\n\n* The *Steps* are the (ahem) individual steps of the workflow. They are really just messages that the sswf workers will use to invoke your `WorkflowDefinition#act` method.\n  We could use strings, but you define them in an enum so there is a clear symbolic way to reference them in code. They also contain a small amount of configuration,\n  like how long sswf should let the step run before timing it out.\n  \n* There are also *Task Lists*, which let you restrict workflow executions to particular environments. For example, you may have different data centers \n  (like in the US and the EU), with different data in each data center. Let's say there's a particular workflow to run on new data being put into a datacenter. \n  If new data is added to the EU center, you don't want the US worker picking up parts of the workflow. So, you'll have two task lists: one for the US and one for the EU.\n  This can also be useful for confining workflow executions to dev, test, or prod environments.\n\n\nWriting Steps\n--------------\n\nEvery time a step executes, it returns one of three results: Success, Failure, or InProgress. They can all contain\nmessages for reporting later.\n\nThe point here is simplicity. Make each Step idempotent, so if a Step takes an action and needs to wait for completion,\nmake the Step check for completion _first_, returning one of the three results, and _then_ evaluate if the step needs\nto execute. If so, execute it and return InProgress so the workflow will call the Step again.\n\nThis way, each step enforces an invariant rather than performing an action. You will have the comfort of knowing that\nit's always safe to re-start a workflow, since anything that doesn't need to run will simply pass through and anything\nin progress will wait for completion.\n\nExample:\n        \n        ExtractStep:\n          - extractState := getExtractState()\n          - if extractState.defined \u0026\u0026 extractState.isRunning:\n              return new InProgress(\"EXTRACT is running: \" + extractState.status)\n          - if extractState.defined \u0026\u0026 extractState.isFailed:\n              return new Failure(\"EXTRACT failed: \" + extractState.errorMessage)\n          - if extractState.defined \u0026\u0026 extractState.isComplete:\n              return new Success(\"EXTRACT done: \" + extractState.summary)\n\n          - needsExtract := decideWhetherWeNeedAnExtract():\n          - if needsExtract:\n              startExtract()\n              return new InProgress(\"Started EXTRACT\")\n          - else:\n              return new Success(\"Nothing to do!\")\n\n          - in case of any error:\n              return new Failure(\"Unexpected error: \" + error.message)\n              \nNotice how the ExtractStep code will always do its job without corrupting the system no matter how many times it's called\nand independent of whatever else has happened. This gives you the power to run, or re-run, the workflow any time\nand however often you like without worrying that it will do the wrong thing.\n\nWaiting on Signals\n------------------\n\nSometimes, you ned a workflow to wait for some other system (or person) to complete an action. You can accomplish\nthis by creating a signal, passing it to that other party, and then they can give it back to you when they are done.\n\nThe first step in using signals is to make a signal token by calling `WorkflowManagement#generateSignal()`. \nThis gives you back a token you can wait on and which you can also use to send a signal.\nYou will pass these signals on to the process that you intend to signal you. \n\nA workflow step can wait on one or more of these signals by returning `new Wait(WAIT_TIMEOUT,SIGNAL_TOKEN)`.\n\nThe most convenient way to send the signal is implemented in `WorkflowManagement#signalWorkflow(SIGNAL_TOKEN)`.\nYou could, for example, set up a web endpoint at `POST http://myservice/signal/{SIGNAL_TOKEN}`, which\ndelegates to `signalWorkflow(SIGNAL_TOKEN)`.\n\nThe example code provides a working (if somewhat contrived) signalling example: in [the load step](https://github.com/bazaarvoice/super-simple-workflow/blob/master/sswf-java-example/src/main/java/example/ExampleWorkflowDefinition.java#L104). In practice, instead of directly passing the signal to `exampleSignalHandler`, you would send it out to another system, and that system would send it to your signal handler upon task completion.\n\nIf sending the signal from a JVM process is inconvenient, you can extract the workflowId, runId, and signalName\nfrom the token and just use the [SWF Signal API](http://docs.aws.amazon.com/amazonswf/latest/developerguide/swf-dg-signals.html)\ndirectly. Here is the format of the tokens generated by `generateSignal()` (pipe delimited):\n\n    WORKFLOW_ID|RUN_ID|SIGNAL_NAME\n    \nTo send a signal, that is all the information you need. The `input` field\nof AWS signals is currently unused.\n\nDevelopment\n===========\n\nset up your access to the BV maven repo:\n--------------------\n\n1. For starters, install sbt.\n1. Create a file ```~/.sbt/repositories```:\n\n    ```\n    [repositories]\n      local\n      bazaarvoice: https://repo.bazaarvoice.com:443/nexus/content/groups/bazaarvoice\n    ```\n    \n1. Create a file ```~/.sbt/.credentials```:\n\n    ```\n    realm:Sonatype Nexus Repository Manager\n    host:repo.bazaarvoice.com\n    user:LDAP USERNAME\n    password:LDAP PASSWORD\n    ```\n\nWorking with IDEA\n--------------------\n\nThe built-in scala and idea support should do you just fine.\n\nbuild the project:\n--------------------\n\n```\nsbt compile\n# to run samples\nsbt example/run \n# execute unit, integration, and end-to-end tests\nsbt test-all\n# to package\nsbt publishLocal #(etc...)\n```\n\nProtip: Use a tilde (`sbt ~test`) to have sbt monitor the files and re-execute the task when anything changes.\n\n\nTo cross-build for scala 2.10 and scala 2.11 (note the '+'):\n\n```\nsbt +compile\n# to package\nsbt +publishLocal #(etc...)\n```\n\nperforming a release\n--------------------\n\nWe have a (private) jenkins job to do releases. It's `super-simple-workflow-release`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbazaarvoice%2Fsuper-simple-workflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbazaarvoice%2Fsuper-simple-workflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbazaarvoice%2Fsuper-simple-workflow/lists"}