Reputation: 113
In my project I have some JSON files that are used to get environment configurations at runtime through an entrypoint to the main dart file, they hold sensitive data so I put their containing folder in the .gitignore
file.
I have written a test that passes when I run it locally, but fails when triggered by the github action because of this error:
The following assertion was thrown running a test:
Unable to load asset: assets/config/dev.json
Is there a way to somehow inject this JSON while performing the action? Any help is much appreciated, my only concern is having private data not stored in the github repository and having the action pass.
This is my code:
dev_run.dart
import 'package:gitgo/main.dart' as App;
void main() {
App.main('dev');
}
EnvironmentConfig
import 'dart:convert';
import 'package:flutter/services.dart';
class EnvironmentConfig {
final Map<String, String> environment;
EnvironmentConfig({this.environment});
static Future<EnvironmentConfig> forEnvironment(String env) async {
env = env ?? 'dev';
final contents = await rootBundle.loadString(
'assets/config/$env.json',
);
final Map<String, String> json = Map.castFrom(jsonDecode(contents));
return EnvironmentConfig(environment: json);
}
}
pubspec.yaml
name: gitgo
description: Git on the go.
version: 1.0.0+1
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
http: ^0.12.1
oauth2: ^1.6.1
url_launcher: ^5.4.10
flutter_config: ^1.0.8
gql: ^0.12.3
gql_exec: ^0.2.4
gql_link: ^0.3.0
gql_http_link: ^0.3.2
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^1.11.1
gql_build: ^0.0.11
pedantic: ^1.9.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
assets:
- assets/config/
main.dart
import 'package:flutter/material.dart';
import 'package:gitgo/inbound/configuration/config_environment_widget.dart';
import 'package:gitgo/outbound/api/viewer.req.gql.dart';
import 'package:gql_exec/gql_exec.dart';
import 'package:gql_link/gql_link.dart';
import 'package:gitgo/outbound/api/viewer.data.gql.dart';
import 'package:gitgo/outbound/auth.dart';
import 'package:gql_http_link/gql_http_link.dart';
import 'inbound/configuration/environment_config.dart';
Future main(String env) async {
WidgetsFlutterBinding.ensureInitialized();
final config = await EnvironmentConfig.forEnvironment(env);
print("starting app in $env mode");
runApp(MyApp(config));
}
class MyApp extends StatelessWidget {
final EnvironmentConfig config;
MyApp(this.config);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'GitGo Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: EnvironmentConfigWidget(
config: config, child: MyHomePage(title: 'GitGo Demo Home Page')),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState(title: "GitHub login");
}
class _MyHomePageState extends State<MyHomePage> {
_MyHomePageState({this.title});
EnvironmentConfigWidget environmentConfigWidget;
String title;
@override
Widget build(BuildContext context) {
return GithubLoginWidget(
builder: (context, httpClient) {
final link = HttpLink(
'https://api.github.com/graphql',
httpClient: httpClient,
);
return FutureBuilder<$ViewerDetail$viewer>(
future: viewerDetail(link),
builder: (context, snapshot) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Text(
snapshot.hasData
? 'Hello ${snapshot.data?.login}!'
: 'Retrieving viewer login details...',
),
),
);
},
);
},
githubClientId: EnvironmentConfigWidget.of(context)
.config
.environment['githubClientId'],
githubClientSecret: EnvironmentConfigWidget.of(context)
.config
.environment['githubClientSecret'],
githubScopes: EnvironmentConfigWidget.of(context)
.config
.environment['githubScopes']
.split(","));
}
}
Future<$ViewerDetail$viewer> viewerDetail(Link link) async {
var result = await link.request(ViewerDetail((b) => b)).first;
if (result.errors != null && result.errors.isNotEmpty) {
throw QueryException(result.errors);
}
return $ViewerDetail(result.data).viewer;
}
class QueryException implements Exception {
QueryException(this.errors);
List<GraphQLError> errors;
@override
String toString() {
return 'Query Exception: ${errors.map((err) => '$err').join(',')}';
}
}
widget_dart.test
import 'package:flutter_test/flutter_test.dart';
import 'package:gitgo/inbound/configuration/environment_config.dart';
import 'package:gitgo/main.dart';
void main() {
testWidgets('Smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
var env = await EnvironmentConfig.forEnvironment('dev');
await tester.pumpWidget(MyApp(env));
// Verify that our counter starts at 0.
expect(find.text('Log into Github'), findsOneWidget);
expect(find.text('1'), findsNothing);
});
}
ci.yml
name: ci
jobs:
ci:
name: ci
runs-on: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Flutter test
uses: subosito/[email protected]
with:
flutter-version: '1.26.0-17.2.pre'
channel: dev
- run: flutter pub get
- run: flutter analyze
- run: flutter test --no-sound-null-safety
- name : Clean merged branches
run: |
git fetch -p && for branch in $(git branch -vv | grep ': gone]' | awk '{print $1}'); do git branch -D $branch; done
echo "Finished cleaning"
Upvotes: 1
Views: 1388
Reputation: 113
The proposed solution didn't work for me, but as hacker1024 pointed out:
Put your dev.json contents in a secret (for example, DEV_JSON_CONTENTS), and write it to the correct location with a command.
So what worked in my case, was adding the github secret DEV_JSON
with the contents of the original file, then
I modified the workflow file by adding the secret as an env variable in the workflow:
env:
DEV_JSON : ${{ secrets.DEV_JSON }}
And I added this step to write the contents to a new file:
- name: Write dev.json
run: |
touch assets/config/dev.json
echo $DEV_JSON >> assets/config/dev.json
cat assets/config/dev.json
Upvotes: 2
Reputation: 3668
You can use GitHub Action secrets.
Put your dev.json
contents in a secret (for example, DEV_JSON_CONTENTS
), and write it to the correct location with a command.
- name: Write dev.json
run: echo '{{ secrets.DEV_JSON_CONTENTS }}' > assets/config/dev.json
Upvotes: 3