DEV Community

Jonathan Gómez
Jonathan Gómez

Posted on

🧪 Github Actions for Dart package with Environment variables 🧪

🎉 I just end the configuration and I'm so happy that it work so I'm just gonna throw it here 😅

I'm currently working on a dar wrapper package for the Notion API so I had to add a secret token for testing. I didn't know how to work with environment variables on flutter until today, and to configure a GitHub Action for the package testing was a good challenge to learn and here are the steps I did if you want to make something similar and don't know how.

💡 Also, as I mentioned, I just do this today and I'm still learning so if you know a better way please let me know. And excuse my English hehe.

Now let's get into it in two points:

🔧 Set up Flutter test

- A): By default my variables are set from Platform

String? token = Platform.environment['TOKEN'];
String? testBlockId = Platform.environment['TEST_BLOCK_ID'];
Enter fullscreen mode Exit fullscreen mode

- B): I have a variable to know when the execution environment is a GitHub Action*

String execEnv =
  env['EXEC_ENV'] ?? Platform.environment['EXEC_ENV'] ?? '';

if (execEnv != 'github_actions') {
  // more code here...
}
Enter fullscreen mode Exit fullscreen mode

- C): If the environment is not a GitHub Action then I try to load the .env file

setUpAll(() {
  // load .env variables for all tests
  load();

  // more code here...
});

tearDownAll(() {
  // clean environment after all tests
  clean();
});
Enter fullscreen mode Exit fullscreen mode

- D): I try to set the value of the variables with the following hierarchy from highest to lowest:

  • Value from .env file
  • Value from Platform (initial value by default)
  • An empty string as last option
token = env['TOKEN'] ?? token ?? '';
testBlockId = env['TEST_BLOCK_ID'] ?? testBlockId ?? '';
// variables declared before, see full example code bellow.
Enter fullscreen mode Exit fullscreen mode

*At least the dotenv package only gets the variables from a file and in GitHub actions the secrets are flushed directly into the environment without occupying an .env file.

full example code:

void main() {
  // (A)
  String? token = Platform.environment['TOKEN'];
  String? testBlockId = Platform.environment['TEST_BLOCK_ID'];

  // (B)
  String execEnv = env['EXEC_ENV'] ?? Platform.environment['EXEC_ENV'] ?? '';

  // (B)
  if (execEnv != 'github_actions') {
    setUpAll(() {
      // (C)
      load();

      // (D)
      token = env['TOKEN'] ?? token ?? '';
      testBlockId = env['TEST_BLOCK_ID'] ?? testBlockId ?? '';
    });

    tearDownAll(() {
      clean();
    });
  }

  group('Notion Block Client', () {
    test('Retrieve block children', () async {
      final NotionBlockClient blocks = NotionBlockClient(token: token);

      var res = await blocks.fetch(testBlockId ?? '');
      expect(res.statusCode, 200);
    });
  });
}
Enter fullscreen mode Exit fullscreen mode

full real code click here

🐙 Set up GitHub Action

Now on GitHub I create a new GitHub Action.

First of all I have to add the environment variables to the secrets on Settings -> Secrets -> Click to New repository secret:

Screen Shot 2021-05-20 at 17.54.58

And then:
- A) First I add flutter SDK

- uses: actions/setup-java@v1
  with:
    java-version: '12.x'
- uses: subosito/flutter-action@v1
  with:
    flutter-version: '2.0.5'
Enter fullscreen mode Exit fullscreen mode

- B) Then I install the dependencies

- name: Install dependencies
  run: flutter pub get
Enter fullscreen mode Exit fullscreen mode

- C) Finally I run the test passing the secrets as environment variables. Note that I set the EXEC_ENV as "github_actions" like I defined on the tests configuration to avoid to try to load the .env file.

- name: Test package
  run: flutter test
  env:
    TOKEN: ${{ secrets.TOKEN }}
    TEST_BLOCK_ID: ${{ secrets.TEST_BLOCK_ID }}
    EXEC_ENV: 'github_actions'
Enter fullscreen mode Exit fullscreen mode

full example code:

name: Test
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
jobs:
  build:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v2
      # (A)
      - uses: actions/setup-java@v1
        with:
          java-version: '12.x'
      - uses: subosito/flutter-action@v1
        with:
          flutter-version: '2.0.5'
      # (B)
      - name: Install dependencies
        run: flutter pub get
      # (C)
      - name: Test package
        run: flutter test
        env:
          TOKEN: ${{ secrets.TOKEN }}
          TEST_BLOCK_ID: ${{ secrets.TEST_BLOCK_ID }}
          EXEC_ENV: 'github_actions'
Enter fullscreen mode Exit fullscreen mode

full real code click here

📚 Resources

I found very useful the next resources:
Main source:
https://medium.com/flutter-community/testing-dart-packages-with-github-actions-4c2c671b1e34
Secondary but necessary source:
https://github.com/subosito/flutter-action

Top comments (1)

Collapse
 
devbirgit profile image
Birgit Pohl 🏡

I believe by the time that this article has been written flutter_dotenv has added an additional feature, where you can merge the dotenv and Platform.environment together. Which would simplify your code. :)

// For example using Platform.environment that contains a CLIENT_ID entry
  await DotEnv.load(mergeWith: Platform.environment);
  print(env["CLIENT_ID"]);
Enter fullscreen mode Exit fullscreen mode

pub.dev/packages/flutter_dotenv