Sort by Topics, Resources
Clear
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Salto for

NetSuite

Articles

SHARE

An Introduction to CI/CD for SuiteScript Developers (Part 3) - Advanced GitHub Actions

Eric Grubaugh

July 17, 2023

9

min read

About Salto: Salto's platform helps you and your team deploy, track, and manage your NetSuite customizations effortlessly. Learn more here.

Introduction

In Part 2 of the CI/CD for NetSuite Developers series, we established a working pipeline using SDF and GitHub Actions to automatically unit test, validate, and deploy an SDF project when pushing new changes to a git repository. That pipeline consisted of a single Workflow with a single Job.

In all honesty, this foundational setup will likely be sufficient for the vast majority of SuiteScript development use cases; however, there are still valuable concepts and lessons that can be learned from ramping up the complexity of our pipeline. These are what we’ll explore in Part 3:

  • How to split a single Job into multiple Jobs
  • How to parallelize or serialize Jobs
  • How to create reusable Actions
  • How to dynamically select from multiple Environments
  • How to require manual approval of a Job

Experience the Ease & Confidence of NetSuite Customizations with Salto

Automate the way you migrate Jira configurations from sandbox to production

STAY UP TO DATE

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Splitting a Job

Our first Workflow consisted of a single Job which contained several sequential Steps; the Steps of a Job are always executed serially. As our Project grows—particularly as we add significant numbers of unit tests, files, and Objects—the Steps that interact with these elements will require increasing amounts of time and resources. For Projects of sufficient size, it may become beneficial to parallelize some of these Steps.

In order to parallelize these processes, we need to split the Steps into multiple Jobs. Let’s update our initial Workflow to contain three Jobs: one for running the unit tests, one for validating the SDF Project, and one for deploying the SDF Project.

Note: While developing these changes, ensure you are using a Sandbox environment. You may want to adjust the triggers for your Workflow so that you do not have to push on the main branch to see the results of your changes.

We’re going to leave the existing sdf-validate Job and give it two sibling Jobs: unit-test and sdf-deploy.


unit-test:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Install node
        uses: actions/setup-node@v3
        with:
          node-version: 'lts/*'
      - name: Install JDK
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'oracle'
      - name: Install package
        run: npm ci --acceptsuitecloudsdklicense
      - name: Run unit tests
        run: npm test


sdf-deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Install node
        uses: actions/setup-node@v3
        with:
          node-version: 'lts/*'
      - name: Install JDK
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'oracle'
      - name: Install package
        run: npm ci --acceptsuitecloudsdklicense
      - name: Authenticate project against ${{ vars.NS_ACCOUNT_ID }}
        run: ./node_modules/.bin/suitecloud account:savetoken --account ${{ vars.NS_ACCOUNT_ID }} --authid ${{ vars.NS_ACCOUNT_ID }} --tokenid ${{ secrets.NS_TOKEN_ID }} --tokensecret ${{ secrets.NS_TOKEN_SECRET }}
      - name: Deploy project to ${{ vars.NS_ACCOUNT_ID }}
        run: npm run deploy


sdf-validate:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Install node
        uses: actions/setup-node@v3
        with:
          node-version: 'lts/*'
      - name: Install JDK
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'oracle'
      - name: Install package
        run: npm ci --acceptsuitecloudsdklicense
      - name: Authenticate project against ${{ vars.NS_ACCOUNT_ID }}
        run: ./node_modules/.bin/suitecloud account:savetoken --account ${{ vars.NS_ACCOUNT_ID }} --authid ${{ vars.NS_ACCOUNT_ID }} --tokenid ${{ secrets.NS_TOKEN_ID }} --tokensecret ${{ secrets.NS_TOKEN_SECRET }}
      - name: Validate project against ${{ vars.NS_ACCOUNT_ID }}
        run: npm run validate

We’ve extracted the appropriate Steps from the original sdf-validate Job to their respective new Jobs—the npm test Step moved to the unit-test Job, and the deployment Step moved to the sdf-deploy Job.

Jobs are Self-Contained

Note the sdf-deploy Job needs to repeat the Authentication Step. Notice also that each Job repeats the same installation Steps (checkout, install node, etc). This is because each Job executes in its own Runner, completely separate from the other Jobs in the Workflow. Thus, each Job needs to install the Project’s prerequisites into its Runner. This is the primary performance trade-off for parallelizing Jobs; you’ll have to assess for your own situation whether this is worth it for your operations.

Jobs are Parallelized by Default

When triggering this updated Workflow, you should see that all three Jobs execute at the same time. By default, GitHub Actions executes in parallel all the Jobs within a Workflow. It’s nice that parallelization doesn’t require any special action or handling from us, but this may not be exactly what we want in all cases.

For instance, you probably don’t want to deploy if either your unit tests or Project validation fails, but that is currently what will happen. It’s OK if the tests and validation occur simultaneously, but we should wait for both to succeed before we deploy—otherwise they’re not really doing their jobs.

Using needs to Serialize Jobs

To ensure a Job executes after other Jobs, you can use a Job’s needs parameter.

The value for needs can be a single Job ID or an Array of Job IDs. In this case, we want the sdf-deploy Job to wait for both unit-test and sdf-validate to complete:


sdf-deploy:
    runs-on: ubuntu-latest
    environment: production
    needs: [unit-test, sdf-validate]

Now when you trigger this Workflow, unit-test and sdf-validate will run first in parallel, and if both succeed, sdf-deploy will run afterwards. If either fails, sdf-deploy will be skipped and the Workflow will exit. This is almost certainly a more desirable behavior for Production code.

Reducing Repetition with Composite Actions

If you’re currently shaking your fist and shouting the word DRY at me through your monitor, I feel you; there’s a lot of repetition in this code (but do remember that DRY is about repeated facts, not necessarily repeated code, and that premature abstraction is perhaps worse than repeated code).

Pedantic soapboxing aside, “How to set up the Runner for SDF” is definitely a repeated fact in our current configuration. To eliminate those repeated steps, we can extract the installation steps into our own custom Action which GitHub calls a composite action. The full reference documentation can be found here.

Creating the Action

Composite actions are defined in yet another YAML file named action.yml. This file could exist in the same repository or a separate one; for simplicity in this article, we’ll create our action in the same repository.

While the file must be named action.yml, it can live anywhere in our repository. For that reason, I think it makes sense to make a new actions folder under our existing .github/ directory as a sibling to our workflows directory. To differentiate this action.yml from any other custom actions we might want in this repository, let’s create it under .github/actions/sdf-install/:


mkdir -p .github/actions/sdf-install
touch .github/actions/sdf-install/action.yml

In the new action.yml, we can add the initial configuration for our composite action:


name: 'sdf-install'
description: 'Run common installation steps for a NetSuite SDF Project'
runs:
  using: 'composite'
steps:

Parameterizing the Action

Before we implement the steps, we need to examine them for any dynamic data they require. Most of the Steps are static, but in order to correctly authenticate, we need a NetSuite Account ID, Token ID, and Token Secret. Let’s add these values as parameters in our action so that we can pass in the requisite data.

The parameters for an Action are specified with the inputs property:


name: 'sdf-install'
description: 'Run common installation steps for a NetSuite SDF Project'
runs:
  using: 'composite'
inputs:
  ns-account-id:
    description: 'The Account ID of the target NetSuite environment'
    required: true
  ns-token-id:
    description: 'The Token ID for authenticating to the target NetSuite environment'
    required: true
  ns-token-secret:
    description: 'The Token Secret for authenticating to the target NetSuite environment'
    required: true
steps:

Implementing the Action

With our inputs in place, we can extract the repeated installation steps into the steps structure, then replace the old environment variable references with references to our new inputs:


name: 'sdf-install'
description: 'Run common installation steps for a NetSuite SDF Project'
runs:
  using: 'composite'
steps:
  - name: Install node
    uses: actions/setup-node@v3
    with:
      node-version: 'lts/*'
  - name: Install JDK
    uses: actions/setup-java@v3
    with:
      java-version: '17'
      distribution: 'oracle'
  - name: Install package
    run: npm ci --acceptsuitecloudsdklicense
    shell: bash
  - name: Authenticate project against ${{ inputs.ns-account-id }}
    run: ./node_modules/.bin/suitecloud account:savetoken --account ${{ inputs.ns-account-id }} --authid ${{ inputs.ns-account-id }} --tokenid ${{ inputs.ns-token-id }} --tokensecret ${{ inputs.ns-token-secret }}
    shell: bash

Notice that the checkout step is missing from our implementation. This is because the Action lives in the repository, so we can’t perform the Action without first checking out the repository. Thus, we’ll still have to perform the checkout step from each Job.

Invoke the Action

Back in sdf-validate.yml, we’re ready to replace the repeated installation steps with a single call to our new custom Action. In each of the three Jobs, our steps can now start like so:


steps:
  - uses: actions/checkout@v3
  - uses: ./.github/actions/sdf-install
    with:
      ns-account-id: ${{ vars.NS_ACCOUNT_ID }}
      ns-token-id: ${{ secrets.NS_TOKEN_ID }}
      ns-token-secret: ${{ secrets.NS_TOKEN_SECRET }}

We invoke Actions with the uses command. Within a uses command, inputs are specified using the with structure. Here we pass in the environment variables and secrets that we were previously specifying directly in our authentication Step.

Triggering our Workflow again, we should expect to see exactly the same behavior as before, but now with much less repeated configuration.

Working with Multiple Environments

For those of you embarking on this CI/CD journey with me, and for all NetSuite developers generally, I sincerely hope you have access to at least one non-Production account for learning and testing, though I know that’s not always the case. While the functionality of our pipeline is filling out nicely, it can only operate on a single, hard-coded environment. To change the pipeline from Sandbox to Production or back, you’d currently have to push a code change in the configuration file; that kind of manual interaction is the opposite of what we want from our automation pipeline.

Luckily for us, the environment property of a Job accepts not only names but expressions as well. This means we can dynamically select an Environment for a Job based on conditions or values set in the pipeline.

I prefer to follow a feature-branching strategy in my SuiteScript repositories, so ongoing development is done in feature branches while main is considered the stable, Production-ready code. Using that information, I can conditionally select which Environment my Jobs should use based on which branch has changed:

  • If main changes, select the Production Environment.
  • Otherwise, select the Sandbox Environment.

The branch name which triggered the Workflow is available in the github context’s ref_name property:


environment: ${{ github.ref_name == 'main' && 'production' || 'sandbox' }}

Enforcing a Manual Approval

In practice, you probably don’t want to continuously/automatically deploy to a Sandbox or Production account, unless you are a solo developer. If a team of developers is sharing the same account and working in the same repository which deploys every feature branch push, they’d constantly be overwriting each others’ changes.

You might, however, want to introduce a manual approval step into your pipeline to allow a gatekeeper to decide whether a build gets deployed or not. We can do so via the Required Approvers setting on an Environment.

By checking the Required reviewers box and specifying appropriate users in an Environment’s settings, GitHub will pause each Job that targets this Environment and wait for manual approval from the listed users. It will notify all approvers that a build is pending their review, and approvers can then jump into GitHub and provide their approval or rejection of a build.

For me, the behavior of this approval isn’t quite what I want as it will request approval on every Job within the Workflow. I’d prefer to incorporate an approval as a Step within a Job or Workflow instead (this is actually how CircleCI, a “competitor” of GitHub Actions, handles this process).

There is a third-party Action that purports to solve this problem, but it leverages the repository’s Issues to provide approvals, and that’s also not ideal for me. If you’re curious, I leave the investigation and setup of this Action to you as an exercise.

STAY UP TO DATE

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Conclusion

At this point, we have a strong and flexible foundation for automating the testing, validation, and deployment of our SuiteScript code. You can find this complete configuration in the Part 3 Release of my GitHub repository. 

From here, I hope you’ve seen enough that you feel comfortable and inspired to add and adapt this Workflow to your needs, and I hope it makes delivering your SuiteScript easier, faster, and more enjoyable.

WRITTEN BY OUR EXPERT

Eric Grubaugh

Senior NetSuite Developer

Since 2012, Eric has been designing and developing SuiteScript solutions, coaching NetSuite developers on doing the same, and advising SuiteScript teams on building healthy, effective practices. He also launched the SuiteScript Stories podcast.

Sort by Topics, Resources
Clear
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Salto for

NetSuite

NetSuite

SHARE

An Introduction to CI/CD for SuiteScript Developers (Part 3) - Advanced GitHub Actions

Eric Grubaugh

July 17, 2023

9

min read

About Salto: Salto's platform helps you and your team deploy, track, and manage your NetSuite customizations effortlessly. Learn more here.

Introduction

In Part 2 of the CI/CD for NetSuite Developers series, we established a working pipeline using SDF and GitHub Actions to automatically unit test, validate, and deploy an SDF project when pushing new changes to a git repository. That pipeline consisted of a single Workflow with a single Job.

In all honesty, this foundational setup will likely be sufficient for the vast majority of SuiteScript development use cases; however, there are still valuable concepts and lessons that can be learned from ramping up the complexity of our pipeline. These are what we’ll explore in Part 3:

  • How to split a single Job into multiple Jobs
  • How to parallelize or serialize Jobs
  • How to create reusable Actions
  • How to dynamically select from multiple Environments
  • How to require manual approval of a Job

What if Zendesk was 4x less work?

Request a Demo Get started with Salto

Splitting a Job

Our first Workflow consisted of a single Job which contained several sequential Steps; the Steps of a Job are always executed serially. As our Project grows—particularly as we add significant numbers of unit tests, files, and Objects—the Steps that interact with these elements will require increasing amounts of time and resources. For Projects of sufficient size, it may become beneficial to parallelize some of these Steps.

In order to parallelize these processes, we need to split the Steps into multiple Jobs. Let’s update our initial Workflow to contain three Jobs: one for running the unit tests, one for validating the SDF Project, and one for deploying the SDF Project.

Note: While developing these changes, ensure you are using a Sandbox environment. You may want to adjust the triggers for your Workflow so that you do not have to push on the main branch to see the results of your changes.

We’re going to leave the existing sdf-validate Job and give it two sibling Jobs: unit-test and sdf-deploy.


unit-test:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Install node
        uses: actions/setup-node@v3
        with:
          node-version: 'lts/*'
      - name: Install JDK
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'oracle'
      - name: Install package
        run: npm ci --acceptsuitecloudsdklicense
      - name: Run unit tests
        run: npm test


sdf-deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Install node
        uses: actions/setup-node@v3
        with:
          node-version: 'lts/*'
      - name: Install JDK
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'oracle'
      - name: Install package
        run: npm ci --acceptsuitecloudsdklicense
      - name: Authenticate project against ${{ vars.NS_ACCOUNT_ID }}
        run: ./node_modules/.bin/suitecloud account:savetoken --account ${{ vars.NS_ACCOUNT_ID }} --authid ${{ vars.NS_ACCOUNT_ID }} --tokenid ${{ secrets.NS_TOKEN_ID }} --tokensecret ${{ secrets.NS_TOKEN_SECRET }}
      - name: Deploy project to ${{ vars.NS_ACCOUNT_ID }}
        run: npm run deploy


sdf-validate:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: Install node
        uses: actions/setup-node@v3
        with:
          node-version: 'lts/*'
      - name: Install JDK
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'oracle'
      - name: Install package
        run: npm ci --acceptsuitecloudsdklicense
      - name: Authenticate project against ${{ vars.NS_ACCOUNT_ID }}
        run: ./node_modules/.bin/suitecloud account:savetoken --account ${{ vars.NS_ACCOUNT_ID }} --authid ${{ vars.NS_ACCOUNT_ID }} --tokenid ${{ secrets.NS_TOKEN_ID }} --tokensecret ${{ secrets.NS_TOKEN_SECRET }}
      - name: Validate project against ${{ vars.NS_ACCOUNT_ID }}
        run: npm run validate

We’ve extracted the appropriate Steps from the original sdf-validate Job to their respective new Jobs—the npm test Step moved to the unit-test Job, and the deployment Step moved to the sdf-deploy Job.

Jobs are Self-Contained

Note the sdf-deploy Job needs to repeat the Authentication Step. Notice also that each Job repeats the same installation Steps (checkout, install node, etc). This is because each Job executes in its own Runner, completely separate from the other Jobs in the Workflow. Thus, each Job needs to install the Project’s prerequisites into its Runner. This is the primary performance trade-off for parallelizing Jobs; you’ll have to assess for your own situation whether this is worth it for your operations.

Jobs are Parallelized by Default

When triggering this updated Workflow, you should see that all three Jobs execute at the same time. By default, GitHub Actions executes in parallel all the Jobs within a Workflow. It’s nice that parallelization doesn’t require any special action or handling from us, but this may not be exactly what we want in all cases.

For instance, you probably don’t want to deploy if either your unit tests or Project validation fails, but that is currently what will happen. It’s OK if the tests and validation occur simultaneously, but we should wait for both to succeed before we deploy—otherwise they’re not really doing their jobs.

Using needs to Serialize Jobs

To ensure a Job executes after other Jobs, you can use a Job’s needs parameter.

The value for needs can be a single Job ID or an Array of Job IDs. In this case, we want the sdf-deploy Job to wait for both unit-test and sdf-validate to complete:


sdf-deploy:
    runs-on: ubuntu-latest
    environment: production
    needs: [unit-test, sdf-validate]

Now when you trigger this Workflow, unit-test and sdf-validate will run first in parallel, and if both succeed, sdf-deploy will run afterwards. If either fails, sdf-deploy will be skipped and the Workflow will exit. This is almost certainly a more desirable behavior for Production code.

Reducing Repetition with Composite Actions

If you’re currently shaking your fist and shouting the word DRY at me through your monitor, I feel you; there’s a lot of repetition in this code (but do remember that DRY is about repeated facts, not necessarily repeated code, and that premature abstraction is perhaps worse than repeated code).

Pedantic soapboxing aside, “How to set up the Runner for SDF” is definitely a repeated fact in our current configuration. To eliminate those repeated steps, we can extract the installation steps into our own custom Action which GitHub calls a composite action. The full reference documentation can be found here.

Creating the Action

Composite actions are defined in yet another YAML file named action.yml. This file could exist in the same repository or a separate one; for simplicity in this article, we’ll create our action in the same repository.

While the file must be named action.yml, it can live anywhere in our repository. For that reason, I think it makes sense to make a new actions folder under our existing .github/ directory as a sibling to our workflows directory. To differentiate this action.yml from any other custom actions we might want in this repository, let’s create it under .github/actions/sdf-install/:


mkdir -p .github/actions/sdf-install
touch .github/actions/sdf-install/action.yml

In the new action.yml, we can add the initial configuration for our composite action:


name: 'sdf-install'
description: 'Run common installation steps for a NetSuite SDF Project'
runs:
  using: 'composite'
steps:

Parameterizing the Action

Before we implement the steps, we need to examine them for any dynamic data they require. Most of the Steps are static, but in order to correctly authenticate, we need a NetSuite Account ID, Token ID, and Token Secret. Let’s add these values as parameters in our action so that we can pass in the requisite data.

The parameters for an Action are specified with the inputs property:


name: 'sdf-install'
description: 'Run common installation steps for a NetSuite SDF Project'
runs:
  using: 'composite'
inputs:
  ns-account-id:
    description: 'The Account ID of the target NetSuite environment'
    required: true
  ns-token-id:
    description: 'The Token ID for authenticating to the target NetSuite environment'
    required: true
  ns-token-secret:
    description: 'The Token Secret for authenticating to the target NetSuite environment'
    required: true
steps:

Implementing the Action

With our inputs in place, we can extract the repeated installation steps into the steps structure, then replace the old environment variable references with references to our new inputs:


name: 'sdf-install'
description: 'Run common installation steps for a NetSuite SDF Project'
runs:
  using: 'composite'
steps:
  - name: Install node
    uses: actions/setup-node@v3
    with:
      node-version: 'lts/*'
  - name: Install JDK
    uses: actions/setup-java@v3
    with:
      java-version: '17'
      distribution: 'oracle'
  - name: Install package
    run: npm ci --acceptsuitecloudsdklicense
    shell: bash
  - name: Authenticate project against ${{ inputs.ns-account-id }}
    run: ./node_modules/.bin/suitecloud account:savetoken --account ${{ inputs.ns-account-id }} --authid ${{ inputs.ns-account-id }} --tokenid ${{ inputs.ns-token-id }} --tokensecret ${{ inputs.ns-token-secret }}
    shell: bash

Notice that the checkout step is missing from our implementation. This is because the Action lives in the repository, so we can’t perform the Action without first checking out the repository. Thus, we’ll still have to perform the checkout step from each Job.

Invoke the Action

Back in sdf-validate.yml, we’re ready to replace the repeated installation steps with a single call to our new custom Action. In each of the three Jobs, our steps can now start like so:


steps:
  - uses: actions/checkout@v3
  - uses: ./.github/actions/sdf-install
    with:
      ns-account-id: ${{ vars.NS_ACCOUNT_ID }}
      ns-token-id: ${{ secrets.NS_TOKEN_ID }}
      ns-token-secret: ${{ secrets.NS_TOKEN_SECRET }}

We invoke Actions with the uses command. Within a uses command, inputs are specified using the with structure. Here we pass in the environment variables and secrets that we were previously specifying directly in our authentication Step.

Triggering our Workflow again, we should expect to see exactly the same behavior as before, but now with much less repeated configuration.

Working with Multiple Environments

For those of you embarking on this CI/CD journey with me, and for all NetSuite developers generally, I sincerely hope you have access to at least one non-Production account for learning and testing, though I know that’s not always the case. While the functionality of our pipeline is filling out nicely, it can only operate on a single, hard-coded environment. To change the pipeline from Sandbox to Production or back, you’d currently have to push a code change in the configuration file; that kind of manual interaction is the opposite of what we want from our automation pipeline.

Luckily for us, the environment property of a Job accepts not only names but expressions as well. This means we can dynamically select an Environment for a Job based on conditions or values set in the pipeline.

I prefer to follow a feature-branching strategy in my SuiteScript repositories, so ongoing development is done in feature branches while main is considered the stable, Production-ready code. Using that information, I can conditionally select which Environment my Jobs should use based on which branch has changed:

  • If main changes, select the Production Environment.
  • Otherwise, select the Sandbox Environment.

The branch name which triggered the Workflow is available in the github context’s ref_name property:


environment: ${{ github.ref_name == 'main' && 'production' || 'sandbox' }}

Enforcing a Manual Approval

In practice, you probably don’t want to continuously/automatically deploy to a Sandbox or Production account, unless you are a solo developer. If a team of developers is sharing the same account and working in the same repository which deploys every feature branch push, they’d constantly be overwriting each others’ changes.

You might, however, want to introduce a manual approval step into your pipeline to allow a gatekeeper to decide whether a build gets deployed or not. We can do so via the Required Approvers setting on an Environment.

By checking the Required reviewers box and specifying appropriate users in an Environment’s settings, GitHub will pause each Job that targets this Environment and wait for manual approval from the listed users. It will notify all approvers that a build is pending their review, and approvers can then jump into GitHub and provide their approval or rejection of a build.

For me, the behavior of this approval isn’t quite what I want as it will request approval on every Job within the Workflow. I’d prefer to incorporate an approval as a Step within a Job or Workflow instead (this is actually how CircleCI, a “competitor” of GitHub Actions, handles this process).

There is a third-party Action that purports to solve this problem, but it leverages the repository’s Issues to provide approvals, and that’s also not ideal for me. If you’re curious, I leave the investigation and setup of this Action to you as an exercise.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Conclusion

At this point, we have a strong and flexible foundation for automating the testing, validation, and deployment of our SuiteScript code. You can find this complete configuration in the Part 3 Release of my GitHub repository. 

From here, I hope you’ve seen enough that you feel comfortable and inspired to add and adapt this Workflow to your needs, and I hope it makes delivering your SuiteScript easier, faster, and more enjoyable.

WRITTEN BY OUR EXPERT

Eric Grubaugh

Senior NetSuite Developer

Since 2012, Eric has been designing and developing SuiteScript solutions, coaching NetSuite developers on doing the same, and advising SuiteScript teams on building healthy, effective practices. He also launched the SuiteScript Stories podcast.