# Using custom transformers to customize GitHub Actions Importer's behavior In this lab you will build upon the `dry-run` command to override GitHub Actions Importer's default behavior and customize the converted workflow using "custom transformers". Custom transformers can be used to: 1. Convert items that are not automatically converted. 2. Convert items that were automatically converted using different actions. 3. Convert environment variable values differently. 4. Convert references to runners to use a different runner name in Actions. ## Prerequisites 1. Followed the steps [here](./readme.md#configure-your-codespace) to set up your GitHub Codespaces environment. 2. Completed the [configure lab](./1-configure.md#configuring-credentials). 3. Completed the [dry-run lab](./3-dry-run.md). ## Perform a dry-run You will be performing a `dry-run` command to inspect the workflow that is converted by default. Run the following command within the codespace terminal: ```bash gh actions-importer dry-run travis-ci --travis-ci-repository "travisci-deploy-example" --output-dir tmp/dry-run ``` The converted workflow that is generated by the above command can be seen below:
Converted workflow 👇 ```yaml name: actions-importer-labs/travisci-deploy-example on: push: branches: - "**/*" pull_request: concurrency: # # This item has no matching transformer # maximum_number_of_builds: 0 env: DB: mysql jobs: test: runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v2 - run: gem install bundler - run: bundle install --jobs=3 --retry=3 - run: rake - run: echo 'ready?' # # This item has no matching transformer # - codedeploy: # provider: codedeploy # access_key_id: YOUR AWS ACCESS KEY # secret_access_key: YOUR AWS SECRET KEY # bucket: S3 Bucket # key: latest/MyApp.zip # application: MyApp # deployment_group: MyDeploymentGroup # if: "${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}" - run: "./after_deploy_1.sh" - run: "./after_deploy_2.sh" - uses: desiderati/github-action-pushover@v1 with: job-status: "${{ job.status }}" pushover-api-token: '12345' pushover-user-key: "${{ secrets.PUSHOVER_USER_KEY }}" if: "${{ github.event_name != 'pull_request' }}" ```
_Note_: You can refer to the previous [lab](./3-dry-run.md) to learn about the fundamentals of the `dry-run` command. ## Custom transformers for an unknown step The converted workflow above contains an `codedeploy` step that was not automatically converted. Answer the following questions before writing a custom transformer: 1. What is the "identifier" of the step to customize? - __codedeploy__ 2. What is the desired Actions syntax to use instead? - After some research, you have determined that we can login to AWS with the `aws-actions/configure-aws-credentials@v1` action, and deploy the app to AWS using a run step to replace the functionality of `codedeploy`: ```yaml - uses: aws-actions/configure-aws-credentials@v1 with: role-to-assume: owner role-session-name: GitHub-Action-Role aws-region: east-2 - run: | echo "Deploying branch ${{ env.GITHUB_REF }} to ${{ github.event.inputs.environment }}" commit_hash=`git rev-parse HEAD` aws deploy create-deployment --application-name MyApp --deployment-group-name MyDeploymentGroup --github-location repository=$GITHUB_REPOSITORY,commitId=$commit_hash --ignore-application-stop-failures ``` Now you can begin to write the custom transformer. Custom transformers use a DSL built on top of Ruby and should be defined in a file with the `.rb` file extension. You can create this file by running the following command in your codespace terminal: ```bash touch transformers.rb && code transformers.rb ``` Next, you will define a `transform` method for the `codedeploy` identifier by adding the following code to `transformers.rb`: ```ruby transform "codedeploy" do |_item| [ { "uses" => "aws-actions/configure-aws-credentials@v1", "with" => { "role-to-assume" => "owner", "role-session-name" => "GitHub-Action-Role", "aws-region" => "east-2" } }, { "run" => "echo \"Deploying branch ${{ env.GITHUB_REF }} to ${{ github.event.inputs.environment }}\"\ncommit_hash=`git rev-parse HEAD`\naws deploy create-deployment --application-name MyApp --deployment-group-name MyDeploymentGroup --github-location repository=$GITHUB_REPOSITORY,commitId=$commit_hash --ignore-application-stop-failures\n" } ] end ``` This method can use any valid ruby syntax and should return a `Hash`, or an array of `Hashes` that represent the YAML that should be generated for a given step. GitHub Actions Importer will use this method to convert a step with the provided identifier and will use the `item` parameter for the original values configured in Travis CI. Now you can perform another `dry-run` command and use the `--custom-transformers` CLI option to provide this custom transformer. Run the following command within your codespace terminal: ```bash gh actions-importer dry-run travis-ci --travis-ci-repository "travisci-deploy-example" --output-dir tmp/travis/dry-run --custom-transformers transformers.rb ``` The converted workflow that is generated by the above command will now use the custom logic for the `codedeploy` step. ```diff - # # This item has no matching transformer - # - codedeploy: - # provider: codedeploy - # access_key_id: YOUR AWS ACCESS KEY - # secret_access_key: YOUR AWS SECRET KEY - # bucket: S3 Bucket - # key: latest/MyApp.zip - # application: MyApp - # deployment_group: MyDeploymentGroup - # if: "${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}" + - uses: aws-actions/configure-aws-credentials@v1 + with: + role-to-assume: owner + role-session-name: GitHub-Action-Role + aws-region: east-2 + - run: | + echo "Deploying branch ${{ env.GITHUB_REF }} to ${{ github.event.inputs.environment }}" + commit_hash=`git rev-parse HEAD` + aws deploy create-deployment --application-name MyApp --deployment-group-name MyDeploymentGroup --github-location repository=$GITHUB_REPOSITORY,commitId=$commit_hash --ignore-application-stop-failures ``` _Note_: We hard coded certain values such as the `application-name`, but we can apply these properties programmatically as well by using the item passed into the transform method. If you were unsure what the data structure of `item` was, you could use the following code in the custom transformer to print `item` to the console: ```ruby transform "codecov_codecov_upload" do |item| puts item end ``` ## Custom transformers for environment variables You can use custom transformers to edit the values of environment variables in converted workflows. In this example, you will update the `DB` environment variable to be `sqlite` instead of `mysql`. To do this, add the following code to the `transformers.rb` file. ```ruby env "DB", "sqlite" ``` In this example, the first parameter to the `env` method is the environment variable name and the second is the updated value. Now you can perform another `dry-run` command with the `--custom-transformers` CLI option. When you open the converted workflow the `DB` environment variable will be set to `sqlite`: ```diff env: - DB: "mysql" + DB: "sqlite" ``` ## Custom transformers for runners Finally, you can use custom transformers to dictate which runners converted workflows should use. First, answer the following questions: 1. What is the label of the runner in Travis to update? - __linux__ 2. What is/are the label(s) of the runner(s) in Actions to use instead? - __new-runner__, __self-hosted__ With these questions answered, you can add the following code to the `transformers.rb` file: ```ruby runner "linux", ["new-runner", "self-hosted"] ``` In this example, the first parameter to the `runner` method is the Azure DevOps label and the second is the Actions runner labels. Now you can perform another `dry-run` command with the `--custom-transformers` CLI option. When you open the converted workflow, the `runs-on` statement will use the customized runner labels: ```diff - runs-on: ubuntu-latest + runs-on: + - new-runner + - self-hosted ``` At this point, the file contents of `transformers.rb` should match this:
Custom transformers 👇 ```ruby transform "codedeploy" do |_item| [ { "uses": "aws-actions/configure-aws-credentials@v1", "with": { "role-to-assume": "owner", "role-session-name": "GitHub-Action-Role", "aws-region": "east-2" } }, { "run": "echo \"Deploying branch ${{ env.GITHUB_REF }} to ${{ github.event.inputs.environment }}\"\ncommit_hash=`git rev-parse HEAD`\naws deploy create-deployment --application-name MyApp --deployment-group-name MyDeploymentGroup --github-location repository=$GITHUB_REPOSITORY,commitId=$commit_hash --ignore-application-stop-failures\n" } ] end env "DB", "sqlite" runner "linux", ["new-runner", "self-hosted"] ```
That's it! Congratulations, you have overridden GitHub Actions Importer's default behavior by customizing the conversion of: - Unknown steps - Environment variables - Runners ## Next lab [Perform a production migration of a Travis CI pipeline](6-migrate.md)