{"id":42655740,"url":"https://github.com/TimoKoerber/laravel-one-time-operations","last_synced_at":"2026-02-06T20:00:27.049Z","repository":{"id":142263477,"uuid":"612343287","full_name":"TimoKoerber/laravel-one-time-operations","owner":"TimoKoerber","description":"Run operations once after deployment - just like you do it with migrations!","archived":false,"fork":false,"pushed_at":"2025-02-27T12:12:39.000Z","size":82,"stargazers_count":626,"open_issues_count":18,"forks_count":38,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-10-18T22:41:29.653Z","etag":null,"topics":["cicd","deployment","dispatch","jobs","laravel","laravel-framework","migrations","operations"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TimoKoerber.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-10T18:23:54.000Z","updated_at":"2025-10-15T01:50:09.000Z","dependencies_parsed_at":"2024-04-04T11:46:18.003Z","dependency_job_id":"e82bfdb8-b9f8-468d-82d6-c1273e9fa322","html_url":"https://github.com/TimoKoerber/laravel-one-time-operations","commit_stats":{"total_commits":37,"total_committers":6,"mean_commits":6.166666666666667,"dds":0.2702702702702703,"last_synced_commit":"33292b8606ff51b8bebe2d6f62fe057621e56942"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/TimoKoerber/laravel-one-time-operations","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimoKoerber%2Flaravel-one-time-operations","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimoKoerber%2Flaravel-one-time-operations/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimoKoerber%2Flaravel-one-time-operations/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimoKoerber%2Flaravel-one-time-operations/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TimoKoerber","download_url":"https://codeload.github.com/TimoKoerber/laravel-one-time-operations/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimoKoerber%2Flaravel-one-time-operations/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29174319,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-06T19:56:27.068Z","status":"ssl_error","status_checked_at":"2026-02-06T19:56:18.934Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["cicd","deployment","dispatch","jobs","laravel","laravel-framework","migrations","operations"],"created_at":"2026-01-29T08:00:22.657Z","updated_at":"2026-02-06T20:00:27.002Z","avatar_url":"https://github.com/TimoKoerber.png","language":"PHP","funding_links":[],"categories":["PHP","Frameworks"],"sub_categories":[],"readme":"![One-Time Operations for Laravel](https://user-images.githubusercontent.com/65356688/225704995-ec7f54fb-a5b8-4d73-898f-2ebeed9ee733.jpg)\n# One-Time Operations for Laravel\n\nRun operations once after deployment - just like you do it with migrations!\n\n-----\n\n**Take your CI/CD to the next Level with One-Time Operations for Laravel**! 🚀\n\nCreate specific classes for a one-time usage, that can be executed automatically after each deployment. \nSame as migrations they get processed once and then never again. Perfect for seeding or updating some data instantly after \nsome database changes or feature updates.\n\nThis package is for you if...\n\n- you regularly need to **update specific data** after you deployed new code\n- you often execute jobs just **only one single time** after a deployment\n- you sometimes **forget to execute** that one specific job and stuff gets crazy\n- your code gets **cluttered with jobs**, that are not being used anymore\n- your co-workers always need to be reminded to **execute that one job** after some database changes\n- you often seed or process data **in a migration file** (which is a big no-no!)\n\n\n## Installation\n\nRequire this package with composer:\n\n```shell\ncomposer require timokoerber/laravel-one-time-operations\n```\n\nCreate the required table in your database:\n\n```shell\nphp artisan migrate\n```\n\nNow you're all set!\n\n## Commands\n\n### Create operation files\nCreate new operation file:\n```shell\nphp artisan operations:make \u003coperation_name\u003e\n```\nCreate file without any attributes:\n```shell\nphp artisan operations:make \u003coperation_name\u003e -e|--essential\n```\n\nUse command alias to create operation file:\n```shell\nphp artisan make:operation \u003coperation_name\u003e\n```\n\n### Process operations\n\nProcess all new operation files:\n```shell\nphp artisan operations:process\n```\n\nForce synchronous execution:\n```shell\nphp artisan operations:process --sync\n```\n\nForce asynchronous execution:\n```shell\nphp artisan operations:process --async\n```\n\nTest mode (don't flag operations as processed):\n```shell\nphp artisan operations:process --test\n```\n\nRun command isolated:\n```shell\nphp artisan operations:process --isolated\n```\n\nForce a specific queue for the job:\n```shell\nphp artisan operations:process --queue=\u003cname\u003e\n```\n\nOnly process operations with a specific tag:\n```shell\nphp artisan operations:process --tag=\u003ctagname\u003e\n```\n\nRe-run one specific operation:\n```shell\nphp artisan operations:process \u003coperation_name\u003e\n```\n\n### Show operations\n\nShow all operations:\n```shell\nphp artisan operations:show\n```\n\nShow pending operations:\n```shell\nphp artisan operations:show pending\n```\n\nShow processed operations:\n```shell\nphp artisan operations:show processed\n```\n\nShow disposed operations:\n```shell\nphp artisan operations:show disposed\n```\n\nUse multiple filters to show operations:\n```shell\nphp artisan operations:show pending processed disposed\n```\n\n## Tutorials\n\n### CI/CD \u0026 Deployment-Process\n\nThe *One-Time Operations* work exactly like [Laravel Migrations](https://laravel.com/docs/9.x/migrations). \nJust process the operations *after your code was deployed and the migrations were migrated*. \nYou can make it part of your deployment script like this: \n\n```shell\n...\n - php artisan migrate\n - php artisan operations:process\n...\n```\n\n### Edit config\n\nBy default, the following elements will be created in your project:\n\n- the table `operations` in your database\n- the directory `operations` in your project root directory\n\nIf you want to use a different settings just publish and edit the config file:\n\n```shell\nphp artisan vendor:publish --provider=\"TimoKoerber\\LaravelOneTimeOperations\\Providers\\OneTimeOperationsServiceProvider\"\n```\n\nThis will create the file `config/one-time-operations.php` with the following content.\n\n```php\n// config/one-time-operation.php\n\nreturn [\n    'directory' =\u003e 'operations',\n    'table' =\u003e 'operations',\n];\n```\n\nMake changes as you like.\n\n### Create One-Time Operation files\n\n![One-Time Operations for Laravel - Create One-Time Operation files](https://user-images.githubusercontent.com/65356688/224433928-721b1261-b7ad-40c6-a512-d0f5b5fa0cbf.png)\n\n![One-Time Operations for Laravel - Create One-Time Operation files](https://user-images.githubusercontent.com/65356688/224433323-96b23e84-e22e-4333-8749-ae61cc866cd1.png)\n\nTo create a new operation file execute the following command:\n\n```shell\nphp artisan operations:make AwesomeOperation\n```\n\nThis will create a file like `operations/XXXX_XX_XX_XXXXXX_awesome_operation.php` with the following content.\n\n```php\n\u003c?php\n// operations/XXXX_XX_XX_XXXXXX_awesome_operation.php\n\nuse TimoKoerber\\LaravelOneTimeOperations\\OneTimeOperation;\n\nreturn new class extends OneTimeOperation\n{\n    /**\n     * Determine if the operation is being processed asynchronously.\n     */\n    protected bool $async = true;\n    \n    /**\n     * The queue that the job will be dispatched to.\n     */\n    protected string $queue = 'default';\n    \n    /**\n     * A tag name, that this operation can be filtered by.\n     */\n    protected ?string $tag = null;\n\n    /**\n     * Process the operation.\n     */\n    public function process(): void\n    {\n        //\n    }\n};\n\n```\n\nProvide your code in the `process()` method, for example: \n\n```php\n// operations/XXXX_XX_XX_XXXXXX_awesome_operation.php\n\npublic function process(): void\n{\n    User::where('active', 1)-\u003eupdate(['status' =\u003e 'awesome']) // make active users awesome\n}\n```\n\nBy default, the operation is being processed ***asynchronously*** (based on your configuration) by dispatching the job `OneTimeOperationProcessJob`.\nBy default, the operation is being dispatched to the `default` queue of your project. Change the `$queue` as you wish.  \n\nYou can also execute the code synchronously by setting the `$async` flag to `false`.\n_(this is only recommended for small operations, since the processing of these operations should be part of the deployment process)_\n\n**Hint:** If you use synchronous processing, the `$queue` attribute will be ignored (duh!).\n\n### Create a cleaner operation file\n\nIf you don't need all the available attributes for your operation, you can create a *cleaner* operation file with the `--essential` or `-e` option: \n\n```shell\nphp artisan operations:make AwesomeOperation --essential\nphp artisan operations:make AwesomeOperation -e\n```\n\n### Custom operation file\n\nYou can provide a custom class layout in `/stubs/one-time-operation.stub`, which will be used to create a new operation file.  \n\n### Processing the operations\n\n![One-Time Operations for Laravel - Processing the operations](https://user-images.githubusercontent.com/65356688/224434129-43082402-6077-4043-8e97-c44786e60a59.png)\n\nUse the following call to process all new operation files.\n\n```shell\nphp artisan operations:process\n```\n\nYour code will be executed, and you will find all the processed operations in the `operations` table: \n\n| id  | name                                | dispatched | processed_at        | \n|-----|-------------------------------------|------------|---------------------|\n| 1   | XXXX_XX_XX_XXXXXX_awesome_operation | async      | 2015-10-21 07:28:00 |\n\nAfter that, this operation will not be processed anymore.\n\n### Dispatching Jobs synchronously or asynchronously\n\nFor each operation a `OneTimeOperationProcessJob` is being dispatched, \neither with `dispatch()` oder `dispatchSync()` based on the `$async` attribute in the operation file.\n\nBy providing the `--sync` or `--async` option with the `operations:process` command, you can force a synchronously/asynchronously execution and ignore the attribute:\n\n```shell\nphp artisan operations:process --async  // force dispatch()\nphp artisan operations:process --sync   // force dispatchSync()  \n```\n\n**Hint!** If `operation:process` is part of your deployment process, it is **not recommended** to process the operations synchronously,\nsince an error in your operation could make your whole deployment fail. \n\n### Force different queue for all operations \n\nYou can provide the `--queue` option in the artisan call. The given queue will be used for all operations, ignoring the `$queue` attribute in the class.  \n\n```shell\nphp artisan operations:process --queue=redis  // force redis queue \n```\n\n### Run commands isolated on Multi-Server Architecture\n\nIf you work with a Multi-Server Architecture you can use `--isolated` option to make sure to only run one instance of the command ([Laravel Isolatable Commands](https://laravel.com/docs/10.x/artisan#isolatable-commands)). \n\n```shell\nphp artisan operations:process --isolated \n```\n\n### Run only operations with a given tag\n\nYou can provide the `$tag` attribute in your operation file: \n\n```php\n\u003c?php\n// operations/XXXX_XX_XX_XXXXXX_awesome_operation.php\n\n    protected ?string $tag = \"awesome\";\n};\n```\n\nThat way you can filter operations with this specific tag when processing the operations:\n\n```shell\nphp artisan operations:process --tag=awesome  // run only operations with \"awesome\" tag\n```\n\nThis is quite usefull if, for example, you want to process some of your operations before and some after the migrations: \n\n```text\n - php artisan operations:process --tag=before-migrations \n - php artisan migrate\n - php artisan operations:process\n```\n\nYou can also provide multiple tags:\n\n```shell\nphp artisan operations:process --tag=awesome --tag=foobar // run only operations with \"awesome\" or \"foobar\" tag \n```\n\n*Hint!* `operations:process` (without tags) still processes *all* operations, even if they have a tag.\n\n### Re-run an operation\n\n![One-Time Operations for Laravel - Re-run an operation manually](https://user-images.githubusercontent.com/65356688/224440344-3d095730-12c3-4a2c-b4c3-42a8b6d60767.png)\n\nIf something went wrong (or if you just feel like it), you can process an operation again by providing the **name of the operation** as parameter in `operations:process`.\n\n```shell\nphp artisan operations:process XXXX_XX_XX_XXXXXX_awesome_operation\n```\n\n### Testing the operation\n\nYou might want to test your code a couple of times before flagging the operation as \"processed\". Provide the `--test` flag to run the command again and again.\n\n```shell\nphp artisan operations:process --test\n```\n\n### Showing all operations\n\n![One-Time Operations for Laravel - Showing all operations](https://user-images.githubusercontent.com/65356688/224432952-49009531-8946-4d19-8cee-70ca12605038.png)\n\nSo you don't have to check the database or the directory for the existing operations, \nyou can show a list with `operations:show`. \nFilter the list with the available filters `pending`, `processed` and `disposed`. \n\n- `pending` - Operations, that have not been processed yet\n- `processed` - Operations, that have been processed\n- `disposed` - Operations, that have been processed and the files were already deleted\n\n```shell\nphp artisan operations:show pending           // show only pending operations\nphp artisan operations:show pending disposed  // show only pending and disposed operations\n```\n\n### Deleting operations\n\nThe whole idea of this package is, that you can dispose the operations once they were executed, so your project won't be cluttered with files and code, you won't be using anymore. \n\nSo you just need to **delete the files from your repository**\n\nThe deleted operations will be shown as ``DISPOSED`` when you call `operations:show`, so you still have a history on all the processed operations.\n\n## Testing\n\n```\ncomposer test\n```\n\n## License\n\nCopyright © Timo Körber | [www.timokoerber.com](https://www.timokoerber.com)\n\n\"One-Time Operations for Laravel\" is open-sourced software licensed under the [MIT license](LICENSE).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTimoKoerber%2Flaravel-one-time-operations","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTimoKoerber%2Flaravel-one-time-operations","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTimoKoerber%2Flaravel-one-time-operations/lists"}