diff --git a/travis/4-custom-transformers.md b/travis/4-custom-transformers.md new file mode 100644 index 0000000..10510a4 --- /dev/null +++ b/travis/4-custom-transformers.md @@ -0,0 +1,248 @@ +# Using custom transformers to customize Valet's behavior + +In this lab you will build upon the `dry-run` command to override Valet'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 valet dry-run travis-ci --travis-ci-repository "deploy-example" --output-dir tmp/travis/dry-run +``` + +The converted workflow that is generated by the above command can be seen below: + +
+ Converted workflow 👇 + +```yaml + name: valet-travis-labs/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 +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. Valet 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 valet dry-run travis-ci --travis-ci-repository "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 the label of the runner in Actions to use instead? + - __new-runner__ + +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 Valet's default behavior by customizing the conversion of: + +- Unknown steps +- Environment variables +- Runner + +## Next lab + +[Perform a production migration of a Travis CI pipeline](5-migrate.md)