pulumi / actions

Deploy continuously to your cloud of choice, using your favorite language, Pulumi, and GitHub!
Apache License 2.0
258 stars 72 forks source link

[Epic] JavaScript-based GitHub Action: GA #40

Closed stack72 closed 3 years ago

stack72 commented 3 years ago

Updated by @infin8x on February 3 with our new epic issue template

Work items

Design and specification đź“”

Engineering ⚙️

Release coordinator: TBD

Objective and Key Results

stack72 commented 3 years ago

I wanted to update this issue with the design doc that we wrote for the new JavaScript based GHA - this is the direction that we will be moving in going forward

Pulumi GitHub Action V2

Goal:

The goal is to eliminate the dockerfile GitHub Action and replace it with a native JavaScript based GitHub Action. This will mean the action is faster and doesn’t download large docker containers each time the action is triggered

Background:

GitHub Actions can either be JavaScript based or Dockerfile based. In the dockerfile based action, the entry point is defined by a bash script. The current GitHub Action, uses a Dockerfile that builds on top of the [large] Pulumi docker container. This container needs to be continually updated to support new features and grows each time this is done. It takes approximately 3minutes to run the Action due to the time taken to run the container. JavaScript based actions are much faster to run as they are not all packaged into a single container and doesn’t require the build / warm-up time

The Pulumi container packages all of the following components:

These are all pinned to specific versions that the users cannot control themselves. This means users are at the mercy of a Pulumi docker release before they can use newer versions of tooling. This also makes users at the mercy of Pulumi to patch vulnerabilities in versions of software.

A JavaScript based Pulumi action would allow the user to control their own CI pipeline by installing their own versions of the tools they need. They would use the Pulumi Action to interact with the Pulumi CLI

Implementation:

Pulumi now has an automation api that will allow us to use in the JavaScript based action. The current features of the GitHub Action support:

We can offload a lot of the current logic around npm / yarn / pip3 / gcloud-auth to other GitHub Actions e.g. GoogleCloudPlatform/github-actions/setup-gcloud

The current action setup in GitHub looks as follows:

name: Pulumi
on:
  - pull_request
jobs:
  preview:
    name: Preview
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: pulumi/actions@v1.0.0
        with:
          command: preview
        env:
          GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}
          PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}
          PULUMI_STACK_NAME: dev

In this case, the user has no control over the Python version, whether it uses pip3 or pyenv or even how to login to their Google Cloud account. The user cannot even control the version of Pulumi that they need to use as it’s pre-packaged. We can make this action, much more scoped to a specific language or a specific version of tooling as follows:

name: Pulumi
on:
  - pull_request

env:
  PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}

jobs:
  preview:
    name: Preview
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-python@v2
        with:
          python-version: '3.x'
      - run: pip install -r requirements.txt
      - uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
        with:
          version: '285.0.0'
          project_id: ${{ secrets.GCP_PROJECT_ID }}
          service_account_email: ${{ secrets.GCP_SA_EMAIL }}
          service_account_key: ${{ secrets.GCP_SA_KEY }}
      - name: Install pulumi
        uses: pulumi/action-install-pulumi-cli@v1.0.1
        with:
          pulumi-version: 2.16.2
      - uses: pulumi/actions@v2.0.0
        with:
          command: preview
          stack_name: dev

This gives the user much more control and the action will be much faster as it doesn’t need to run a large container on each action.

The last benefit of moving to a JavaScript based action is that we can take advantage of the native workflows in GitHub. Currently, the action has the following logic packaged:

# Not all PR events warrant running a preview. Many of them pertain to changes in assignments and
# ownership, but we only want to run the preview if the action is "opened", "edited", or "synchronize".
PR_ACTION=$(jq -r ".action" < $GITHUB_EVENT_PATH)
if [ "$PR_ACTION" != "opened" ] && [ "$PR_ACTION" != "edited" ] && [ "$PR_ACTION" != "synchronize" ]; then
    echo -e "PR event ($PR_ACTION) contains no changes and does not warrant a Pulumi Preview"
    echo -e "Skipping Pulumi action altogether..."
    exit 0
fi

This is taking away the control over when the action will actually trigger when a change to a PR has been made. We want to remove this type of logic and allow the user to specify their own logic for this type of run as part of the “on” GitHub Action event.

infin8x commented 3 years ago

Status week of February 1, 2021: 🟢

stack72 commented 3 years ago

Last 2 pieces needed:

simenandre commented 3 years ago

Last 2 pieces needed:

  • Add ability to pulumi login

    • if pulumi-access-token then pulumi login to the Saas
    • if cloud-url specified then login to that specific backend (this action will not need access keys, things like AZURE_STORAGE_ACCOUNT_NAME will be set as environment variables)
  • if comment-on-pr is set then we will write pulumi output back to the PR

Done 👆 🎉

simenandre commented 3 years ago

Just noticed an issue, will fix today: Warning: Unexpected input(s) 'cloud-url', valid inputs are ['command', 'stack-name', 'work-dir', 'comment-on-pr', 'github-token']

simenandre commented 3 years ago
  • Add Publish scripts to ensure that v2.x.x also gets tagged as v2

IMO, there are two options for this.

a) We use Semantic Release (see a full example here). With this setup, every commit pushed to main or master would be analyzed and if there are commit messages that follow some commit message spec, such as conventional commits it would be tagged according to that spec. Benefits are that contributions from the community are released once their PRs are merged, maintainers do not have to tag anything. We only need to make sure the title of our PRs are according to specs, if we squash merge PRs. Semantic Release does not support tagging v2 out of the box (check semantic-release/semantic-release#1515), but look at the fix here: https://github.com/cobraz/setup-variables/blob/main/.github/workflows/release.yml

b) Add a script/workflow that runs every release which parses major version of the tag, and runs this command: git push HEAD:refs/heads/v<insert tag>

Working example of that: https://github.com/cobraz/setup-variables/blob/f72eddbdf75f9533d27335087c1567364a974ee6/.github/workflows/release.yml#L30-L34

Relevant tool: https://github.com/marketplace/actions/actions-tagger

stack72 commented 3 years ago

I am happy to go with your thoughts on this - it seems like b) is the simplest path for now right?

simenandre commented 3 years ago

For now, I would recommend trying out actions-tagger. Semantic Release is nice, and I use it for most of my personal projects. However, there are drawbacks to continuously releasing – and honestly, a discussion that can be postponed until this product is running.

infin8x commented 3 years ago

Closing this since the new version (and supporting blog post and docs) are live!