Search code examples
githubgithub-actionsenvironment

GitHub Actions: How to dynamically set environment url based on deployment step output?


I found out about a really nice GitHub Actions Feature called Environments. Using the appropriate syntax a Environment could also be created inside a GitHub Action workflow.yml like this:

environment:
  name: test_environment
  url: https://your-apps-url-here.com

As the docs state thats a valid way to create GitHub Action Environments:

Running a workflow that references an environment that does not exist will create an environment with the referenced name.

But inside my current GitHub Action workflow is there a way I dynamically set the url based on a deployment step output? I have a dynamic URL resulting from the deployment process to AWS which I can't define up-front.


Solution

  • The job workflow docs tell us that there's also a way of using expressions inside the url field:

    environment:
      name: test_environment
      url: ${{ steps.step_name.outputs.url_output }}
    

    Now imagine a ci.yml workflow file that uses AWS CLI to deploy a static website to S3, where we used a tool like Pulumi to dynamically create a S3 Bucket inside our AWS account. We can read the dynamically created S3 url using the following command pulumi stack output bucketName. The deploy step inside the ci.yml could then look like this:

      - name: Deploy Nuxt.js generated static site to S3 Bucket via AWS CLI
        id: aws-sync
        run: |
          aws s3 sync ../dist/ s3://$(pulumi stack output bucketName) --acl public-read
          echo "s3_url=http://$(pulumi stack output bucketUrl)" >> $GITHUB_OUTPUT
        working-directory: ./deployment
    

    There are 2 crucial points here: First we should use id inside the deployment step to define a step name we could easily access via step_name inside our environment:url. Second we need to define a step output using echo "s3_url=http://$(pulumi stack output bucketUrl)" >> $GITHUB_OUTPUT. In this example I create a variable s3_url. You could replace the pulumi stack output bucketUrl with any other command you'd like or tool you use, which responds with your dynamic environment url.

    Be also sure to add a http:// or https:// in order to prevent an error message like this:

    Environment URL 'microservice-ui-nuxt-js-hosting-bucket-bc75fce.s3-website.eu-central-1.amazonaws.com' is not a valid http(s) URL, so it will not be shown as a link in the workflow graph.
    

    Now the environment definition at the top of our ci.yml can access the s3_url output variable from our deployment step like this:

    jobs:
      ci:
        runs-on: ubuntu-latest
    
        environment:
          name: microservice-ui-nuxt-js-deployment
          url: ${{ steps.aws-sync.outputs.s3_url }}
    
        steps:
          - name: Checkout
            ...
    

    Using steps.aws-sync we reference the deployment step directly, since we defined it with the id. The appended .outputs.s3_url then directly references the variable containing our S3 url. If you defined everything correctly the GitHub Actions UI will render the environment URL directly below the finished job:

    enter image description here

    Here's also a fully working workflow embedded inside a example project.

    Update: The set-output name=VARNAME::VALUE notation is deprecated and produces the following output (thanks Rob for pointing that out!):

    Warning: The `set-output` command is deprecated and will be disabled soon. Please upgrade to using Environment Files. For more information see: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/