preview-action icon indicating copy to clipboard operation
preview-action copied to clipboard

Dynamically Provision GitHub Environments, Deployments, and Deployment Statuses

Open axisofentropy opened this issue 2 years ago • 4 comments

We can enhance our customers' experiences on GitHub by specifying Environments and Deployments on GitHub from within our reusable workflow and/or GitHub Actions. Read about them here https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment

Because we want to provision these dynamically, we probably cannot use the easy YAML syntax within GitHub Actions. We can talk to GitHub's REST API directly, either using curl or the gh CLI api command. I wasn't able to find an action in the Marketplace for this, but search for one before implementing!

Design: We should consider whether we want to create a single "Uffizzi" Environment and separate Deployments within it, or create Environments for each Uffizzi Deployment. Test both cases and explore the UX within GitHub.

GitHub Environments and Deployments should broadly follow the lifecycle of the Uffizzi Environments and Deployments they represent. Status updates should be posted before and after each uffizzi CLI invocation action. It's very important to include the URL of each environment everywhere possible.

Slack thread: https://uffizzi-internal.slack.com/archives/C85U32F3M/p1660238762177499

axisofentropy avatar Aug 11 '22 20:08 axisofentropy

REST API documentation:

  • Environments https://docs.github.com/en/rest/deployments/environments
  • Deployments https://docs.github.com/en/rest/deployments/deployments
  • Statuses https://docs.github.com/en/rest/deployments/statuses

Note that Statuses are immutable and immortal; they may only be created. Usually only the most recent Status is displayed in the GitHub UI.

axisofentropy avatar Aug 11 '22 20:08 axisofentropy

Example Environment Creation

adam@ephemeron:~/src/preview-action$ gh api --method PUT -H "Accept: application/vnd.github+json" /repos/UffizziCloud/example-voting-app/environments/deployment-333
{
  "id": 588408369,
  "node_id": "EN_kwDOHe4BRM4jEmYx",
  "name": "deployment-333",
  "url": "https://api.github.com/repos/UffizziCloud/example-voting-app/environments/deployment-333",
  "html_url": "https://github.com/UffizziCloud/example-voting-app/deployments/activity_log?environments_filter=deployment-333",
  "created_at": "2022-08-11T18:14:19Z",
  "updated_at": "2022-08-11T18:14:19Z",
  "protection_rules": [],
  "deployment_branch_policy": null
}```

axisofentropy avatar Aug 11 '22 20:08 axisofentropy

Example Deployment creation that failed for some unknown reason.

adam@ephemeron:~/src/preview-action$ gh api --method POST -H "Accept: application/vnd.github+json" /repos/UffizziCloud/example-voting-app/deployments -f ref='main' -f environment='deployment-333'
{
  "message": "Conflict: Commit status checks failed for main.",
  "errors": [
    {
      "contexts": [
        {
          "context": "Build and Push `vote`",
          "state": "success"
        },
        {
          "context": "Build and Push `worker`",
          "state": "success"
        },
        {
          "context": "Use Remote Workflow to Delete an Existing Preview",
          "state": "skipped"
        },
        {
          "context": "Build and Push `loadbalancer`",
          "state": "success"
        },
        {
          "context": "Build and Push `result`",
          "state": "success"
        },
        {
          "context": "Render Docker Compose File",
          "state": "success"
        },
        {
          "context": "Use Remote Workflow to Preview on Uffizzi",
          "state": "skipped"
        }
      ],
      "resource": "Deployment",
      "field": "required_contexts",
      "code": "invalid"
    }
  ],
  "documentation_url": "https://docs.github.com/rest/reference/repos#create-a-deployment"
}
gh: Conflict: Commit status checks failed for main. (HTTP 409)

axisofentropy avatar Aug 11 '22 20:08 axisofentropy

Note that some additional permissions may be required for our reusable workflow (or wherever we end up implementing this.) The workflow permission is probably deployments: write.

Also see this important note about "inactive" and "transient" deployments https://docs.github.com/en/rest/deployments/deployments#inactive-deployments

axisofentropy avatar Aug 11 '22 20:08 axisofentropy