How do I pass environment configuration like URLs to Flutter application using Jenkins? - flutter

I have a Jenkins job that builds my Flutter application based on different parameters like flavor (for different environments), backend URLs, etc. Right now in the build phase, I have a bash script that creates a new dart file based on my parameters and then Flutter uses that file as its environment configuration.
Future<void> main() async {
final config = {
'param1': Platform.environment['param1'],
};
final filename = 'lib/env.dart';
await File(filename)
.writeAsString('final environment = ${json.encode(config)};');
}
Is there a better way to send parameters like URLs from Jenkins to the Flutter application during the build process?

Maybe you must try pass your URLs with environments variables from jenkins to flask app.
In jenkins for example you can create a build stage like this
stage('Build') {
agent {
label 'master'
}
environment {
YOUR_URL = "https://example.com/api/v1"
}
steps {
script {
/* Some actions */
}
}
}
So, in your flask app only just missing get the env variables with any method like os.environ method like this example
import os
YOUR_URL = os.environ.get("YOUR_URL")

Related

Can I skip generating the {proxy+} when creating Rest API using Amplify

I am currently playing around with creating rest-api:s with amplify. I am trying to create the following structure:
/helloText
/helloText/{name}
But I get the following error when trying to push the backend:
Unable to create resource at path '/helloText/{proxy+}': A sibling ({name}) of this resource already has a variable path part -- only one is allowed
As I understand, it is because Amplify is creating "greedy paths" by default.
When manually removing these "greedy paths" from the template file RestTest-cloudformation-template.json it works.
Is it somehow possible to create these paths by using only the command line?
There is no configuration switch for that in amplify-cli. You need to create an override. Reference: Amplify override api.
Run:
amplify override api
Then edit generated override.ts like:
import { AmplifyApiRestResourceStackTemplate } from '#aws-amplify/cli-extensibility-helper';
export function override(resources: AmplifyApiRestResourceStackTemplate) {
const {paths} = resources.restApi.body;
Object.keys(paths).forEach((path) => {
if (path.includes('{proxy+}')) {
delete paths[path];
}
});
}

How to include dlls in flutter build windows

I am working on a flutter project that runs fine in development.
However I do not know how to get the build to include dll's referenced using FFI.
I can't find clear instructions on how to do it.
I tried following the steps to build an msix here, which worked but didn't seem to include the dll (it fails in the same way as the regular build)
what is the procedure to have the build process consider the dll's?
other dll's show up in the build directory from 3rd party packages so there must be a way right?
That's really hard to discover by your own, but indeed you can bind those libraries to you MSIX. In my case I just made a package for label printers using Dart FFI and DLL`s provided by manufacturer and this is how I did it.
You need to add these DLL's to your assets setting on pubspec.yaml from your package. This is my case:
[...]
flutter:
[...]
assets:
- assets/WinPort.dll
- assets/Winppla.dll
- assets/Winpplb.dll
- assets/Winpplz.dll
With this setting you will embed your DLL files in your final MSIX, but this was the easy part. Now you have make sure to load the proper load these files in code.
Based on my own tests, I still dealing with two ways to develop and test code, the first one is when I am running a project in my machine via flutter run I must set the target for current.path, when I get it done and start building for deploy I change this to resolvedExecutable.parent.path. Where is what you need to do.
Loading you DLL in development environment (flutter run):
final String _packageAssetsDirPath = normalize(join(Directory.current.path,'assets'));
On production environment (running from .exe or MSIX installed):
final String _assetsPackageDir = normalize(
join('data', 'flutter_assets', 'packages', 'YOUR_PACKAGE_NAME', 'assets'));
final String _exeDirPath = File(Platform.resolvedExecutable).parent.path;
final String _packageAssetsDirPath =
normalize(join(_exeDirPath, _assetsPackageDir));
After with this var called _packageAssetsDirPath will be easy to load your DLL's, now you invoke a DynamicLibrary constructor:
// Path for DLL file
final String _libDllSourceFullPath =
normalize(join(_packageAssetsDirPath, 'Winppla.dll'));
// Target for copy, place DLL in same place the .exe you are running
final String _libDllDestFullPath =
normalize(join(_packageAssetsDirPath, 'YOUROWN.dll'));
// Try to copy for running exe path
File(_libDllSourceFullPath).copySync(_libDllDestFullPath);
// With this copy, would be simple to load, and if it fails, try in full path
// LOAD DLL
try {
String _packageAssetsDirPath =
normalize(join(Directory.current.path, 'assets'));
String _printerLibraryPath =
normalize(join(_packageAssetsDirPath, 'Winppla.dll'));
DynamicLibrary _library = DynamicLibrary.open(_printerLibraryPath);
return _library;
} catch (e) {
try {
DynamicLibrary _library = DynamicLibrary.open('Winppla.dll');
return _library;
} catch (e) {
// Avoing errors creating a fake DLL, but you could deal with an exception
return DynamicLibrary.process();
}
}
At this point you can load a DLL and use it, you can check my package full code at https://github.com/saviobatista/argox_printer check for lib/src/ppla.dart at function _setupDll() and you will see that loading.
I built a simpler option inspired in the solution of Sávio Batista
(You must have your .dll in your assets folder)
if (kReleaseMode) {
// I'm on release mode, absolute linking
final String local_lib = join('data', 'flutter_assets', 'assets', 'libturbojpeg.dll');
String pathToLib = join(Directory(Platform.resolvedExecutable).parent.path, local_lib);
DynamicLibrary lib = DynamicLibrary.open(pathToLib);
} else {
// I'm on debug mode, local linking
var path = Directory.current.path;
DynamicLibrary lib = DynamicLibrary.open('$path/assets/libturbojpeg.dll');
}
Just replace libturbojpeg.dll for your .dll

How to get build and version number of Flutter Web app

The keyword here is Web. I can get the build and version number of a Flutter app by using the package_info plugin, but if it is running on the web I can't. How do I get the package info for a Flutter Web app?
I'll include an answer below as a temporary fix, but I am looking a solution that gets the version info from pubspec.yaml.
As a temporary workaround you can create a separate file with the version info in it:
web_version_info.dart
class WebVersionInfo {
static const String name = '1.0.0';
static const int build = 1;
}
You can use that for all platforms or in your code you can use kIsWeb to just use it for the web:
Future<String> _getAppVersion() async {
if (kIsWeb) {
return WebVersionInfo.name;
} else {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
return packageInfo.version;
}
}
Of course, this is not a great solution because now you need to remember to update the version and build information in both pubspec.yaml and in WebVersionInfo every time you update the app.
If you use beta channel you can use package_info_plus plugin that appears to be a drop-in-replacement for package_info. So all you need to change is pubspec.yaml and your import. (I only use version so there could be differences that I haven't noticed)
Change pubspec and your import
pubspec.yaml: package_info_plus: '>=0.6.3 <2.0.0'
import: import 'package:package_info_plus/package_info_plus.dart'
Reference:
Github issue 46609
For those using Linux and in order to improve Suragch's answer, I suggest automating the build process using bash scripts. For that, we need two scripts: one to increase the version build number and another to call the flutter build command itself, forwarding the parameters. That way, if you prefer to just increment the version build number manually, you can just call the update script and then 'flutter build' later, but if you want to do everything in one step, you can call the builder script.
You will only need to edit the '.app_version' file as the version changes.
The '.build_seq', '.version_number' files are always rewritten, and the '.app_version' file is created only if it is not found.
The scripts:
updversion.sh:
#!/bin/bash
if [ -f ".app_version" ]; then
VER=`cat .app_version`
else
VER="1.0.0"
echo $VER > .app_version
fi
if [ -f ".build_seq" ]; then
BLD=`cat .build_seq`
else
BLD='0'
fi
((BLD++))
echo $BLD > .build_seq
echo "Ver: $VER ($BLD)" > .current_version
echo "
// Auto-generated by updversion.sh. Do not edit.
class WebVersionInfo {
static const String name = '$VER';
static const int build = $BLD;
}
" > lib/version_info.dart
exit 0
buildweb.sh:
#!/bin/bash
./updversion.sh
flutter build web $*
exit $?

Can I run multiple integration tests with one single config file in Flutter?

I am trying to write Flutter integration tests and to run them all with one config file instead of making config file for every single test. Is there any way to do that?
For now I have login.dart and login_test.dart and so on, for every single test. I know its convention that every config and test file must have the same name, but that's not what I need, more configurable things are welcomed. Thanks in advance.
This is my config file (login.dart)
import 'package:flutter_driver/driver_extension.dart';
import 'package:seve/main.dart' as app;
void main() {
enableFlutterDriverExtension();
app.main();
}
And test (login_test.dart) looks something like this
import ...
FlutterDriver driver;
void main() {
setUpAll(() async {
driver = await FlutterDriver.connect();
});
tearDownAll(() async {
if (driver != null) {
driver.close();
}
});
test('T001loginAsDriverAndVerifyThatDriverIsLogedInTest', () async {
some_code...
});
});
Now I want to make new test file (e.g login_warning.dart) and be able to start both tests by calling single config file (login.dart). Is that even possible?
Yes, running multiple "test" files with the same "config" is possible.
In the flutter jargon, your config file is your target and your test file is your driver. Your target is always login.dart but you have the two drivers login_test.dart and login_warning.dart.
With the flutter drive command, you can specify the target as well as the driver.
So in order to run both drivers, simply execute the following commands
flutter drive --target=test_driver/login.dart --driver=test_driver/login_test.dart
flutter drive --target=test_driver/login.dart --driver=test_driver/login_warning.dart
This executes first the login_test.dart and then the login_warning.dart driver.
You can always have one main test file that you initiate, like say
flutter drive --target=test_driver/app_test.dart
Then in that call your test groups as functions, like so -
void main() {
test1();
}
void test1() {
group('test 1', () {});}
So with one command you get to execute all the cases mentioned in the main()
Like vzurd's answer my favourit and cleanest is to create a single test file and call all main methods from within:
import './first_test.dart' as first;
import './second_test.dart' as second;
void main() {
first.main();
second.main();
}
Then just run driver on the single test file:
flutter drive --driver=test/integration/integration_test_driver.dart --target=test/integration/run_all_test.dart
to expand on to #sceee 's answer:
you can put the multiple commands into a shell script named integration_tests.sh for example and run them with a single command that way.
#!/bin/sh
flutter drive --target=test_driver/app.dart --driver=test_driver/app_test.dart
flutter drive --target=test_driver/app.dart --driver=test_driver/start_screen_test.dar
make executable:
$chmod a+rx integration_tests.sh
run it:
$./integration_tests.sh
We can use shell command to automate this process.
The following solution will work even with any new test files without manually adding its name to any of the files.
Create a shell script with name integrationTestRunner.sh inside the root directory. You can use the command
touch integrationTestRunner.sh
Inside integrationTestRunner.sh file, paste the following code.
#!/bin/bash
# Declare an array to store the file names and paths
declare -a targets
# Find all .dart files in the current directory and subdirectories
while IFS= read -r -d $'\0' file; do
targets+=("$file")
done < <(find integration_test -name "*.dart" -type f -print0)
# Loop through the array and run the flutter drive command for each target
for target in "${targets[#]}"
do
flutter drive \
--driver=test_driver/integation_test_driver.dart \
--target=$target
done
Run the integrationTestRunner.sh file with any methods:
Pressing the ▶️ button in that file (if you are in VS Code)
Running the script from command line ./integrationTestRunner.sh

Copy different files to build directory based on executed Gradle task

I have created a plugin for Gradle to deploy to my company's OpenVMS directory structures, which adds deployDev, deployTest, and, when credentials are provided, deployProd tasks to an application build. I have extracted our configuration files for all environments to a separate project so that we can deploy configuration separately from the application.
These custom tasks depend on the application plugin's distZip task and I haven't found a good way to get the appropriate configuration files into the zip based on the called task (e.g. deployDev includes dev config).
I have tried having the deploy* tasks copy configuration files during the configuration phase with:
task distZip(type:Zip, overwrite:true) {
archiveName = 'config.zip'
from "build/props"
}
deployDev.configure {
copyResources('dev')
}
deployTest.configure {
copyResources('test')
}
project.tasks.findByName('deployProd')?.configure {
copyResources('prod')
}
def copyResources(String environment){
copy {
from "src/$environment/resources"
into 'build/props'
}
}
This doesn't work due to configuration phase executing on all tasks, so even when we execute deployDev, the test configuration has been copied over the dev resources.
I also have tried:
file('build/props').mkdirs()
task distZip(type:Zip, overwrite:true) {
archiveName = 'config.zip'
from "build/props"
outputs.upToDateWhen {false}
}
gradle.taskGraph.whenReady { graph ->
if (graph.hasTask('deployProd')) {
copyResources('prod')
}else if(graph.hasTask('deployTest')){
copyResources('test')
}else if(graph.hasTask('deployDev')){
copyResources('dev')
}
}
def copyResources(String environment){
copy {
from "src/$environment/resources"
into 'build/props'
}
}
However, with this proposal the distZip task always is UP-TO-DATE. Is there a correct way to do this?