Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 27 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -383,35 +383,42 @@ assembles it from the Git log.

## Automatic Deployment to Pantheon

In order to deploy upon every merge automatically using GitHub Actions, you shall:
### Prerequisites

1. Initiate QA (`qa` branch) multidev environment for the given project.
The GitHub Actions workflows for automatic deployment are already configured in the repository. You just need to set up the necessary credentials.

### Setup Steps

In order to deploy upon every merge automatically using GitHub Actions:

1. Ensure QA (`qa` branch) multidev environment exists for the given project. This is automatically created during bootstrap, or can be created manually.
1. Double-check if `./.ddev/providers/pantheon.yaml` contains the proper Pantheon project name.
1. Get a [Pantheon machine token](https://pantheon.io/docs/machine-tokens) (using a dummy new Pantheon user ideally, one user per project for the sake of security)
1. Get a GitHub Personal access token. It will be used to post a comment to GitHub to the relevant issue when a merged PR is deployed, so set the expiry date far in the future enough for this.
1. `ddev robo deploy:config-autodeploy [your terminus token] [your github token]`
1. `git commit -m "Deployment secrets and configuration"`
1. Add the public key in `pantheon-key.pub` to the newly created dummy [Pantheon user](https://pantheon.io/docs/ssh-keys)
1. Set up the following in your GitHub repository settings:

**GitHub Secrets** (Settings → Secrets and variables → Actions → Secrets):
- `TERMINUS_TOKEN`: Your Pantheon machine token
- `PANTHEON_DEPLOY_KEY`: The SSH private key for deployment
- `GH_TOKEN`: GitHub personal access token for posting deployment comments

**GitHub Variables** (Settings → Secrets and variables → Actions → Variables):
- `PANTHEON_GIT_URL`: The Pantheon Git URL for your project
- `ROLLBAR_SERVER_TOKEN`: Your Rollbar server token (optional)
- `DEPLOY_EXCLUDE_WARNING`: Warnings to exclude from deployment notifications (optional)
1. Run the autodeploy configuration command:
```bash
ddev robo deploy:config-autodeploy [your terminus token] [your github token]
```

1. Actualize `public static string $githubProject = 'Gizra/the-client';` in the `RoboFile.php`.
This will generate an SSH key pair and provide instructions for setting up GitHub Secrets and Variables.

1. Follow the instructions provided by the command to:
- Add the SSH public key (`pantheon-key.pub`) to your [Pantheon account](https://pantheon.io/docs/ssh-keys)
- Set up GitHub Secrets (TERMINUS_TOKEN, PANTHEON_DEPLOY_KEY, GH_TOKEN)
- Set up GitHub Variables (PANTHEON_GIT_URL, ROLLBAR_SERVER_TOKEN, DEPLOY_EXCLUDE_WARNING)

**Note**: If you used the `bootstrap:project` command to create your project, the `$githubProject` variable in `DeploymentTrait.php` is automatically updated with your organization and project name. Otherwise, you'll need to manually update `public static string $githubProject = 'YourOrg/your-project';` in `robo-components/DeploymentTrait.php`.

Optionally you can specify which target branch you'd like to push on Pantheon, by default it's `master`, so the target is the DEV environment, but alternatively you can issue:
`ddev robo deploy:config-autodeploy [your terminus token] [your github token] [pantheon project name] [gh_branch] [pantheon_branch]`
```bash
ddev robo deploy:config-autodeploy [your terminus token] [your github token] [github_deploy_branch] [pantheon_deploy_branch]
```

### Tag-based Deployments

After you have automatic deployment for a project, you are able to deploy to Pantheon `test` and `live` using Git tags.
`git tag 0.1.2` will imply a deployment to the `test` environment (and `dev` - as enforced by Pantheon).
`git tag 0.1.2_live` will imply a deployment to `live`. In order to make it fast, you need to first create the tag that deploy to `test`, then you need to tag the same commit with a tag suffixed with `_live`.
- `git tag 0.1.2` will imply a deployment to the `test` environment (and `dev` - as enforced by Pantheon).
- `git tag 0.1.2_live` will imply a deployment to `live`. In order to make it fast, you need to first create the tag that deploy to `test`, then you need to tag the same commit with a tag suffixed with `_live`.

### Excluding Warnings in Deployment

Expand Down
22 changes: 17 additions & 5 deletions robo-components/BootstrapTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,23 @@ public function bootstrapProject(string $project_name, string $github_repository
$this->taskExec("terminus secrets:set $project_machine_name.dev tfa $tfa_secret")->run();

$this->say("Bootstrap completed successfully.");
$this->say("You might want to run the following commands to properly place the project:");
$this->say("mv .bootstrap ../$project_machine_name");
$this->say("mv .pantheon ../$project_machine_name/.pantheon");
$this->say("To configure autodeployment to Pantheon run:");
$this->say("ddev robo deploy:config-autodeploy $terminus_token $github_token");
$this->say("");
$this->say("Next steps:");
$this->say("1. Move the project to its final location:");
$this->say(" mv .bootstrap ../$project_machine_name");
$this->say(" mv .pantheon ../$project_machine_name/.pantheon");
$this->say("");
$this->say("2. Configure automatic deployment to Pantheon with GitHub Actions:");
$this->say(" cd ../$project_machine_name");
$this->say(" ddev robo deploy:config-autodeploy $terminus_token $github_token");
$this->say("");
$this->say(" This will generate SSH keys and provide instructions for:");
$this->say(" - Setting up GitHub Secrets (TERMINUS_TOKEN, PANTHEON_DEPLOY_KEY, GH_TOKEN)");
$this->say(" - Setting up GitHub Variables (PANTHEON_GIT_URL, ROLLBAR_SERVER_TOKEN)");
$this->say(" - Adding the SSH public key to your Pantheon account");
$this->say("");
$this->say("For full deployment setup details, see:");
$this->say("https://github.com/$organization/$project_machine_name#automatic-deployment-to-pantheon");
}

/**
Expand Down
64 changes: 20 additions & 44 deletions robo-components/DeploymentTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -720,63 +720,39 @@ public function deployConfigAutodeploy(string $token, string $github_token, stri
throw new \Exception('The key generation failed.');
}

// Encrypt the SSH key for use in GitHub Actions.
$result = $this->taskExec('openssl rand -hex 32')->printOutput(FALSE)->run();
if ($result->getExitCode() !== 0) {
throw new \Exception('Failed to generate encryption key.');
}
$encryption_key = trim($result->getMessage());

$result = $this->taskExec('openssl rand -hex 16')->printOutput(FALSE)->run();
if ($result->getExitCode() !== 0) {
throw new \Exception('Failed to generate encryption IV.');
}
$encryption_iv = trim($result->getMessage());

$result = $this->taskExec("openssl aes-256-cbc -K $encryption_key -iv $encryption_iv -in pantheon-key -out pantheon-key.enc")->run();
if ($result->getExitCode() !== 0) {
throw new \Exception('The encryption of the private key failed.');
}

$result = $this->taskExec("terminus connection:info $project_name.dev --fields='Git Command' --format=string | awk '{print $3}'")
->printOutput(FALSE)
->run();
$pantheon_git_url = trim($result->getMessage());

// Update GitHub Actions workflows if they exist.
if (file_exists('.github/workflows/lint.template.yml')) {
$this->_exec("cp .github/workflows/lint.template.yml .github/workflows/lint.yml");
$this->taskReplaceInFile('.github/workflows/lint.yml')
->from('{{ GITHUB_DEPLOY_BRANCH }}')
->to($github_deploy_branch)
->run();
}

$result = $this->taskExec('git add pantheon-key.enc')->run();
if ($result->getExitCode() !== 0) {
throw new \Exception("git add failed.");
}

$this->say("The project was prepared for automatic deployment to Pantheon using GitHub Actions");
$this->say("");
$this->say("Please complete the following steps:");
$this->say("");
$this->say("1. Add the following secrets to your GitHub repository:");
$this->say(" - Go to: Settings → Secrets and variables → Actions → New repository secret");
$this->say(" - PANTHEON_GIT_URL: " . $pantheon_git_url);
$this->say(" - TERMINUS_TOKEN: " . $token);
$this->say(" - ENCRYPTED_KEY: " . $encryption_key);
$this->say(" - ENCRYPTED_IV: " . $encryption_iv);
$this->say(" - GITHUB_TOKEN: (use the automatically provided token or your personal token)");
$this->say(" - ROLLBAR_SERVER_TOKEN: (your Rollbar token if applicable)");
$this->say("");
$this->say("2. Add the SSH public key to the Pantheon account:");
$this->say("1. Add the SSH public key to the Pantheon account:");
$this->say(" - Key location: pantheon-key.pub");
$this->say(" - Instructions: https://pantheon.io/docs/ssh-keys");
$this->say("");
$this->say("3. Review and commit the encrypted key file (pantheon-key.enc)");
$this->say("2. Set up the following GitHub Secrets:");
$this->say(" - Go to: Settings → Secrets and variables → Actions → Secrets → New repository secret");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Can we automate it with gh CLI? If yes, we can install it on-demand inside DDEV and help the user to accomplish this!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! Added gh CLI automation in commit 82479da.

The command now:

  • Detects if gh CLI is available
  • Offers to automatically set up GitHub Secrets (TERMINUS_TOKEN, PANTHEON_DEPLOY_KEY, GH_TOKEN) and Variables (PANTHEON_GIT_URL)
  • Falls back to manual instructions if gh CLI is not available or user declines

The gh CLI can be installed on-demand in DDEV, and users will be prompted to confirm before any secrets are set.

$this->say(" - TERMINUS_TOKEN: " . $token);
$this->say(" - PANTHEON_DEPLOY_KEY: (paste the contents of pantheon-key file)");
$this->say(" - GH_TOKEN: " . $github_token);
$this->say("");
$this->say("3. Set up the following GitHub Variables:");
$this->say(" - Go to: Settings → Secrets and variables → Actions → Variables → New repository variable");
$this->say(" - PANTHEON_GIT_URL: " . $pantheon_git_url);
$this->say(" - ROLLBAR_SERVER_TOKEN: (your Rollbar token, optional)");
$this->say(" - DEPLOY_EXCLUDE_WARNING: (warnings to exclude, optional)");
$this->say("");
$this->say("4. IMPORTANT: Keep the pantheon-key file secure and DO NOT commit it to the repository.");
$this->say(" You only need to add its contents as the PANTHEON_DEPLOY_KEY secret in GitHub.");
$this->say("");
$this->say("5. After setting up secrets and variables, you can delete the pantheon-key files locally.");
$this->say("");
$this->say("6. Ensure nested docroot is configured: https://pantheon.io/docs/nested-docroot");
$this->say("");
$this->say("4. Ensure nested docroot is configured: https://pantheon.io/docs/nested-docroot");
$this->say("For more details, see the 'Automatic Deployment to Pantheon' section in README.md");
}

/**
Expand Down