├── LICENSE.md ├── README.md ├── bin └── forge ├── composer.json └── src ├── Commands ├── Authorize.php ├── BaseCommand.php ├── Certificates │ ├── Activate.php │ ├── Delete.php │ ├── Install.php │ ├── ListAll.php │ ├── Make.php │ └── Show.php ├── Credentials.php ├── Daemons │ ├── Delete.php │ ├── ListAll.php │ ├── Make.php │ ├── Reboot.php │ └── Show.php ├── DatabaseUsers │ ├── Delete.php │ ├── ListAll.php │ ├── Make.php │ ├── Show.php │ └── Update.php ├── Databases │ ├── Delete.php │ ├── ListAll.php │ ├── Make.php │ └── Show.php ├── DeployScript │ ├── Get.php │ └── Set.php ├── Deployment │ ├── GetLog.php │ └── ResetState.php ├── Env │ ├── Get.php │ └── Update.php ├── FirewallRules │ ├── Delete.php │ ├── ListAll.php │ ├── Make.php │ └── Show.php ├── Jobs │ ├── Delete.php │ ├── ListAll.php │ ├── Make.php │ └── Show.php ├── NginxConfig │ ├── Get.php │ └── Set.php ├── Projects │ ├── DeleteGit.php │ ├── DeleteWordpress.php │ ├── InstallGit.php │ └── InstallWordpress.php ├── QuickDeploy │ ├── Disable.php │ └── Enable.php ├── Recipes │ ├── Delete.php │ ├── ListAll.php │ ├── Make.php │ ├── Run.php │ ├── Show.php │ └── Update.php ├── Servers │ ├── Delete.php │ ├── ListAll.php │ ├── Make.php │ ├── Reboot.php │ ├── Show.php │ └── Update.php ├── Services │ ├── Install.php │ ├── Reboot.php │ ├── Stop.php │ └── Uninstall.php ├── Sites │ ├── Delete.php │ ├── Deploy.php │ ├── ListAll.php │ ├── Make.php │ ├── Show.php │ └── Update.php ├── SshKeys │ ├── Delete.php │ ├── ListAll.php │ ├── Make.php │ └── Show.php └── Workers │ ├── Delete.php │ ├── ListAll.php │ ├── Make.php │ ├── Reboot.php │ └── Show.php └── Contracts └── NeedsForge.php /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) Sven Luijten 4 | 5 | > Permission is hereby granted, free of charge, to any person obtaining a copy 6 | > of this software and associated documentation files (the "Software"), to deal 7 | > in the Software without restriction, including without limitation the rights 8 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | > copies of the Software, and to permit persons to whom the Software is 10 | > furnished to do so, subject to the following conditions: 11 | > 12 | > The above copyright notice and this permission notice shall be included in 13 | > all copies or substantial portions of the Software. 14 | > 15 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | > THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![forge-cli](https://cloud.githubusercontent.com/assets/11269635/24330714/fdfddfaa-1224-11e7-8f84-f1b4efa7a8b7.jpg) 2 | 3 | # Forge CLI 4 | 5 | [![Latest Version on Packagist][ico-version]][link-packagist] 6 | [![Total Downloads][ico-downloads]][link-packagist] 7 | [![Software License][ico-license]](LICENSE.md) 8 | [![Build Status][ico-tests]][link-tests] 9 | [![StyleCI][ico-styleci]][link-styleci] 10 | 11 | --- 12 | ## ⚠️ Notice 13 | **This package is abandoned**: Use [the official `laravel/forge-cli`](https://github.com/laravel/forge-cli) instead. 14 | --- 15 | 16 | Interact with your [Laravel Forge](https://forge.laravel.com) servers and sites via the command line with this package. Create and list 17 | servers, add sites, and install repositories all without leaving the comfort of your command line. An overview of all available commands 18 | can be found [here](#usage). 19 | 20 | ## Installation 21 | Via [composer](http://getcomposer.org): 22 | 23 | ```bash 24 | $ composer global require sven/forge-cli 25 | ``` 26 | 27 | ## Setup 28 | Ensure Composer's global `bin` directory is included in your path. This directory is located at `~/.composer/vendor/bin` on macOS / Linux, and at 29 | `%APPDATA%/Composer/vendor/bin` on Windows. 30 | 31 | Before using the commands, you have to provide an API token. To generate a new token, visit [this page](https://forge.laravel.com/user/profile#/api), 32 | give the token a name (like `ForgeCLI`) and click "Create new token". 33 | 34 | Then, execute the following command on the command line: 35 | 36 | ```bash 37 | $ forge authorize 38 | ``` 39 | 40 | When prompted for it, paste in your API key. You may optionally pass in the key directly as an argument to the command: 41 | 42 | ```bash 43 | $ forge authorize 44 | ``` 45 | 46 | If the API key on your Forge account changed, you'll need to run the same command again. A hidden configuration file 47 | will be saved to your home directory (`~/.forge.json` on macOS / Linux, `%USERPROFILE%/.forge.json` on Windows). 48 | 49 | ## Usage 50 | A list of commands with their explanation can be found below. You can also find a list of commands and their arguments by installing the package 51 | and running `forge list` or `forge help {command}`. 52 | 53 | --- 54 | 55 | ### Servers 56 | 57 | #### server:list 58 | Show all servers associated with your account. 59 | 60 | ```bash 61 | $ forge server:list 62 | 63 | +----------------+--------+----------------+-------------+-------+ 64 | | Name | Id | IP Address | Region | Ready | 65 | +----------------+--------+----------------+-------------+-------+ 66 | | sparkling-reef | 124833 | 95.85.60.157 | Amsterdam 2 | Yes | 67 | +----------------+--------+----------------+-------------+-------+ 68 | ``` 69 | 70 | #### server:show 71 | Show information about one of your servers. 72 | 73 | ```bash 74 | $ forge server:show {serverId} 75 | 76 | Name: sparkling-reef 77 | IP Address: 95.85.60.157 78 | Size: 512MB 79 | Region: Amsterdam 2 80 | PHP version: php71 81 | Created: 2017-03-13 20:59:16 82 | ``` 83 | 84 | #### server:make 85 | Create a new server. 86 | 87 | ```bash 88 | $ forge server:make 89 | --provider=ocean2 90 | --credentials={credentialId} 91 | --region=ams2 92 | --ip=127.0.0.1 93 | --private-ip=192.168.1.1 94 | --php=php71 95 | --database=some_database 96 | --install-maria 97 | --load-balancer 98 | --network={otherServerId} 99 | --network={anotherServerId} 100 | ``` 101 | 102 | #### server:update 103 | Update the metadata on one of your servers. This will only update the data in Forge, it won't make any actual 104 | changes to your server. 105 | 106 | ```bash 107 | $ forge server:update {serverId} 108 | --name=sluggish-cheetah 109 | --size=1GB 110 | --ip=127.0.0.1 111 | --private-ip=192.168.1.1 112 | --max-upload-size=256 113 | --network={otherServerId} 114 | --network={anotherServerId} 115 | ``` 116 | 117 | #### server:reboot 118 | Reboot one of your servers. You will need to confirm your action. 119 | 120 | ```bash 121 | $ forge server:reboot {serverId} 122 | ``` 123 | 124 | #### server:delete 125 | Delete an existing server. You will need to confirm your action. 126 | 127 | ```bash 128 | $ forge server:delete {serverId} 129 | ``` 130 | 131 | --- 132 | 133 | ### Sites 134 | 135 | #### site:list 136 | Show all sites installed on a server. 137 | 138 | ```bash 139 | $ forge site:list {serverId} 140 | 141 | +--------+-----------------+------+-----------------------------+--------+ 142 | | Id | Name | Type | Repository | Branch | 143 | +--------+-----------------+------+-----------------------------+--------+ 144 | | 303243 | default | php | - | - | 145 | | 303246 | svenluijten.com | html | svenluijten/svenluijten.com | master | 146 | | 303247 | pkgst.co | php | svenluijten/slack-packagist | master | 147 | +--------+-----------------+------+-----------------------------+--------+ 148 | ``` 149 | 150 | #### site:show 151 | Show information about a site on a specified server. 152 | 153 | ```bash 154 | $ forge site:show {serverId} {siteId} 155 | 156 | Name: svenluijten.com 157 | Repository info: svenluijten/svenluijten.com @ master 158 | Directory: /build_production 159 | Quick deploy: Off 160 | Status: installed 161 | Project type: html 162 | Created: 2017-03-13 21:14:19 163 | ``` 164 | 165 | #### site:make 166 | Create a new site on one of your servers. Use `--alias` to include one or more additional domains. 167 | 168 | ```bash 169 | $ forge site:make {serverId} 170 | --domain=example.com 171 | --alias=example.org 172 | --alias=another-site.net 173 | --type=php 174 | --directory=/public 175 | ``` 176 | 177 | #### site:update 178 | Update a site on a specified server. 179 | 180 | ```bash 181 | $ forge site:update {serverId} {siteId} 182 | --directory=/html 183 | ``` 184 | 185 | #### site:deploy 186 | Deploy the given site. 187 | 188 | ```bash 189 | $ forge site:deploy {serverId} {siteId} 190 | ``` 191 | 192 | #### site:delete 193 | Delete a site. You will need to confirm your action. 194 | 195 | ```bash 196 | $ forge site:delete {serverId} {siteId} 197 | ``` 198 | 199 | --- 200 | 201 | ### Services 202 | 203 | #### service:reboot 204 | Reboot a service on the given server. Supported services are `nginx`, `mysql`, and `postgres`. 205 | 206 | ```bash 207 | $ forge service:reboot {serverId} {service} 208 | ``` 209 | 210 | #### service:stop 211 | Stop a service on the given server. Supported services are `nginx`, `mysql`, and `postgres`. 212 | 213 | ```bash 214 | $ forge service:stop {serverId} {service} 215 | ``` 216 | 217 | #### service:install 218 | Install a service on the given server. Supported services are `blackfire` and `papertrail`. The `--host` option 219 | is only required when installing Papertrail, `--server-id` and `--server-token` are only required when installing 220 | Blackfire. 221 | 222 | ```bash 223 | $ forge service:install {serverId} {service} 224 | --host=192.168.1.1 225 | --server-id=12345 226 | --server-token=YOUR_SERVER_TOKEN 227 | ``` 228 | 229 | #### service:uninstall 230 | Uninstall a service from the given server. Supported services are `blackfire` and `papertrail`. 231 | 232 | ```bash 233 | $ forge service:uninstall {serverId} {service} 234 | ``` 235 | 236 | --- 237 | 238 | ### Daemons 239 | 240 | #### daemon:list 241 | List all active daemons on the given server. 242 | 243 | ```bash 244 | $ forge daemon:list {serverId} 245 | 246 | +-------+------------+---------------------------------+---------------------+ 247 | | Id | Status | Command | Created | 248 | +-------+------------+---------------------------------+---------------------+ 249 | | 12345 | installing | echo 'hello world' >> /dev/null | 2017-03-13 21:14:19 | 250 | +-------+------------+---------------------------------+---------------------+ 251 | ``` 252 | 253 | #### daemon:show 254 | Show information about the given daemon. 255 | 256 | ```bash 257 | $ forge show:daemon {serverId} {daemonId} 258 | 259 | Status: installing 260 | Command: echo 'hello world' >> /dev/null 261 | Created: 2017-03-21 18:26:33 262 | ``` 263 | 264 | #### daemon:make 265 | Create a new daemon to run on the given server. If no user is supplied, it defaults to `forge`. 266 | 267 | ```bash 268 | $ forge make:daemon {serverId} 269 | --command="command to run" 270 | --user=root 271 | ``` 272 | 273 | #### daemon:reboot 274 | Reboot the given daemon. You will need to confirm your action. 275 | 276 | ```bash 277 | $ forge reboot:daemon {serverId} {daemonId} 278 | ``` 279 | 280 | #### daemon:delete 281 | Delete the given daemon from the given server. You will need to confirm your action. 282 | 283 | ```bash 284 | $ forge delete:daemon {serverId} {daemonId} 285 | ``` 286 | 287 | --- 288 | 289 | ### MySQL Users 290 | 291 | #### mysql-user:make 292 | Create a new MySQL user with access to the given databases. 293 | 294 | ```bash 295 | $ forge mysql-user:make {serverId} 296 | --username="your_username" 297 | --password="password" 298 | --database=456 299 | --database=789 300 | ``` 301 | 302 | #### mysql-user:list 303 | List all MySQL users on the given server. 304 | 305 | ```bash 306 | $ forge mysql-user:list {serverId} 307 | 308 | +-------+---------------+------------+---------------------+ 309 | | Id | Name | Status | Created | 310 | +-------+---------------+------------+---------------------+ 311 | | 67890 | your_username | installing | 2017-03-13 21:14:19 | 312 | +-------+---------------+------------+---------------------+ 313 | ``` 314 | 315 | #### mysql-user:show 316 | Show information about the given MySQL user. 317 | 318 | ```bash 319 | $ forge mysql-user:show {serverId} {userId} 320 | 321 | Status: installing 322 | Name: your_username 323 | Created: 2017-03-21 18:26:33 324 | ``` 325 | 326 | #### mysql-user:update 327 | Update the databases a MySQL user has access to. 328 | 329 | ```bash 330 | $ forge mysql-user:update {serverId} {userId} 331 | --database=987 332 | --database=654 333 | ``` 334 | 335 | #### mysql-user:delete 336 | Delete the given MySQL user from your server. You will need to confirm your action. 337 | 338 | ```bash 339 | $ forge mysql-user:delete {serverId} {userId} 340 | ``` 341 | 342 | ### Firewall Rules 343 | 344 | #### rule:make 345 | Create a new firewall rule. 346 | 347 | ```bash 348 | $ forge rule:make {serverId} 349 | --name="firewall rule" 350 | --port=88 351 | ``` 352 | 353 | #### rule:list 354 | Show all firewall rules. 355 | 356 | ```bash 357 | $ forge rule:list {serverId} 358 | ``` 359 | 360 | #### rule:show 361 | Show information about one of your firewall rules. 362 | 363 | ```bash 364 | $ forge rule:show {serverId} {ruleId} 365 | ``` 366 | 367 | #### rule:delete 368 | Delete a given firewall rule from one of your servers. You will need to confirm your action. 369 | 370 | ```bash 371 | $ forge rule:delete {serverId} {ruleId} 372 | ``` 373 | 374 | --- 375 | 376 | ### Scheduled Jobs 377 | 378 | #### job:make 379 | Create a new scheduled job. 380 | 381 | ```bash 382 | $ forge job:make {serverId} 383 | --user="forge" 384 | --command="echo 'hello world' > /dev/null" 385 | --frequency="hourly" 386 | ``` 387 | 388 | #### job:list 389 | Show all scheduled jobs. 390 | 391 | ```bash 392 | $ forge job:list {serverId} 393 | ``` 394 | 395 | #### job:show 396 | Show information about one of your scheduled jobs. 397 | 398 | ```bash 399 | $ forge job:show {serverId} {jobId} 400 | ``` 401 | 402 | #### job:delete 403 | Delete a given scheduled job from one of your servers. You will need to confirm your action. 404 | 405 | ```bash 406 | $ forge job:delete {serverId} {jobId} 407 | ``` 408 | 409 | --- 410 | 411 | ### Databases 412 | 413 | #### database:make 414 | Create a new database. The flags `--user` and `--password` must either both be present or both 415 | be absent. 416 | 417 | ```bash 418 | $ forge database:make {serverId} 419 | --user="sven" 420 | --password="My_P45sw0rD" 421 | ``` 422 | 423 | #### database:list 424 | Show all databases on a server. 425 | 426 | ```bash 427 | $ forge database:list {serverId} 428 | ``` 429 | 430 | #### database:show 431 | Show information about one of your databases. 432 | 433 | ```bash 434 | $ forge database:show {serverId} {databaseId} 435 | ``` 436 | 437 | #### database:delete 438 | Delete a given database from one of your servers. You will need to confirm your action. 439 | 440 | ```bash 441 | $ forge database:delete {serverId} {databaseId} 442 | ``` 443 | 444 | --- 445 | 446 | ### SSL Certificates 447 | 448 | #### certificate:list 449 | Show all certificates installed on the given site. 450 | 451 | ```bash 452 | $ forge certificate:list {serverId} {siteId} 453 | ``` 454 | 455 | #### certificate:show 456 | Show information about the specified certificate. 457 | 458 | ```bash 459 | $ forge certificate:show {serverId} {siteId} {certificateId} 460 | ``` 461 | 462 | #### certificate:make 463 | Create a new certificate for one of your sites. 464 | 465 | ```bash 466 | $ forge certificate:make {serverId} {siteId} 467 | --domain="www.example.com" 468 | --country="US" 469 | --state="NY" 470 | --city="New York" 471 | --organization="Acme, Inc." 472 | --department="Development" 473 | ``` 474 | 475 | #### certificate:activate 476 | Activate a currently installed SSL certificate. 477 | 478 | ```bash 479 | $ forge certificate:activate {serverId} {siteId} {certificateId} 480 | ``` 481 | 482 | #### certificate:install 483 | Install a certificate on the given site. 484 | 485 | ```bash 486 | $ forge certificate:install {serverId} {siteId} {certificateId} 487 | ``` 488 | 489 | #### certificate:delete 490 | Revoke and remove a certificate from the given site. You will need to confirm you action. 491 | 492 | ```bash 493 | $ forge certificate:delete {serverId} {siteId} {certificateId} 494 | ``` 495 | 496 | --- 497 | 498 | ### SSH Keys 499 | 500 | #### key:make 501 | Create a new SSH key and add it to a server. 502 | 503 | ```bash 504 | $ forge key:make {serverId} 505 | --name="Macbook" 506 | --file="~/.ssh/id_rsa.pub" 507 | ``` 508 | 509 | If you do not supply the `--file` option, the command will look in `STDIN` for any input: 510 | 511 | ```bash 512 | $ forge key:make {serverId} --name="Macbook" < ~/.ssh/id_rsa.pub 513 | ``` 514 | 515 | #### key:list 516 | Show all SSH keys installed on a server. 517 | 518 | ```bash 519 | $ forge key:list {serverId} 520 | ``` 521 | 522 | #### key:show 523 | Show information about one of your SSH keys. 524 | 525 | ```bash 526 | $ forge key:show {serverId} {keyId} 527 | ``` 528 | 529 | #### key:delete 530 | Delete a given SSH key from one of your servers. You will need to confirm your action. 531 | 532 | ```bash 533 | $ forge key:delete {serverId} {keyId} 534 | ``` 535 | 536 | --- 537 | 538 | ### Workers 539 | 540 | #### worker:make 541 | Create a new worker. 542 | 543 | ```bash 544 | $ forge worker:make {serverId} {siteId} 545 | --connection=sqs 546 | --timeout=90 547 | --sleep=10 548 | --tries=1 549 | --daemon 550 | ``` 551 | 552 | #### worker:list 553 | Show all workers installed on a site. 554 | 555 | ```bash 556 | $ forge worker:list {serverId} {siteId} 557 | ``` 558 | 559 | #### worker:show 560 | Show information about one of your workers. 561 | 562 | ```bash 563 | $ forge worker:show {serverId} {siteId} {workerId} 564 | ``` 565 | 566 | #### worker:delete 567 | Delete a given worker from one of your sites. You will need to confirm your action. 568 | 569 | ```bash 570 | $ forge worker:delete {serverId} {siteId} {workerId} 571 | ``` 572 | 573 | #### worker:reboot 574 | Reboot one of your workers. You will need to confirm your action. 575 | 576 | ```bash 577 | $ forge worker:reboot {serverId} {siteId} {workerId} 578 | ``` 579 | 580 | --- 581 | 582 | #### quickdeploy:enable 583 | Enable quick deployment for the given site. 584 | 585 | ```bash 586 | $ forge quickdeploy:enable {serverId} {siteId} 587 | ``` 588 | 589 | #### quickdeploy:disable 590 | Disable quick deployment for the given site. 591 | 592 | ```bash 593 | $ forge quickdeploy:disable {serverId} {siteId} 594 | ``` 595 | 596 | #### deploy-script:get 597 | Get the deployment script of the given site. 598 | 599 | ```bash 600 | $ forge deploy-script:get {serverId} {siteId} 601 | ``` 602 | 603 | The output will be written to `STDOUT`, so you can save it to a file directly: 604 | 605 | ```bash 606 | $ forge deploy-script:get {serverId} {siteId} > file.txt 607 | ``` 608 | 609 | #### deploy-script:set 610 | Update the deployment script of the given site. 611 | 612 | ```bash 613 | $ forge deploy-script:set {serverId} {siteId} 614 | --file=file.txt 615 | ``` 616 | 617 | If you do not supply the `--file` option, the command will look in `STDIN` for any input: 618 | 619 | ```bash 620 | $ forge deploy-script:set {serverId} {siteId} < file.txt 621 | ``` 622 | 623 | #### deploy-log 624 | Show the latest deployment log. 625 | 626 | ```bash 627 | $ forge deploy-log {serverId} {siteId} 628 | ``` 629 | 630 | The output will be written to `STDOUT`, so you can save it to a file directly: 631 | 632 | ```bash 633 | $ forge deploy-log {serverId} {siteId} > file.log 634 | ``` 635 | 636 | #### reset-deploy-state 637 | Reset the state of the deployment. 638 | 639 | ```bash 640 | $ forge reset-deploy-state {serverId} {siteId} 641 | ``` 642 | 643 | --- 644 | 645 | ### Configuration 646 | 647 | #### env:get 648 | Get the environment file of one of your sites. 649 | 650 | ```bash 651 | $ forge env:get {serverId} {siteId} 652 | ``` 653 | 654 | The output will be written to `STDOUT`, so you can save it to a file directly: 655 | 656 | ```bash 657 | $ forge env:get {serverId} {siteId} > env-file.txt 658 | ``` 659 | 660 | #### env:set 661 | Update the environment file for one of your sites. 662 | 663 | ```bash 664 | $ forge env:set {serverId} {siteId} 665 | --file=new-env.txt 666 | ``` 667 | 668 | If you do not supply the `--file` option, the command will look in `STDIN` for any input: 669 | 670 | ```bash 671 | $ forge env:set {serverId} {siteId} < new-env.txt 672 | ``` 673 | 674 | #### nginx-config:get 675 | Get the nginx config file of one of your sites. 676 | 677 | ```bash 678 | $ forge nginx-config:get {serverId} {siteId} 679 | ``` 680 | 681 | The output will be written to `STDOUT`, so you can save it to a file directly: 682 | 683 | ```bash 684 | $ forge nginx-config:get {serverId} {siteId} > nginx.conf 685 | ``` 686 | 687 | #### nginx-config:set 688 | Update the nginx config file for one of your sites. 689 | 690 | ```bash 691 | $ forge nginx-config:set {serverId} {siteId} 692 | --file=new.conf 693 | ``` 694 | 695 | If you do not supply the `--file` option, the command will look in `STDIN` for any input: 696 | 697 | ```bash 698 | $ forge nginx-config:set {serverId} {siteId} < new.conf 699 | ``` 700 | 701 | --- 702 | 703 | ### Projects 704 | 705 | #### git:install 706 | Install a git project on the given site. 707 | 708 | ```bash 709 | $ forge git:install {serverId} {siteId} 710 | --provider="github" 711 | --repository="username/repository" 712 | ``` 713 | 714 | The `provider` option can be either `github` (default) or `custom`. 715 | 716 | #### git:delete 717 | Remove a git project from the given site. You will need to confirm your action. 718 | 719 | ```bash 720 | $ forge git:delete {serverId} {siteId} 721 | ``` 722 | 723 | #### wordpress:install 724 | Install WordPress on the given site. 725 | 726 | ```bash 727 | $ forge wordpress:install {serverId} {siteId} 728 | --database="name_of_database" 729 | --user="your_username" 730 | ``` 731 | 732 | #### wordpress:delete 733 | Remove a WordPress project from the given site. You will need to confirm your action. 734 | 735 | ```bash 736 | $ forge wordpress:delete {serverId} {siteId} 737 | ``` 738 | 739 | --- 740 | 741 | ### Recipes 742 | 743 | #### recipe:make 744 | Create a new recipe. 745 | 746 | ```bash 747 | $ forge recipe:make 748 | --name="My Recipe" 749 | --user=forge 750 | --script="echo 'hi' >> /dev/null" 751 | ``` 752 | 753 | If you do not supply the `--script` option, the command will look in `STDIN` for any input: 754 | 755 | ```bash 756 | $ forge recipe:make --name="My Recipe" --user=forge < file.txt 757 | ``` 758 | 759 | #### recipe:list 760 | Show all recipes in your Forge account. 761 | 762 | ```bash 763 | $ forge recipe:list 764 | ``` 765 | 766 | #### recipe:show 767 | Show information about one of your recipes. 768 | 769 | ```bash 770 | $ forge recipe:show {recipeId} 771 | ``` 772 | 773 | #### recipe:run 774 | Run the given recipe on the specified server(s). 775 | 776 | ```bash 777 | $ forge recipe:run {recipeId} 778 | --server=1234 779 | --server=5678 780 | ``` 781 | 782 | #### recipe:delete 783 | Delete the given recipe. You will need to confirm your action. 784 | 785 | ```bash 786 | $ forge recipe:delete {recipeId} 787 | ``` 788 | 789 | --- 790 | 791 | ### Credentials 792 | Show all credentials associated with your account. 793 | 794 | ```bash 795 | $ forge credentials 796 | 797 | +-------+----------+--------+ 798 | | Id | Name | Type | 799 | +-------+----------+--------+ 800 | | 15071 | Personal | ocean2 | 801 | +-------+----------+--------+ 802 | ``` 803 | 804 | ## Contributing 805 | All contributions (pull requests, issues and feature requests) are 806 | welcome. Make sure to read through the [CONTRIBUTING.md](CONTRIBUTING.md) first, 807 | though. See the [contributors page](../../graphs/contributors) for all contributors. 808 | 809 | ## License 810 | `sven/forge-cli` is licensed under the MIT License (MIT). Please see the 811 | [license file](LICENSE.md) for more information. 812 | 813 | [ico-version]: https://img.shields.io/packagist/v/sven/forge-cli.svg?style=flat-square 814 | [ico-downloads]: https://img.shields.io/packagist/dt/sven/forge-cli.svg?style=flat-square 815 | [ico-license]: https://img.shields.io/badge/license-MIT-green.svg?style=flat-square 816 | [ico-tests]: https://github.com/svenluijten/forge-cli/workflows/Tests%20(PHP)/badge.svg 817 | [ico-styleci]: https://styleci.io/repos/85804300/shield 818 | 819 | [link-packagist]: https://packagist.org/packages/sven/forge-cli 820 | [link-downloads]: https://packagist.org/packages/sven/forge-cli 821 | [link-tests]: https://github.com/svenluijten/forge-cli/actions?query=workflow%3ATests%20(PHP) 822 | [link-styleci]: https://styleci.io/repos/85804300 823 | -------------------------------------------------------------------------------- /bin/forge: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | addCommands([ 19 | new Authorize, 20 | new Credentials, 21 | new Servers\Make, 22 | new Servers\ListAll, 23 | new Servers\Show, 24 | new Servers\Update, 25 | new Servers\Delete, 26 | new Servers\Reboot, 27 | new Sites\Make, 28 | new Sites\ListAll, 29 | new Sites\Show, 30 | new Sites\Update, 31 | new Sites\Delete, 32 | new Sites\Deploy, 33 | new Services\Reboot, 34 | new Services\Stop, 35 | new Services\Install, 36 | new Services\Uninstall, 37 | new Daemons\ListAll, 38 | new Daemons\Make, 39 | new Daemons\Delete, 40 | new Daemons\Show, 41 | new Daemons\Reboot, 42 | new QuickDeploy\Disable, 43 | new QuickDeploy\Enable, 44 | new Deployment\GetLog, 45 | new Deployment\ResetState, 46 | new DeployScript\Get, 47 | new DeployScript\Set, 48 | new FirewallRules\ListAll, 49 | new FirewallRules\Make, 50 | new FirewallRules\Delete, 51 | new FirewallRules\Show, 52 | new Jobs\ListAll, 53 | new Jobs\Make, 54 | new Jobs\Delete, 55 | new Jobs\Show, 56 | new Databases\ListAll, 57 | new Databases\Make, 58 | new Databases\Delete, 59 | new Databases\Show, 60 | new DatabaseUsers\ListAll, 61 | new DatabaseUsers\Make, 62 | new DatabaseUsers\Delete, 63 | new DatabaseUsers\Show, 64 | new Workers\ListAll, 65 | new Workers\Make, 66 | new Workers\Delete, 67 | new Workers\Show, 68 | new Workers\Reboot, 69 | new Recipes\ListAll, 70 | new Recipes\Make, 71 | new Recipes\Delete, 72 | new Recipes\Show, 73 | new Recipes\Run, 74 | new Recipes\Update, 75 | new NginxConfig\Get, 76 | new NginxConfig\Set, 77 | new Env\Get, 78 | new Env\Update, 79 | new SshKeys\ListAll, 80 | new SshKeys\Make, 81 | new SshKeys\Delete, 82 | new SshKeys\Show, 83 | new Projects\DeleteGit, 84 | new Projects\DeleteWordpress, 85 | new Projects\InstallGit, 86 | new Projects\InstallWordpress, 87 | new Certificates\Activate, 88 | new Certificates\ListAll, 89 | new Certificates\Delete, 90 | new Certificates\Install, 91 | new Certificates\Make, 92 | new Certificates\Show, 93 | ]); 94 | 95 | $app->run(); 96 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sven/forge-cli", 3 | "description": "A set of commands to interact with your Laravel Forge servers, sites, and more", 4 | "keywords": ["laravel", "forge", "command", "cli", "laravel forge", "forge api", "laravel api"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Sven Luijten", 9 | "email": "contact@svenluijten.com", 10 | "homepage": "https://svenluijten.com" 11 | } 12 | ], 13 | "require": { 14 | "php": "^8.0", 15 | "symfony/console": "^4.0 || ^5.0", 16 | "symfony/process": "^4.0 || ^5.0", 17 | "laravel/forge-sdk": "^3.0", 18 | "sven/file-config": "^3.0" 19 | }, 20 | "require-dev": { 21 | "phpunit/phpunit": "^8.0", 22 | "mockery/mockery": "^1.0" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "Sven\\ForgeCLI\\": "src/" 27 | } 28 | }, 29 | "autoload-dev": { 30 | "psr-4": { 31 | "Sven\\ForgeCLI\\Tests\\": "tests/" 32 | } 33 | }, 34 | "bin": [ 35 | "bin/forge" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /src/Commands/Authorize.php: -------------------------------------------------------------------------------- 1 | setName('authorize') 16 | ->setDescription('Set or update the API key used in the commands.') 17 | ->addArgument('key', InputArgument::OPTIONAL, 'Forge API Key'); 18 | } 19 | 20 | public function execute(InputInterface $input, OutputInterface $output): int 21 | { 22 | if (!$input->getArgument('key')) { 23 | /** @var \Symfony\Component\Console\Helper\QuestionHelper $helper */ 24 | $helper = $this->getHelper('question'); 25 | 26 | $question = new Question('What is your API key? '); 27 | $question->setHidden(true); 28 | 29 | $this->config->set('key', $helper->ask($input, $output, $question)); 30 | } else { 31 | $this->config->set('key', $input->getArgument('key')); 32 | } 33 | 34 | $this->config->persist(); 35 | 36 | $output->write('Your API key has successfully been set.'); 37 | 38 | return 0; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Commands/BaseCommand.php: -------------------------------------------------------------------------------- 1 | config = $this->getFileConfig(); 28 | 29 | if ($this instanceof NeedsForge) { 30 | $this->forge = $forge ?: new Forge($this->config->get('key')); 31 | } 32 | } 33 | 34 | protected function table(OutputInterface $output, array $header, array $rows) 35 | { 36 | $table = new Table($output); 37 | $table->setHeaders($header) 38 | ->setRows($rows); 39 | 40 | $table->render(); 41 | } 42 | 43 | protected function fillData(array $options, array $optionMap = null): array 44 | { 45 | $data = []; 46 | 47 | foreach ($optionMap ?: $this->optionMap as $option => $requestKey) { 48 | if (!isset($options[$option])) { 49 | continue; 50 | } 51 | 52 | $data[$requestKey] = $options[$option]; 53 | } 54 | 55 | return $data; 56 | } 57 | 58 | protected function getFileContent(InputInterface $input, string $option): bool|string 59 | { 60 | $filename = $input->hasOption($option) ? $input->getOption($option) : 'php://stdin'; 61 | 62 | if (!file_exists($filename)) { 63 | return $filename; 64 | } 65 | 66 | if ($filename && ftell(STDIN) !== false) { 67 | return file_get_contents($filename); 68 | } 69 | 70 | throw new InvalidArgumentException('This command requires either the "--'.$option.'" option to be set, or an input from STDIN.'); 71 | } 72 | 73 | protected function requireOptions(InputInterface $input, string ...$keys): void 74 | { 75 | foreach ($keys as $key) { 76 | if ($input->hasOption($key)) { 77 | continue; 78 | } 79 | 80 | throw new RuntimeException( 81 | sprintf('The option "%s" is required.', $key) 82 | ); 83 | } 84 | } 85 | 86 | protected function getFileConfig(): Store 87 | { 88 | $homeDirectory = ( 89 | strncasecmp(PHP_OS, 'WIN', 3) === 0 90 | ? $_SERVER['USERPROFILE'] 91 | : $_SERVER['HOME'] 92 | ).DIRECTORY_SEPARATOR; 93 | 94 | $visibleConfigFile = $homeDirectory.'forge.json'; 95 | $hiddenConfigFile = $homeDirectory.'.forge.json'; 96 | 97 | // If an existing visible configuration file exists, continue using it. 98 | if (file_exists($visibleConfigFile)) { 99 | return new Store(new File($visibleConfigFile), new Json()); 100 | } 101 | 102 | // If a hidden configuration file does not exist, create it. 103 | if (!file_exists($hiddenConfigFile)) { 104 | file_put_contents($hiddenConfigFile, '{"key":""}'); 105 | } 106 | 107 | // Return the hidden configuration file. 108 | return new Store(new File($hiddenConfigFile), new Json()); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/Commands/Certificates/Activate.php: -------------------------------------------------------------------------------- 1 | setName('certificate:activate') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 17 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site the certificate should be activated on.') 18 | ->addArgument('certificate', InputArgument::REQUIRED, 'The id of the certificate to activate.') 19 | ->setDescription('Activate one of the SSL certificates on the given site.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $this->forge->activateCertificate( 25 | $input->getArgument('server'), $input->getArgument('site'), $input->getArgument('certificate'), false 26 | ); 27 | 28 | return 0; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Commands/Certificates/Delete.php: -------------------------------------------------------------------------------- 1 | setName('certificate:delete') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server where the site is.') 18 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site the SSL certificate to delete is on.') 19 | ->addArgument('certificate', InputArgument::REQUIRED, 'The id of the SSL certificate to delete.') 20 | ->setDescription('Delete an SSL certificate.'); 21 | } 22 | 23 | public function execute(InputInterface $input, OutputInterface $output): int 24 | { 25 | $certificate = $input->getArgument('certificate'); 26 | 27 | $helper = $this->getHelper('question'); 28 | $question = new ConfirmationQuestion('Are you sure you want to delete the SSL certificate with id "'.$certificate.'"?', false); 29 | 30 | if (!$helper->ask($input, $output, $question)) { 31 | $output->writeln('Ok, aborting. Your SSL certificate is safe.'); 32 | } else { 33 | $this->forge->deleteCertificate($input->getArgument('server'), $input->getArgument('site'), $certificate); 34 | } 35 | 36 | return 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Commands/Certificates/Install.php: -------------------------------------------------------------------------------- 1 | setName('certificate:install') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server where the site is.') 17 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site the SSL certificate to delete is on.') 18 | ->addArgument('certificate', InputArgument::REQUIRED, 'The id of the SSL certificate to delete.') 19 | ->setDescription('Install the given SSL certificate on a site.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $this->forge->installCertificate( 25 | $input->getArgument('server'), $input->getArgument('site'), $input->getArgument('certificate') 26 | ); 27 | 28 | return 0; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Commands/Certificates/ListAll.php: -------------------------------------------------------------------------------- 1 | setName('certificate:list') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 18 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to list certificates for.') 19 | ->setDescription('Show all SSL certificates installed on the given site.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $certificates = $this->forge->certificates($input->getArgument('server'), $input->getArgument('site')); 25 | 26 | $this->table($output, ['Id', 'Status', 'Active', 'Created'], array_map(function (Certificate $certificate) { 27 | return [$certificate->id, $certificate->status, $certificate->active ? 'Yes' : 'No', $certificate->createdAt]; 28 | }, $certificates)); 29 | 30 | return 0; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Commands/Certificates/Make.php: -------------------------------------------------------------------------------- 1 | setName('certificate:make') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 18 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to make the SSL certificate for.') 19 | ->addOption('domain', null, InputOption::VALUE_REQUIRED, 'The domain to create an SSL certificate for.') 20 | ->addOption('country', null, InputOption::VALUE_REQUIRED, 'The country you currently live in.') 21 | ->addOption('state', null, InputOption::VALUE_REQUIRED, 'The state you currently live in.') 22 | ->addOption('city', null, InputOption::VALUE_REQUIRED, 'The city you currently live in.') 23 | ->addOption('organization', null, InputOption::VALUE_REQUIRED, 'The organization the SSL certificate should be issued to.') 24 | ->addOption('department', null, InputOption::VALUE_REQUIRED, 'The department you work in.') 25 | ->setDescription('Create a new SSL certificate.'); 26 | } 27 | 28 | public function execute(InputInterface $input, OutputInterface $output): int 29 | { 30 | $this->requireOptions($input, 'domain', 'country', 'state', 'city', 'organization', 'department'); 31 | 32 | $certificate = $this->forge->createCertificate( 33 | $input->getArgument('server'), 34 | $input->getArgument('site'), 35 | $this->fillData($input->getOptions()), 36 | false 37 | ); 38 | 39 | $output->writeln([ 40 | 'Domain: '.$certificate->domain, 41 | 'Status: '.$certificate->status, 42 | 'Exists: '.$certificate->existing ? 'Yes' : 'No', 43 | 'Activation Status: '.$certificate->activationStatus, 44 | 'Created: '.$certificate->createdAt, 45 | ]); 46 | 47 | return 0; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Commands/Certificates/Show.php: -------------------------------------------------------------------------------- 1 | setName('certificate:show') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 17 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site the SSL certificate is on.') 18 | ->addArgument('certificate', InputArgument::REQUIRED, 'The id of the SSL certificate to show information about.') 19 | ->setDescription('Show information about an SSL certificate on the given website.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $certificate = $this->forge->certificate( 25 | $input->getArgument('server'), $input->getArgument('site'), $input->getArgument('certificate') 26 | ); 27 | 28 | $output->writeln([ 29 | 'Domain: '.$certificate->domain, 30 | 'Status: '.$certificate->status, 31 | 'Exists: '.$certificate->existing ? 'Yes' : 'No', 32 | 'Activation Status: '.$certificate->activationStatus, 33 | 'Request Status: '.$certificate->requestStatus, 34 | 'Created: '.$certificate->createdAt, 35 | ]); 36 | 37 | return 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Commands/Credentials.php: -------------------------------------------------------------------------------- 1 | setName('credentials') 15 | ->setDescription('Show all credentials associated with your account.'); 16 | } 17 | 18 | public function execute(InputInterface $input, OutputInterface $output): int 19 | { 20 | $this->table($output, ['Id', 'Name', 'Type'], array_map(function (Credential $credential) { 21 | return [$credential->id, $credential->name, $credential->type]; 22 | }, $this->forge->credentials())); 23 | 24 | return 0; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Commands/Daemons/Delete.php: -------------------------------------------------------------------------------- 1 | setName('delete:daemon') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the daemon is on.') 18 | ->addArgument('daemon', InputArgument::REQUIRED, 'The id of the daemon to delete.') 19 | ->setDescription('Delete the given daemon from one of your servers.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $daemon = $input->getArgument('daemon'); 25 | 26 | $helper = $this->getHelper('question'); 27 | $question = new ConfirmationQuestion('Are you sure you want to delete the daemon with id "'.$daemon.'"?', false); 28 | 29 | if (!$helper->ask($input, $output, $question)) { 30 | $output->writeln('Ok, aborting. Your daemon is safe.'); 31 | } else { 32 | $this->forge->deleteDaemon($input->getArgument('server'), $daemon); 33 | } 34 | 35 | return 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Commands/Daemons/ListAll.php: -------------------------------------------------------------------------------- 1 | setName('daemon:list') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to list the daemons for.') 18 | ->setDescription('Show all daemons running on a server.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $rows = array_map(function (Daemon $daemon) { 24 | return [$daemon->id, $daemon->status, $daemon->command, $daemon->createdAt]; 25 | }, $this->forge->daemons($input->getArgument('server'))); 26 | 27 | $this->table($output, ['Id', 'Status', 'Command', 'Created'], $rows); 28 | 29 | return 0; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Commands/Daemons/Make.php: -------------------------------------------------------------------------------- 1 | 'command', 16 | 'user' => 'user', 17 | ]; 18 | 19 | public function configure(): void 20 | { 21 | $this->setName('daemon:make') 22 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to create the daemon on.') 23 | ->addOption('command', null, InputOption::VALUE_REQUIRED, 'The command to run.') 24 | ->addOption('user', null, InputOption::VALUE_REQUIRED, 'The user to run the command as.', 'forge') 25 | ->setDescription('Create and start a new daemon.'); 26 | } 27 | 28 | public function execute(InputInterface $input, OutputInterface $output): int 29 | { 30 | $this->forge->createDaemon( 31 | $input->getArgument('server'), $this->fillData($input->getOptions()) 32 | ); 33 | 34 | return 0; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Commands/Daemons/Reboot.php: -------------------------------------------------------------------------------- 1 | setName('daemon:reboot') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the daemon is on.') 18 | ->addArgument('daemon', InputArgument::REQUIRED, 'The id of the daemon to reboot.') 19 | ->setDescription('Restart the given daemon on one of your servers.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $daemon = $input->getArgument('daemon'); 25 | 26 | $helper = $this->getHelper('question'); 27 | $question = new ConfirmationQuestion('Are you sure you want to reboot the daemon with id "'.$daemon.'"?', false); 28 | 29 | if (!$helper->ask($input, $output, $question)) { 30 | $output->writeln('Ok, aborting. Your daemon is safe.'); 31 | } else { 32 | $this->forge->restartDaemon($input->getArgument('server'), $daemon); 33 | } 34 | 35 | return 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Commands/Daemons/Show.php: -------------------------------------------------------------------------------- 1 | setName('daemon:show') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to the daemon is running on.') 17 | ->addArgument('daemon', InputArgument::REQUIRED, 'The id of the daemon to show information about.') 18 | ->setDescription('Show information about the given daemon.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $daemon = $this->forge->daemon( 24 | $input->getArgument('server'), $input->getArgument('daemon') 25 | ); 26 | 27 | $output->writeln([ 28 | 'Status: '.$daemon->status, 29 | 'Command: '.$daemon->command, 30 | 'Created: '.$daemon->createdAt, 31 | ]); 32 | 33 | return 0; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Commands/DatabaseUsers/Delete.php: -------------------------------------------------------------------------------- 1 | setName('mysql-user:delete') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the MySQL user is on.') 18 | ->addArgument('user', InputArgument::REQUIRED, 'The id of the MySQL user to delete.') 19 | ->setDescription('Delete the given MySQL user from one of your servers.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $user = $input->getArgument('user'); 25 | 26 | $helper = $this->getHelper('question'); 27 | $question = new ConfirmationQuestion('Are you sure you want to delete the MySQL user with id "'.$user.'"?', false); 28 | 29 | if ($helper->ask($input, $output, $question)) { 30 | $this->forge->deleteDatabaseUser($input->getArgument('server'), $user); 31 | } else { 32 | $output->writeln('Ok, aborting. Your MySQL user is safe.'); 33 | } 34 | 35 | return 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Commands/DatabaseUsers/ListAll.php: -------------------------------------------------------------------------------- 1 | setName('mysql-user:list') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to list the MySQL users for.') 18 | ->setDescription('Show all MySQL users on a server.'); 19 | } 20 | 21 | protected function execute(InputInterface $input, OutputInterface $output) 22 | { 23 | $rows = array_map(function (DatabaseUser $user) { 24 | return [$user->id, $user->name, $user->status, $user->createdAt]; 25 | }, $this->forge->databaseUsers($input->getArgument('server'))); 26 | 27 | $this->table($output, ['Id', 'Name', 'Status', 'Created'], $rows); 28 | 29 | return 0; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Commands/DatabaseUsers/Make.php: -------------------------------------------------------------------------------- 1 | 'name', 16 | 'password' => 'password', 17 | 'database' => 'databases', 18 | ]; 19 | 20 | public function configure(): void 21 | { 22 | $this->setName('mysql-user:make') 23 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to create the MySQL user on.') 24 | ->addOption('username', null, InputOption::VALUE_REQUIRED, 'The username of the MySQL user to create.', null) 25 | ->addOption('password', null, InputOption::VALUE_REQUIRED, 'The password of the database user.', null) 26 | ->addOption('database', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'The id(s) of the database(s) to give the MySQL user access to.', null) 27 | ->setDescription('Create a new MySQL user.'); 28 | } 29 | 30 | public function execute(InputInterface $input, OutputInterface $output): int 31 | { 32 | $this->forge->createDatabaseUser( 33 | $input->getArgument('server'), $this->fillData($input->getOptions()) 34 | ); 35 | 36 | return 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Commands/DatabaseUsers/Show.php: -------------------------------------------------------------------------------- 1 | setName('mysql-user:show') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the MySQL user is on.') 17 | ->addArgument('user', InputArgument::REQUIRED, 'The id of the MySQL user to show information about.') 18 | ->setDescription('Show information about the given MySQL user.'); 19 | } 20 | 21 | protected function execute(InputInterface $input, OutputInterface $output) 22 | { 23 | $user = $this->forge->databaseUser( 24 | $input->getArgument('server'), $input->getArgument('user') 25 | ); 26 | 27 | $output->writeln([ 28 | 'Status: '.$user->status, 29 | 'Name: '.$user->name, 30 | 'Created: '.$user->createdAt, 31 | ]); 32 | 33 | return 0; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Commands/DatabaseUsers/Update.php: -------------------------------------------------------------------------------- 1 | 'databases', 16 | ]; 17 | 18 | public function configure(): void 19 | { 20 | $this->setName('mysql-user:update') 21 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the MySQL user is on.') 22 | ->addArgument('user', InputArgument::REQUIRED, 'The id of the MySQL user to update.') 23 | ->addOption('database', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'The id(s) of the database(s) to give the MySQL user access to.') 24 | ->setDescription('Update the given MySQL user.'); 25 | } 26 | 27 | public function execute(InputInterface $input, OutputInterface $output): int 28 | { 29 | $payload = $this->fillData($input->getOptions()); 30 | 31 | $this->forge->updateDatabaseUser( 32 | $input->getArgument('server'), $input->getArgument('user'), $payload 33 | ); 34 | 35 | return 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Commands/Databases/Delete.php: -------------------------------------------------------------------------------- 1 | setName('database:delete') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the database is on.') 18 | ->addArgument('database', InputArgument::REQUIRED, 'The id of the database to delete.') 19 | ->setDescription('Delete the given database from one of your servers.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $database = $input->getArgument('database'); 25 | 26 | $helper = $this->getHelper('question'); 27 | $question = new ConfirmationQuestion('Are you sure you want to delete the database with id "'.$database.'"?', false); 28 | 29 | if (!$helper->ask($input, $output, $question)) { 30 | $output->writeln('Ok, aborting. Your database is safe.'); 31 | } else { 32 | $this->forge->deleteMysqlDatabase($input->getArgument('server'), $database); 33 | } 34 | 35 | return 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Commands/Databases/ListAll.php: -------------------------------------------------------------------------------- 1 | setName('database:list') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to list the databases for.') 18 | ->setDescription('Show all databases a server.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $rows = array_map(function (Database $database) { 24 | return [$database->id, $database->name, $database->status, $database->createdAt]; 25 | }, $this->forge->mysqlDatabases($input->getArgument('server'))); 26 | 27 | $this->table($output, ['Id', 'Name', 'Status', 'Created'], $rows); 28 | 29 | return 0; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Commands/Databases/Make.php: -------------------------------------------------------------------------------- 1 | 'user', 19 | 'password' => 'password', 20 | 'name' => 'name', 21 | ]; 22 | 23 | public function configure(): void 24 | { 25 | $this->setName('database:make') 26 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to create the database on.') 27 | ->addOption('user', null, InputOption::VALUE_REQUIRED, 'The username of an (optional) database user to create.', null) 28 | ->addOption('password', null, InputOption::VALUE_REQUIRED, 'The password of the database user. Required with "user".', null) 29 | ->addOption('name', null, InputOption::VALUE_REQUIRED, 'The name of the database.', null) 30 | ->setDescription('Create a new database.'); 31 | } 32 | 33 | public function execute(InputInterface $input, OutputInterface $output): int 34 | { 35 | $this->forge->createMysqlDatabase( 36 | $input->getArgument('server'), $this->fillData($input->getOptions()), false 37 | ); 38 | 39 | return 0; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Commands/Databases/Show.php: -------------------------------------------------------------------------------- 1 | setName('database:show') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to the database is running on.') 17 | ->addArgument('database', InputArgument::REQUIRED, 'The id of the database to show information about.') 18 | ->setDescription('Show information about the given database.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $database = $this->forge->mysqlDatabase( 24 | $input->getArgument('server'), $input->getArgument('database') 25 | ); 26 | 27 | $output->writeln([ 28 | 'Status: '.$database->status, 29 | 'Name: '.$database->name, 30 | 'Created: '.$database->createdAt, 31 | ]); 32 | 33 | return 0; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Commands/DeployScript/Get.php: -------------------------------------------------------------------------------- 1 | setName('deploy-script:get') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 17 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to get the deployment script of.') 18 | ->setDescription('Output the deployment script used for the given site.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $script = $this->forge->siteDeploymentScript( 24 | $input->getArgument('server'), $input->getArgument('site') 25 | ); 26 | 27 | $output->writeln($script); 28 | 29 | return 0; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Commands/DeployScript/Set.php: -------------------------------------------------------------------------------- 1 | setName('deploy-script:set') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 18 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site you want to set the deployment script of.') 19 | ->addOption('file', null, InputOption::VALUE_REQUIRED, 'The file your new deployment script is in.') 20 | ->setDescription('Set the deployment script of the given site.'); 21 | } 22 | 23 | public function execute(InputInterface $input, OutputInterface $output): int 24 | { 25 | $this->forge->updateSiteDeploymentScript( 26 | $input->getArgument('server'), $input->getArgument('site'), $this->getFileContent($input, 'file') 27 | ); 28 | 29 | return 0; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Commands/Deployment/GetLog.php: -------------------------------------------------------------------------------- 1 | setName('deploy-log') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 17 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to get the deployment log for.') 18 | ->setDescription('Get latest deployment log of the given site.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $this->forge->siteDeploymentLog( 24 | $input->getArgument('server'), $input->getArgument('site') 25 | ); 26 | 27 | return 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Commands/Deployment/ResetState.php: -------------------------------------------------------------------------------- 1 | setName('reset-deploy-state') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 17 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site you want to reset the deployment state of.') 18 | ->setDescription('Reset the deployment state of the given site.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $this->forge->resetDeploymentState( 24 | $input->getArgument('server'), $input->getArgument('site') 25 | ); 26 | 27 | return 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Commands/Env/Get.php: -------------------------------------------------------------------------------- 1 | setName('env:get') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 17 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to get the .env file for.') 18 | ->setDescription('Show the .env file.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $env = $this->forge->siteEnvironmentFile( 24 | $input->getArgument('server'), $input->getArgument('site') 25 | ); 26 | 27 | $output->writeln($env); 28 | 29 | return 0; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Commands/Env/Update.php: -------------------------------------------------------------------------------- 1 | 'file', 19 | ]; 20 | 21 | public function configure(): void 22 | { 23 | $this->setName('env:set') 24 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 25 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site you want to update the .env file of.') 26 | ->addOption('file', null, InputOption::VALUE_REQUIRED, 'The path to your new .env file.') 27 | ->setDescription('Update the .env file of the given site.'); 28 | } 29 | 30 | public function execute(InputInterface $input, OutputInterface $output): int 31 | { 32 | $this->forge->updateSiteEnvironmentFile( 33 | $input->getArgument('server'), $input->getArgument('site'), $this->getFileContent($input, 'file') 34 | ); 35 | 36 | return 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Commands/FirewallRules/Delete.php: -------------------------------------------------------------------------------- 1 | setName('rule:delete') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the firewall rule to delete is on.') 18 | ->addArgument('rule', InputArgument::REQUIRED, 'The id of the firewall rule to delete.') 19 | ->setDescription('Delete a firewall rule.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $rule = $input->getArgument('rule'); 25 | 26 | $helper = $this->getHelper('question'); 27 | $question = new ConfirmationQuestion('Are you sure you want to delete the rule with id "'.$rule.'"?', false); 28 | 29 | if (!$helper->ask($input, $output, $question)) { 30 | $output->writeln('Ok, aborting. Your firewall rule is safe.'); 31 | } else { 32 | $this->forge->deleteFirewallRule($input->getArgument('server'), $rule); 33 | } 34 | 35 | return 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Commands/FirewallRules/ListAll.php: -------------------------------------------------------------------------------- 1 | setName('rule:list') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to list firewall rules for.') 18 | ->setDescription('Show all firewall rules on a server.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $rules = $this->forge->firewallRules($input->getArgument('server')); 24 | 25 | $rows = array_map(function (FirewallRule $rule) { 26 | return [$rule->name, $rule->id, $rule->port, $rule->ipAddress]; 27 | }, $rules); 28 | 29 | $this->table($output, ['Name', 'Id', 'Port', 'IP Address'], $rows); 30 | 31 | return 0; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Commands/FirewallRules/Make.php: -------------------------------------------------------------------------------- 1 | 'name', 19 | 'port' => 'port', 20 | ]; 21 | 22 | public function configure(): void 23 | { 24 | $this->setName('rule:make') 25 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to create the firewall rule on.') 26 | ->addOption('name', null, InputOption::VALUE_REQUIRED, 'The name of the firewall rule.') 27 | ->addOption('port', null, InputOption::VALUE_REQUIRED, 'The port to create the firewall rule for.') 28 | ->setDescription('Create a new firewall rule.'); 29 | } 30 | 31 | public function execute(InputInterface $input, OutputInterface $output): int 32 | { 33 | $this->forge->createFirewallRule( 34 | $input->getArgument('server'), $this->fillData($input->getOptions()), false 35 | ); 36 | 37 | return 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Commands/FirewallRules/Show.php: -------------------------------------------------------------------------------- 1 | setName('rule:show') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the firewall rule to show information about is on.') 17 | ->addArgument('rule', InputArgument::REQUIRED, 'The id of the firewall rule to show information about.') 18 | ->setDescription('Show information about the given firewall rule.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $rule = $this->forge->firewallRule($input->getArgument('server'), $input->getArgument('rule')); 24 | 25 | $output->writeln([ 26 | 'Name: '.$rule->name, 27 | 'IP Address: '.$rule->ipAddress, 28 | 'Port: '.$rule->port, 29 | 'Status: '.$rule->status, 30 | 'Created: '.$rule->createdAt, 31 | ]); 32 | 33 | return 0; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Commands/Jobs/Delete.php: -------------------------------------------------------------------------------- 1 | setName('job:delete') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server where the site is.') 18 | ->addArgument('job', InputArgument::REQUIRED, 'The id of the job to delete.') 19 | ->setDescription('Delete a scheduled job.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $job = $input->getArgument('job'); 25 | 26 | $helper = $this->getHelper('question'); 27 | $question = new ConfirmationQuestion('Are you sure you want to delete the scheduled job with id "'.$job.'"?', false); 28 | 29 | if (!$helper->ask($input, $output, $question)) { 30 | $output->writeln('Ok, aborting. Your scheduled job is safe.'); 31 | } else { 32 | $this->forge->deleteJob($input->getArgument('server'), $job); 33 | } 34 | 35 | return 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Commands/Jobs/ListAll.php: -------------------------------------------------------------------------------- 1 | setName('job:list') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to list the jobs for.') 18 | ->setDescription('Show all jobs configured on a server.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $this->table($output, ['Id', 'Command', 'User', 'Frequency', 'Created'], array_map(function (Job $job) { 24 | return [$job->id, $job->name, $job->user, $job->frequency, $job->createdAt]; 25 | }, $this->forge->jobs($input->getArgument('server')))); 26 | 27 | return 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Commands/Jobs/Make.php: -------------------------------------------------------------------------------- 1 | 'command', 19 | 'user' => 'user', 20 | 'frequency' => 'frequency', 21 | 'minute' => 'minute', 22 | 'hour' => 'hour', 23 | 'day' => 'day', 24 | 'month' => 'month', 25 | 'weekday' => 'weekday', 26 | ]; 27 | 28 | public function configure(): void 29 | { 30 | $this->setName('job:make') 31 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to schedule a new job for.') 32 | ->addOption('user', null, InputOption::VALUE_REQUIRED, 'The user that will be executing the command.', 'forge') 33 | ->addOption('command', null, InputOption::VALUE_REQUIRED, 'The command to schedule.') 34 | ->addOption('frequency', null, InputOption::VALUE_REQUIRED, 'With what frequency should the command run? Valid values are "minutely", "hourly", "nightly", "weekly", "monthly", and "custom".', 'custom') 35 | ->addOption('minute', null, InputOption::VALUE_REQUIRED, 'The minute to run the scheduled job on. Only required when using the "custom" frequency.', '*') 36 | ->addOption('hour', null, InputOption::VALUE_REQUIRED, 'The hour to run the scheduled job on. Only required when using the "custom" frequency.', '*') 37 | ->addOption('day', null, InputOption::VALUE_REQUIRED, 'The day to run the scheduled job on. Only required when using the "custom" frequency.', '*') 38 | ->addOption('month', null, InputOption::VALUE_REQUIRED, 'The month to run the scheduled job on. Only required when using the "custom" frequency.', '*') 39 | ->addOption('weekday', null, InputOption::VALUE_REQUIRED, 'The weekday to run the scheduled job on. Only required when using the "custom" frequency.', '*') 40 | ->setDescription('Schedule a new job on one of your servers.'); 41 | } 42 | 43 | public function execute(InputInterface $input, OutputInterface $output): int 44 | { 45 | if (strtolower($input->getOption('frequency')) !== 'custom') { 46 | $this->requireOptions($input, 'minute', 'hour', 'day', 'month', 'weekday'); 47 | } 48 | 49 | $this->forge->createJob( 50 | $input->getArgument('server'), 51 | $this->fillData($input->getOptions()), 52 | false 53 | ); 54 | 55 | return 0; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Commands/Jobs/Show.php: -------------------------------------------------------------------------------- 1 | setName('job:show') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the scheduled job is on.') 17 | ->addArgument('job', InputArgument::REQUIRED, 'The id of the scheduled job to show information about.') 18 | ->setDescription('Show information about a scheduled job on a specified server.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $job = $this->forge->job( 24 | $input->getArgument('server'), $input->getArgument('job') 25 | ); 26 | 27 | $output->writeln([ 28 | 'Command: '.$job->name, 29 | 'Frequency: '.$job->frequency, 30 | 'Cron: '.$job->cron, 31 | 'User: '.$job->user, 32 | 'Status: '.$job->status, 33 | 'Created: '.$job->createdAt, 34 | ]); 35 | 36 | return 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Commands/NginxConfig/Get.php: -------------------------------------------------------------------------------- 1 | setName('nginx-config:get') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 17 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to get the config script for.') 18 | ->setDescription('Show the nginx configuration file.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $config = $this->forge->siteNginxFile( 24 | $input->getArgument('server'), $input->getArgument('site') 25 | ); 26 | 27 | $output->writeln($config); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Commands/NginxConfig/Set.php: -------------------------------------------------------------------------------- 1 | setName('nginx-config:set') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 18 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site you want to update the nginx config of.') 19 | ->addOption('file', null, InputOption::VALUE_REQUIRED, 'The path to your new nginx config file.') 20 | ->setDescription('Update the nginx config script of the given site.'); 21 | } 22 | 23 | public function execute(InputInterface $input, OutputInterface $output): int 24 | { 25 | $this->forge->updateSiteNginxFile( 26 | $input->getArgument('server'), $input->getArgument('site'), $this->getFileContent($input, 'file') 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Commands/Projects/DeleteGit.php: -------------------------------------------------------------------------------- 1 | setName('git:delete') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 18 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to delete the git project from.') 19 | ->setDescription('Delete a git project from a site.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $site = $input->getArgument('site'); 25 | 26 | $helper = $this->getHelper('question'); 27 | $question = new ConfirmationQuestion('Are you sure you want to delete the git project from the site with id "'.$site.'"?', false); 28 | 29 | if (!$helper->ask($input, $output, $question)) { 30 | $output->writeln('Ok, aborting. Your git project is safe.'); 31 | } else { 32 | $this->forge->destroySiteGitRepository($input->getArgument('server'), $site); 33 | } 34 | 35 | return 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Commands/Projects/DeleteWordpress.php: -------------------------------------------------------------------------------- 1 | setName('wordpress:delete') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 18 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to delete the WordPress project from.') 19 | ->setDescription('Delete a WordPress project from a site.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $site = $input->getArgument('site'); 25 | 26 | $helper = $this->getHelper('question'); 27 | $question = new ConfirmationQuestion('Are you sure you want to delete the WordPress project from the site with id "'.$site.'"?', false); 28 | 29 | if (!$helper->ask($input, $output, $question)) { 30 | $output->writeln('Ok, aborting. Your WordPress project is safe.'); 31 | } else { 32 | $this->forge->removeWordPress($input->getArgument('server'), $site); 33 | } 34 | 35 | return 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Commands/Projects/InstallGit.php: -------------------------------------------------------------------------------- 1 | 'provider', 19 | 'repository' => 'repository', 20 | 'branch' => 'branch', 21 | ]; 22 | 23 | public function configure(): void 24 | { 25 | $this->setName('git:install') 26 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 27 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to install the git project on.') 28 | ->addOption('provider', null, InputOption::VALUE_REQUIRED, 'The provider to use. Must be either "github" or "custom".', 'github') 29 | ->addOption('repository', null, InputOption::VALUE_REQUIRED, 'The repository to install. Must be in the format "username/repository".') 30 | ->addOption('branch', null, InputOption::VALUE_OPTIONAL, 'The branch to install. Must be in the format "master".', 'master') 31 | ->setDescription('Install a new git project on a site.'); 32 | } 33 | 34 | public function execute(InputInterface $input, OutputInterface $output): int 35 | { 36 | $this->forge->installGitRepositoryOnSite( 37 | $input->getArgument('server'), 38 | $input->getArgument('site'), 39 | $this->fillData($input->getOptions()) 40 | ); 41 | 42 | return 0; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Commands/Projects/InstallWordpress.php: -------------------------------------------------------------------------------- 1 | setName('wordpress:install') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 18 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to install the WordPress project on.') 19 | ->addOption('database', null, InputOption::VALUE_REQUIRED, 'The name of the database to use.') 20 | ->addOption('user', null, InputOption::VALUE_REQUIRED, 'The name of the user to create.') 21 | ->setDescription('Install a new WordPress project on a site.'); 22 | } 23 | 24 | public function execute(InputInterface $input, OutputInterface $output): int 25 | { 26 | $this->forge->installWordPress( 27 | $input->getArgument('server'), 28 | $input->getArgument('site'), 29 | $this->fillData($input->getOptions()) 30 | ); 31 | 32 | return 0; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Commands/QuickDeploy/Disable.php: -------------------------------------------------------------------------------- 1 | setName('quickdeploy:disable') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 17 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to disable quick deployment for.') 18 | ->setDescription('Disable quick deployment on the given site.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $this->forge->disableQuickDeploy( 24 | $input->getArgument('server'), $input->getArgument('site') 25 | ); 26 | 27 | return 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Commands/QuickDeploy/Enable.php: -------------------------------------------------------------------------------- 1 | setName('quickdeploy:enable') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 17 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to enable quick deployment for.') 18 | ->setDescription('Enable quick deployment on the given site.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $this->forge->enableQuickDeploy( 24 | $input->getArgument('server'), $input->getArgument('site') 25 | ); 26 | 27 | return 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Commands/Recipes/Delete.php: -------------------------------------------------------------------------------- 1 | setName('recipe:delete') 17 | ->addArgument('recipe', InputArgument::REQUIRED, 'The id of the recipe to delete.') 18 | ->setDescription('Delete one of your recipes.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $recipe = $input->getArgument('recipe'); 24 | 25 | $helper = $this->getHelper('question'); 26 | $question = new ConfirmationQuestion('Are you sure you want to delete the recipe with id "'.$recipe.'"?', false); 27 | 28 | if (!$helper->ask($input, $output, $question)) { 29 | $output->writeln('Ok, aborting. Your recipe is safe.'); 30 | } else { 31 | $this->forge->deleteRecipe($recipe); 32 | } 33 | 34 | return 0; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Commands/Recipes/ListAll.php: -------------------------------------------------------------------------------- 1 | setName('recipe:list') 16 | ->setDescription('Show all recipes in your Forge account.'); 17 | } 18 | 19 | public function execute(InputInterface $input, OutputInterface $output): int 20 | { 21 | $this->table($output, ['Id', 'Command', 'User', 'Created'], array_map(function (Recipe $recipe) { 22 | return [$recipe->id, $recipe->name, $recipe->user, $recipe->createdAt]; 23 | }, $this->forge->recipes())); 24 | 25 | return 0; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Commands/Recipes/Make.php: -------------------------------------------------------------------------------- 1 | 'name', 18 | 'user' => 'user', 19 | ]; 20 | 21 | public function configure(): void 22 | { 23 | $this->setName('recipe:make') 24 | ->addOption('name', null, InputOption::VALUE_REQUIRED, 'The name of the recipe.') 25 | ->addOption('user', null, InputOption::VALUE_REQUIRED, 'The user the recipe should run as.', 'root') 26 | ->addOption('script', null, InputOption::VALUE_REQUIRED, 'The contents of the recipe.') 27 | ->setDescription('Create a new recipe.'); 28 | } 29 | 30 | public function execute(InputInterface $input, OutputInterface $output): int 31 | { 32 | $payload = $this->fillData($input->getOptions()); 33 | 34 | $payload['script'] = $this->getFileContent($input, 'script'); 35 | 36 | $this->forge->createRecipe($payload); 37 | 38 | return 0; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Commands/Recipes/Run.php: -------------------------------------------------------------------------------- 1 | setName('recipe:run') 17 | ->addArgument('recipe', InputArgument::REQUIRED, 'The id of the recipe to run.') 18 | ->addOption('server', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'The id of the server(s) to run the recipe on.') 19 | ->setDescription('Run one of your recipes.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $this->forge->runRecipe( 25 | $input->getArgument('recipe'), $input->getOption('server') 26 | ); 27 | 28 | return 0; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Commands/Recipes/Show.php: -------------------------------------------------------------------------------- 1 | setName('recipe:show') 16 | ->addArgument('recipe', InputArgument::REQUIRED, 'The id of the recipe to show information about.') 17 | ->setDescription('Show information about a recipe.'); 18 | } 19 | 20 | public function execute(InputInterface $input, OutputInterface $output): int 21 | { 22 | $recipe = $this->forge->recipe( 23 | $input->getArgument('recipe') 24 | ); 25 | 26 | $output->writeln([ 27 | 'Name: '.$recipe->name, 28 | 'User: '.$recipe->user, 29 | 'Created: '.$recipe->createdAt, 30 | ]); 31 | 32 | return 0; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Commands/Recipes/Update.php: -------------------------------------------------------------------------------- 1 | setName('recipe:update') 17 | ->addArgument('recipe', InputArgument::REQUIRED, 'The id of the recipe to update.') 18 | ->addOption('name', null, InputOption::VALUE_REQUIRED, 'The new name of the recipe.') 19 | ->addOption('user', null, InputOption::VALUE_REQUIRED, 'The new user to run the recipe as.') 20 | ->addOption('script', null, InputOption::VALUE_REQUIRED, 'The new contents of the recipe.') 21 | ->setDescription('Update the given recipe.'); 22 | } 23 | 24 | public function execute(InputInterface $input, OutputInterface $output): int 25 | { 26 | $payload = $this->fillData($input->getOptions()); 27 | 28 | $payload['script'] = $this->getFileContent($input, 'script'); 29 | 30 | $this->forge->updateRecipe( 31 | $input->getArgument('recipe'), $payload 32 | ); 33 | 34 | return 0; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Commands/Servers/Delete.php: -------------------------------------------------------------------------------- 1 | setName('server:delete') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to delete.') 18 | ->setDescription('Delete a server.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $server = $input->getArgument('server'); 24 | 25 | $helper = $this->getHelper('question'); 26 | $question = new ConfirmationQuestion('Are you sure you want to delete the server with id "'.$server.'"?', false); 27 | 28 | if (!$helper->ask($input, $output, $question)) { 29 | $output->writeln('Ok, aborting. Your server is safe.'); 30 | } else { 31 | $this->forge->deleteServer($server); 32 | } 33 | 34 | return 0; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Commands/Servers/ListAll.php: -------------------------------------------------------------------------------- 1 | setName('server:list') 16 | ->setDescription('Show all servers associated with your account.'); 17 | } 18 | 19 | public function execute(InputInterface $input, OutputInterface $output): int 20 | { 21 | $rows = array_map(function (Server $server) { 22 | return [$server->name, $server->id, $server->ipAddress, $server->region, $server->isReady ? 'Yes' : 'No']; 23 | }, $this->forge->servers()); 24 | 25 | $this->table($output, ['Name', 'Id', 'IP Address', 'Region', 'Ready'], $rows); 26 | 27 | return 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Commands/Servers/Make.php: -------------------------------------------------------------------------------- 1 | 'provider', 18 | 'credentials' => 'credential_id', 19 | 'region' => 'region', 20 | 'ip' => 'ip_address', 21 | 'private-ip' => 'private_ip_address', 22 | 'php' => 'php_version', 23 | 'database' => 'database', 24 | 'install-maria' => 'maria', 25 | 'load-balancer' => 'load_balancer', 26 | 'network' => 'network', 27 | ]; 28 | 29 | public function configure(): void 30 | { 31 | $this->setName('server:make') 32 | ->addOption('provider', null, InputOption::VALUE_REQUIRED, 'The provider to provision the server on. Can be either "ocean2", "linode", "aws", or "custom".', 'ocean2') 33 | ->addOption('credentials', 'C', InputOption::VALUE_REQUIRED, 'Credentials to use. Not required when using the "custom" provider.') 34 | ->addOption('region', null, InputOption::VALUE_REQUIRED, 'The region to provision the server in. Not required when using the "custom" provider.') 35 | ->addOption('ip', null, InputOption::VALUE_REQUIRED, 'IP address of the server. Required when using the "custom" provider.') 36 | ->addOption('private-ip', null, InputOption::VALUE_REQUIRED, 'Private IP address of the server. Required when using the "custom" provider.') 37 | ->addOption('php', null, InputOption::VALUE_REQUIRED, 'PHP version to install when provisioning the server. Supported versions are "php56", "php70", and "php71".') 38 | ->addOption('database', null, InputOption::VALUE_REQUIRED, 'The name of the database to create when provisioning the server.', 'forge') 39 | ->addOption('install-maria', null, InputOption::VALUE_NONE, 'Whether MariaDB should be installed. If left out, MySQL will be installed by default.') 40 | ->addOption('load-balancer', null, InputOption::VALUE_NONE, 'Whether the server should be provisioned as a load balancer.') 41 | ->addOption('network', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Other servers\' ids this one can network with.') 42 | ->setDescription('Create a new server.'); 43 | } 44 | 45 | public function execute(InputInterface $input, OutputInterface $output): int 46 | { 47 | $this->forge->createServer( 48 | $this->fillData($input->getOptions()) 49 | ); 50 | 51 | return 0; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Commands/Servers/Reboot.php: -------------------------------------------------------------------------------- 1 | setName('server:reboot') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to reboot.') 18 | ->setDescription('Reboot one of your servers.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $server = $input->getArgument('server'); 24 | 25 | $helper = $this->getHelper('question'); 26 | $question = new ConfirmationQuestion('Are you sure you want to reboot the server with id "'.$server.'"?', false); 27 | 28 | if (!$helper->ask($input, $output, $question)) { 29 | $output->writeln('Ok, aborting.'); 30 | } else { 31 | $this->forge->rebootServer($server); 32 | } 33 | 34 | return 0; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Commands/Servers/Show.php: -------------------------------------------------------------------------------- 1 | setName('server:show') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to show information about.') 17 | ->setDescription('Show information about one of your servers.'); 18 | } 19 | 20 | public function execute(InputInterface $input, OutputInterface $output): int 21 | { 22 | $server = $this->forge->server($input->getArgument('server')); 23 | 24 | $output->writeln([ 25 | 'Name: '.$server->name, 26 | 'IP Address: '.$server->ipAddress, 27 | 'Size: '.$server->size, 28 | 'Region: '.$server->region, 29 | 'PHP version: '.$server->phpVersion, 30 | 'Created: '.$server->createdAt, 31 | ]); 32 | 33 | return 0; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Commands/Servers/Update.php: -------------------------------------------------------------------------------- 1 | 'name', 19 | 'size' => 'size', 20 | 'ip' => 'ip_address', 21 | 'private-ip' => 'private_ip_address', 22 | 'max-upload-size' => 'max_upload_size', 23 | 'network' => 'network', 24 | ]; 25 | 26 | public function configure(): void 27 | { 28 | $this->setName('server:update') 29 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to update.') 30 | ->addOption('name', null, InputOption::VALUE_REQUIRED, 'The name of the server.') 31 | ->addOption('size', null, InputOption::VALUE_REQUIRED, 'The amount of RAM the server has.') 32 | ->addOption('ip', null, InputOption::VALUE_REQUIRED, 'The server\'s IP address.') 33 | ->addOption('private-ip', null, InputOption::VALUE_REQUIRED, 'The server\'s private IP address.') 34 | ->addOption('max-upload-size', 'M', InputOption::VALUE_REQUIRED, 'The configured max upload size on the server.') 35 | ->addOption('network', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Other servers\' ids this one can network with.') 36 | ->setDescription('Update the metadata on one of your servers.'); 37 | } 38 | 39 | public function execute(InputInterface $input, OutputInterface $output): int 40 | { 41 | $this->forge->updateServer( 42 | $input->getArgument('server'), $this->fillData($input->getOptions()) 43 | ); 44 | 45 | return 0; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Commands/Services/Install.php: -------------------------------------------------------------------------------- 1 | 'server_id', 19 | 'server-token' => 'server_token', 20 | ]; 21 | 22 | /** 23 | * @var array 24 | */ 25 | protected $papertrailMap = [ 26 | 'host' => 'host', 27 | ]; 28 | 29 | public function configure(): void 30 | { 31 | $this->setName('service:install') 32 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to install the service on.') 33 | ->addArgument('service', InputArgument::REQUIRED, 'The service to be installed. Can be "blackfire" or "papertrail".') 34 | ->addOption('server-id', null, InputOption::VALUE_REQUIRED, 'Blackfire\'s server id. Only required when installing Blackfire.') 35 | ->addOption('server-token', null, InputOption::VALUE_REQUIRED, 'Blackfire\'s server token. Only required when installing Blackfire.') 36 | ->addOption('host', null, InputOption::VALUE_REQUIRED, 'Papertrail\'s host option. Only required when installing Papertrail.') 37 | ->setDescription('Install a service on a server.'); 38 | } 39 | 40 | public function execute(InputInterface $input, OutputInterface $output): int 41 | { 42 | $service = strtolower($input->getArgument('service')); 43 | $server = $input->getArgument('server'); 44 | $options = $input->getOptions(); 45 | 46 | switch ($service) { 47 | case 'blackfire': 48 | $this->forge->installBlackfire($server, $this->fillData($options, $this->blackfireMap)); 49 | break; 50 | 51 | case 'papertrail': 52 | $this->forge->installPapertrail($server, $this->fillData($options, $this->papertrailMap)); 53 | break; 54 | } 55 | 56 | return 0; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Commands/Services/Reboot.php: -------------------------------------------------------------------------------- 1 | setName('service:reboot') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to reboot the service on.') 18 | ->addArgument('service', InputArgument::REQUIRED, 'The service to reboot. Can be either "nginx", "mysql" or "postgres".') 19 | ->setDescription('Reboot a service on a server.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $service = strtolower($input->getArgument('service')); 25 | $server = $input->getArgument('server'); 26 | 27 | $helper = $this->getHelper('question'); 28 | $question = new ConfirmationQuestion('Are you sure you want to reboot '.$service.' on the server with id '.$server.'?', false); 29 | 30 | if (!$helper->ask($input, $output, $question)) { 31 | $output->writeln('Ok, aborting.'); 32 | 33 | return 0; 34 | } 35 | 36 | switch ($service) { 37 | case 'mysql': 38 | $this->forge->rebootMysql($server); 39 | break; 40 | case 'nginx': 41 | $this->forge->rebootNginx($server); 42 | break; 43 | case 'postgres': 44 | $this->forge->rebootPostgres($server); 45 | break; 46 | } 47 | 48 | return 0; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Commands/Services/Stop.php: -------------------------------------------------------------------------------- 1 | setName('service:stop') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to stop the service on.') 18 | ->addArgument('service', InputArgument::REQUIRED, 'The service to stop. Can be either "nginx", "mysql" or "postgres".') 19 | ->setDescription('Stop a service on a server.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $service = strtolower($input->getArgument('service')); 25 | $server = $input->getArgument('server'); 26 | 27 | $helper = $this->getHelper('question'); 28 | $question = new ConfirmationQuestion('Are you sure you want to stop '.$service.' on the server with id '.$server.'?', false); 29 | 30 | if (!$helper->ask($input, $output, $question)) { 31 | $output->writeln('Ok, aborting.'); 32 | 33 | return 0; 34 | } 35 | 36 | switch ($service) { 37 | case 'mysql': 38 | $this->forge->stopMysql($server); 39 | break; 40 | case 'nginx': 41 | $this->forge->stopNginx($server); 42 | break; 43 | case 'postgres': 44 | $this->forge->stopPostgres($server); 45 | break; 46 | } 47 | 48 | return 0; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Commands/Services/Uninstall.php: -------------------------------------------------------------------------------- 1 | setName('service:uninstall') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to uninstall the service from.') 18 | ->addArgument('service', InputArgument::REQUIRED, 'The service to be uninstalled. Can be "blackfire" or "papertrail".') 19 | ->setDescription('Uninstall a service from a server.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $server = $input->getArgument('server'); 25 | $service = strtolower($input->getArgument('service')); 26 | 27 | $helper = $this->getHelper('question'); 28 | $question = new ConfirmationQuestion('Are you sure you want to uninstall '.$service.' from the server with id '.$server.'?', false); 29 | 30 | if (!$helper->ask($input, $output, $question)) { 31 | $output->writeln('Ok, aborting.'); 32 | 33 | return 0; 34 | } 35 | 36 | switch ($service) { 37 | case 'blackfire': 38 | $this->forge->removeBlackfire($server); 39 | break; 40 | 41 | case 'papertrail': 42 | $this->forge->removePapertrail($server); 43 | break; 44 | } 45 | 46 | return 0; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Commands/Sites/Delete.php: -------------------------------------------------------------------------------- 1 | setName('site:delete') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server where the site is.') 18 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to delete.') 19 | ->setDescription('Delete a site.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $site = $input->getArgument('site'); 25 | 26 | $helper = $this->getHelper('question'); 27 | $question = new ConfirmationQuestion('Are you sure you want to delete the site with id "'.$site.'"?', false); 28 | 29 | if (!$helper->ask($input, $output, $question)) { 30 | $output->writeln('Ok, aborting. Your site is safe.'); 31 | } else { 32 | $this->forge->deleteSite($input->getArgument('server'), $site); 33 | } 34 | 35 | return 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Commands/Sites/Deploy.php: -------------------------------------------------------------------------------- 1 | setName('site:deploy') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site to deploy is on.') 17 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to deploy.') 18 | ->setDescription('Deploy the given website.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $this->forge->deploySite( 24 | $input->getArgument('server'), $input->getArgument('site') 25 | ); 26 | 27 | return 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Commands/Sites/ListAll.php: -------------------------------------------------------------------------------- 1 | setName('site:list') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to list the sites for.') 18 | ->setDescription('Show all sites installed on a server.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $this->table($output, ['Id', 'Name', 'Type', 'Repository', 'Branch'], array_map(function (Site $site) { 24 | return [$site->id, $site->name, $site->projectType, $site->repository ?: '-', $site->repositoryBranch ?: '-']; 25 | }, $this->forge->sites($input->getArgument('server')))); 26 | 27 | return 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Commands/Sites/Make.php: -------------------------------------------------------------------------------- 1 | 'domain', 19 | 'type' => 'project_type', 20 | 'directory' => 'directory', 21 | 'isolated' => 'isolated', 22 | 'alias' => 'aliases', 23 | ]; 24 | 25 | public function configure(): void 26 | { 27 | $this->setName('site:make') 28 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to create a new site on.') 29 | ->addOption('domain', null, InputOption::VALUE_REQUIRED, 'The domain of your new site.') 30 | ->addOption('type', null, InputOption::VALUE_REQUIRED, 'The type of application to install on the site. Can be either "php", "html", "Symfony", or "symfony_dev".', 'php') 31 | ->addOption('directory', null, InputOption::VALUE_REQUIRED, 'The base directory of the site.', '/public') 32 | ->addOption('isolated', null, InputOption::VALUE_NONE, 'Whether or not to use website isolation.') 33 | ->addOption('alias', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'The aliases assigned to the site.') 34 | ->setDescription('Create a new site on one of your servers.'); 35 | } 36 | 37 | public function execute(InputInterface $input, OutputInterface $output): int 38 | { 39 | $this->forge->createSite( 40 | $input->getArgument('server'), 41 | $this->fillData($input->getOptions()), 42 | false 43 | ); 44 | 45 | return 0; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Commands/Sites/Show.php: -------------------------------------------------------------------------------- 1 | setName('site:show') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 17 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to show information about.') 18 | ->setDescription('Show information about a site on a specified server.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $site = $this->forge->site( 24 | $input->getArgument('server'), $input->getArgument('site') 25 | ); 26 | 27 | $output->writeln([ 28 | 'Name: '.$site->name, 29 | 'Repository info: '.$site->repository.' @ '.$site->repositoryBranch, 30 | 'Directory: '.$site->directory, 31 | 'Quick deploy: '.($site->quickDeploy ? 'On' : 'Off'), 32 | 'Status: '.$site->status, 33 | 'Project type: '.$site->projectType, 34 | 'Created: '.$site->createdAt, 35 | ]); 36 | 37 | return 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Commands/Sites/Update.php: -------------------------------------------------------------------------------- 1 | 'directory', 19 | ]; 20 | 21 | public function configure(): void 22 | { 23 | $this->setName('site:update') 24 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the site is on.') 25 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the server to update.') 26 | ->addOption('directory', null, InputOption::VALUE_REQUIRED, 'The new base directory of the website.') 27 | ->setDescription('Update a site on a specified server.'); 28 | } 29 | 30 | public function execute(InputInterface $input, OutputInterface $output): int 31 | { 32 | $this->forge->updateSite( 33 | $input->getArgument('server'), $input->getArgument('site'), $this->fillData($input->getOptions()) 34 | ); 35 | 36 | return 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Commands/SshKeys/Delete.php: -------------------------------------------------------------------------------- 1 | setName('key:delete') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server where the SSH key is.') 18 | ->addArgument('key', InputArgument::REQUIRED, 'The id of the SSH key to delete.') 19 | ->setDescription('Delete an SSH key.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $key = $input->getArgument('key'); 25 | 26 | $helper = $this->getHelper('question'); 27 | $question = new ConfirmationQuestion('Are you sure you want to delete the SSH key with id "'.$key.'"?', false); 28 | 29 | if (!$helper->ask($input, $output, $question)) { 30 | $output->writeln('Ok, aborting. Your SSH key is safe.'); 31 | } else { 32 | $this->forge->deleteSSHKey($input->getArgument('server'), $key); 33 | } 34 | 35 | return 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Commands/SshKeys/ListAll.php: -------------------------------------------------------------------------------- 1 | setName('key:list') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to list SSH keys for.') 18 | ->setDescription('Show all SSH keys installed on a server.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $this->table($output, ['Id', 'Name', 'Status', 'Created'], array_map(function (SSHKey $key) { 24 | return [$key->id, $key->name, $key->status, $key->createdAt]; 25 | }, $this->forge->keys($input->getArgument('server')))); 26 | 27 | return 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Commands/SshKeys/Make.php: -------------------------------------------------------------------------------- 1 | 'name', 19 | ]; 20 | 21 | public function configure(): void 22 | { 23 | $this->setName('key:make') 24 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to create a new SSH key on.') 25 | ->addOption('name', null, InputOption::VALUE_REQUIRED, 'The name of your new SSH key.') 26 | ->addOption('file', null, InputOption::VALUE_REQUIRED, 'The path to the SSH key to install on the server.') 27 | ->setDescription('Install a new SSH key on one of your servers.'); 28 | } 29 | 30 | public function execute(InputInterface $input, OutputInterface $output): int 31 | { 32 | $data = $this->fillData($input->getOptions()); 33 | 34 | $data['key'] = $this->getFileContent($input, 'file'); 35 | 36 | $this->forge->createSSHKey( 37 | $input->getArgument('server'), $data, false 38 | ); 39 | 40 | return 0; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Commands/SshKeys/Show.php: -------------------------------------------------------------------------------- 1 | setName('key:show') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the SSH key is on.') 17 | ->addArgument('key', InputArgument::REQUIRED, 'The id of the SSH key to show information about.') 18 | ->setDescription('Show information about an SSH key on a specified server.'); 19 | } 20 | 21 | public function execute(InputInterface $input, OutputInterface $output): int 22 | { 23 | $key = $this->forge->SSHKey( 24 | $input->getArgument('server'), $input->getArgument('key') 25 | ); 26 | 27 | $output->writeln([ 28 | 'Name: '.$key->name, 29 | 'Status: '.$key->status, 30 | 'Created: '.$key->createdAt, 31 | ]); 32 | 33 | return 0; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Commands/Workers/Delete.php: -------------------------------------------------------------------------------- 1 | setName('worker:delete') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the database is on.') 18 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site the worker to delete is on.') 19 | ->addArgument('worker', InputArgument::REQUIRED, 'The id of the worker to delete.') 20 | ->setDescription('Delete the given worker.'); 21 | } 22 | 23 | public function execute(InputInterface $input, OutputInterface $output): int 24 | { 25 | $worker = $input->getArgument('worker'); 26 | 27 | $helper = $this->getHelper('question'); 28 | $question = new ConfirmationQuestion('Are you sure you want to delete the worker with id "'.$worker.'"?', false); 29 | 30 | if (!$helper->ask($input, $output, $question)) { 31 | $output->writeln('Ok, aborting. Your worker is safe.'); 32 | } else { 33 | $this->forge->deleteWorker( 34 | $input->getArgument('server'), $input->getArgument('site'), $worker 35 | ); 36 | } 37 | 38 | return 0; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Commands/Workers/ListAll.php: -------------------------------------------------------------------------------- 1 | setName('worker:list') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to list the workers for.') 18 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site the worker is on.') 19 | ->setDescription('Show all workers.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $rows = array_map(function (Worker $worker) { 25 | return [$worker->id, $worker->connection, $worker->status, $worker->createdAt]; 26 | }, $this->forge->workers($input->getArgument('server'), $input->getArgument('site'))); 27 | 28 | $this->table($output, ['Id', 'Connection', 'Status', 'Created'], $rows); 29 | 30 | return 0; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Commands/Workers/Make.php: -------------------------------------------------------------------------------- 1 | 'connection', 19 | 'timeout' => 'timeout', 20 | 'sleep' => 'sleep', 21 | 'tries' => 'tries', 22 | 'daemon' => 'daemon', 23 | ]; 24 | 25 | public function configure(): void 26 | { 27 | $this->setName('worker:make') 28 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to create the worker on.') 29 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site to install the worker on.') 30 | ->addOption('connection', null, InputOption::VALUE_REQUIRED, 'The connection to start the worker on.') 31 | ->addOption('timeout', null, InputOption::VALUE_REQUIRED, 'The timeout for the worker in seconds.', 90) 32 | ->addOption('sleep', null, InputOption::VALUE_REQUIRED, 'The time in seconds to sleep if the queue is empty.', 60) 33 | ->addOption('tries', null, InputOption::VALUE_REQUIRED, 'How often the worker should try processing a job.', null) 34 | ->addOption('daemon', null, InputOption::VALUE_NONE, 'Whether the worker should be installed as a daemon.') 35 | ->setDescription('Create a new worker.'); 36 | } 37 | 38 | public function execute(InputInterface $input, OutputInterface $output): int 39 | { 40 | $this->forge->createWorker( 41 | $input->getArgument('server'), $input->getArgument('site'), $this->fillData($input->getOptions()), false 42 | ); 43 | 44 | return 0; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Commands/Workers/Reboot.php: -------------------------------------------------------------------------------- 1 | setName('worker:reboot') 17 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server the worker to reboot is on.') 18 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site the worker to reboot is on.') 19 | ->addArgument('worker', InputArgument::REQUIRED, 'The id of the worker to reboot.') 20 | ->setDescription('Reboot one of your workers.'); 21 | } 22 | 23 | public function execute(InputInterface $input, OutputInterface $output): int 24 | { 25 | $worker = $input->getArgument('worker'); 26 | 27 | $helper = $this->getHelper('question'); 28 | $question = new ConfirmationQuestion('Are you sure you want to reboot the worker with id "'.$worker.'"?', false); 29 | 30 | if (!$helper->ask($input, $output, $question)) { 31 | $output->writeln('Ok, aborting.'); 32 | } else { 33 | $this->forge->restartWorker( 34 | $input->getArgument('server'), $input->getArgument('site'), $worker, false 35 | ); 36 | } 37 | 38 | return 0; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Commands/Workers/Show.php: -------------------------------------------------------------------------------- 1 | setName('worker:show') 16 | ->addArgument('server', InputArgument::REQUIRED, 'The id of the server to the database is running on.') 17 | ->addArgument('site', InputArgument::REQUIRED, 'The id of the site the worker is running on.') 18 | ->addArgument('worker', InputArgument::REQUIRED, 'The id of the worker to show information about.') 19 | ->setDescription('Show information about the given worker.'); 20 | } 21 | 22 | public function execute(InputInterface $input, OutputInterface $output): int 23 | { 24 | $worker = $this->forge->worker( 25 | $input->getArgument('server'), $input->getArgument('site'), $input->getArgument('worker') 26 | ); 27 | 28 | $output->writeln([ 29 | 'Status: '.$worker->status, 30 | 'Connection: '.$worker->connection, 31 | 'Timeout: '.$worker->timeout, 32 | 'Command: '.$worker->command, 33 | 'Daemon: '.$worker->daemon ? 'Yes' : 'No', 34 | 'Created: '.$worker->createdAt, 35 | ]); 36 | 37 | return 0; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Contracts/NeedsForge.php: -------------------------------------------------------------------------------- 1 |