cleaner ci
This commit is contained in:
parent
d5e0b7d51a
commit
8d1677d78b
@ -42,20 +42,20 @@ jobs:
|
|||||||
- run: flutter pub get
|
- run: flutter pub get
|
||||||
working-directory: ./frontend
|
working-directory: ./frontend
|
||||||
|
|
||||||
- run: flutter build apk --release --split-per-abi
|
- name: Add required secrets
|
||||||
|
run: |
|
||||||
|
echo ${{ secrets.ANDROID_SECRETS_BASE64 }} | base64 -d > android/secrets.properties
|
||||||
working-directory: ./frontend
|
working-directory: ./frontend
|
||||||
|
|
||||||
- name: Release APK
|
- run: flutter build apk --release --split-per-abi --build-number=${{ gitea.run_number }}
|
||||||
uses: https://gitea.com/akkuman/gitea-release-action@v1
|
working-directory: ./frontend
|
||||||
with:
|
|
||||||
files: ./frontend/build/app/outputs/flutter-apk/*.apk
|
- name: Upload APKs to artifacts
|
||||||
name: Testing release
|
uses: https://gitea.com/actions/upload-artifact@v3
|
||||||
release_name: testing
|
with:
|
||||||
tag: testing
|
name: app-release
|
||||||
tag_name: testing
|
path: frontend/build/app/outputs/flutter-apk/
|
||||||
release_body: "This is a testing release."
|
if-no-files-found: error
|
||||||
prerelease: true
|
retention-days: 15
|
||||||
token: ${{ secrets.GITEA_TOKEN }}
|
|
||||||
env:
|
|
||||||
NODE_OPTIONS: '--experimental-fetch'
|
|
||||||
|
|
||||||
|
1
frontend/android/.gitignore
vendored
1
frontend/android/.gitignore
vendored
@ -4,6 +4,7 @@ gradle-wrapper.jar
|
|||||||
/gradlew
|
/gradlew
|
||||||
/gradlew.bat
|
/gradlew.bat
|
||||||
/local.properties
|
/local.properties
|
||||||
|
/secrets.properties
|
||||||
GeneratedPluginRegistrant.java
|
GeneratedPluginRegistrant.java
|
||||||
|
|
||||||
# Remember to never publicly share your keystore.
|
# Remember to never publicly share your keystore.
|
||||||
|
48
frontend/android/README.md
Normal file
48
frontend/android/README.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
## Android Setup
|
||||||
|
|
||||||
|
### Keystore setup
|
||||||
|
```bash
|
||||||
|
keytool -genkey -v -keystore release.keystore -keyalg RSA -keysize 2048 -validity 10000 -alias release
|
||||||
|
```
|
||||||
|
- This is required to store local credentials securely (not used for now).
|
||||||
|
- But necesseary in order to restrict the particular api key to a particular app (through the sha1 of the associated keystore).
|
||||||
|
|
||||||
|
|
||||||
|
### Building and secret credentials
|
||||||
|
Following the guide under [https://developers.google.com/maps/flutter-package/config#android_1](https://developers.google.com/maps/flutter-package/config#android_1).
|
||||||
|
- Add the following to `android/build.gradle`:
|
||||||
|
```gradle
|
||||||
|
buildscript {
|
||||||
|
dependencies {
|
||||||
|
classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Add the following to `android/app/build.gradle`:
|
||||||
|
```gradle
|
||||||
|
plugins {
|
||||||
|
// ...
|
||||||
|
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Add the credentials to `android/secrets.properties`:
|
||||||
|
```properties
|
||||||
|
MAPS_API_KEY=YOUR_API_KEY
|
||||||
|
```
|
||||||
|
- Reference the credentials in `android/app/src/main/AndroidManifest.xml`:
|
||||||
|
```xml
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.geo.API_KEY"
|
||||||
|
android:value="${MAPS_API_KEY}" />
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Using the credentials in CI
|
||||||
|
- Add the base64 encoded credentials to the repository secrets (e.g. `ANDROID_SECRETS`).
|
||||||
|
```bash
|
||||||
|
base64 -i android/secrets.properties
|
||||||
|
```
|
||||||
|
- Use the following in the CI script:
|
||||||
|
```bash
|
||||||
|
echo {{ secrets.ANDROID_SECRETS }} | base64 -d > android/secrets.properties
|
||||||
|
```
|
@ -2,10 +2,12 @@ plugins {
|
|||||||
id "com.android.application"
|
id "com.android.application"
|
||||||
id "kotlin-android"
|
id "kotlin-android"
|
||||||
id "dev.flutter.flutter-gradle-plugin"
|
id "dev.flutter.flutter-gradle-plugin"
|
||||||
|
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def localProperties = new Properties()
|
def localProperties = new Properties()
|
||||||
def localPropertiesFile = rootProject.file('local.properties')
|
def localPropertiesFile = rootProject.file('secrets.properties')
|
||||||
if (localPropertiesFile.exists()) {
|
if (localPropertiesFile.exists()) {
|
||||||
localPropertiesFile.withReader('UTF-8') { reader ->
|
localPropertiesFile.withReader('UTF-8') { reader ->
|
||||||
localProperties.load(reader)
|
localProperties.load(reader)
|
||||||
@ -52,6 +54,9 @@ android {
|
|||||||
targetSdkVersion flutter.targetSdkVersion
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
// Placeholders of keys that are replaced by the build system.
|
||||||
|
manifestPlaceholders += [MAPS_API_KEY: "some value"]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
/>
|
/>
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.android.geo.API_KEY"
|
android:name="com.google.android.geo.API_KEY"
|
||||||
android:value="AIzaSyCeWk_D2xvfOHLidvV56EZeQCUybypEntw"
|
android:value="${MAPS_API_KEY}"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,3 +16,14 @@ subprojects {
|
|||||||
tasks.register("clean", Delete) {
|
tasks.register("clean", Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1"
|
||||||
|
}
|
||||||
|
}
|
1
frontend/android/fallback.properties
Normal file
1
frontend/android/fallback.properties
Normal file
@ -0,0 +1 @@
|
|||||||
|
MAPS_API_KEY=Key
|
@ -21,47 +21,47 @@ class _LandmarkCardState extends State<LandmarkCard> {
|
|||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
// Container(
|
||||||
width: 160,
|
// width: 160,
|
||||||
height: 160,
|
// height: 160,
|
||||||
decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.only(
|
// borderRadius: BorderRadius.only(
|
||||||
topLeft: Radius.circular(15.0),
|
// topLeft: Radius.circular(15.0),
|
||||||
bottomLeft: Radius.circular(15.0),
|
// bottomLeft: Radius.circular(15.0),
|
||||||
),
|
// ),
|
||||||
image: DecorationImage(
|
// image: DecorationImage(
|
||||||
image: NetworkImage('https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Tour_Eiffel_Wikimedia_Commons.jpg/1037px-Tour_Eiffel_Wikimedia_Commons.jpg'),
|
// image: NetworkImage(widget.landmark.imageURL),
|
||||||
fit: BoxFit.cover,
|
// fit: BoxFit.cover,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.all(10),
|
padding: EdgeInsets.all(10),
|
||||||
child: Expanded(
|
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
widget.landmark.name,
|
widget.landmark.name,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
SizedBox(height: 5),
|
),
|
||||||
Text(
|
SizedBox(height: 5),
|
||||||
"${widget.landmark.name} (${widget.landmark.type.name})",
|
Text(
|
||||||
style: TextStyle(fontSize: 14),
|
"${widget.landmark.name} (${widget.landmark.type.name})",
|
||||||
),
|
style: TextStyle(fontSize: 14),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Align(
|
// Align(
|
||||||
// alignment: Alignment.topRight,
|
// alignment: Alignment.topRight,
|
||||||
// child: Icon(Icons.push_pin, color: theme.primaryColor),
|
// child: Icon(Icons.push_pin, color: theme.primaryColor),
|
||||||
|
@ -2,6 +2,7 @@ class Landmark {
|
|||||||
final String name;
|
final String name;
|
||||||
final List location;
|
final List location;
|
||||||
final LandmarkType type;
|
final LandmarkType type;
|
||||||
|
final String imageURL;
|
||||||
// final String description;
|
// final String description;
|
||||||
// final Duration duration;
|
// final Duration duration;
|
||||||
// final bool visited;
|
// final bool visited;
|
||||||
@ -10,6 +11,7 @@ class Landmark {
|
|||||||
required this.name,
|
required this.name,
|
||||||
required this.location,
|
required this.location,
|
||||||
required this.type,
|
required this.type,
|
||||||
|
this.imageURL = 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Tour_Eiffel_Wikimedia_Commons.jpg/1037px-Tour_Eiffel_Wikimedia_Commons.jpg',
|
||||||
// required this.description,
|
// required this.description,
|
||||||
// required this.duration,
|
// required this.duration,
|
||||||
// required this.visited,
|
// required this.visited,
|
||||||
|
@ -10,14 +10,39 @@ Future<List<Landmark>> fetchLandmarks() async {
|
|||||||
// If the server did return a 200 OK response,
|
// If the server did return a 200 OK response,
|
||||||
// then parse the JSON.
|
// then parse the JSON.
|
||||||
List<Landmark> landmarks = [
|
List<Landmark> landmarks = [
|
||||||
Landmark(name: "Landmark 1", location: [48.85, 2.35], type: LandmarkType(name: "Type 1")),
|
// 48°51′29.6″N 2°17′40.2″E
|
||||||
Landmark(name: "Landmark 2", location: [48.86, 2.36], type: LandmarkType(name: "Type 2")),
|
Landmark(
|
||||||
Landmark(name: "Landmark 3", location: [48.75, 2.3], type: LandmarkType(name: "Type 3")),
|
name: "Eiffel Tower",
|
||||||
Landmark(name: "Landmark 4", location: [48.9, 2.4], type: LandmarkType(name: "Type 4")),
|
location: [48.51296, 2.17402],
|
||||||
Landmark(name: "Landmark 5", location: [48.91, 2.45], type: LandmarkType(name: "Type 5")),
|
type: LandmarkType(name: "Tower"),
|
||||||
|
imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Tour_Eiffel_Wikimedia_Commons.jpg/1037px-Tour_Eiffel_Wikimedia_Commons.jpg"
|
||||||
|
),
|
||||||
|
Landmark(
|
||||||
|
name: "Notre Dame Cathedral",
|
||||||
|
location: [48.8530, 2.3498],
|
||||||
|
type: LandmarkType(name: "Monument"),
|
||||||
|
imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Notre-Dame_de_Paris%2C_4_October_2017.jpg/440px-Notre-Dame_de_Paris%2C_4_October_2017.jpg"
|
||||||
|
),
|
||||||
|
Landmark(
|
||||||
|
name: "Louvre palace",
|
||||||
|
location: [48.8606, 2.3376],
|
||||||
|
type: LandmarkType(name: "Museum"),
|
||||||
|
imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/6/66/Louvre_Museum_Wikimedia_Commons.jpg/540px-Louvre_Museum_Wikimedia_Commons.jpg"
|
||||||
|
),
|
||||||
|
Landmark(
|
||||||
|
name: "Pont-des-arts",
|
||||||
|
location: [48.5130, 2.2015],
|
||||||
|
type: LandmarkType(name: "Bridge"),
|
||||||
|
imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d1/Pont_des_Arts%2C_6e_Arrondissement%2C_Paris_%28HDR%29_20140320_1.jpg/560px-Pont_des_Arts%2C_6e_Arrondissement%2C_Paris_%28HDR%29_20140320_1.jpg"),
|
||||||
|
Landmark(
|
||||||
|
name: "Panthéon",
|
||||||
|
location: [48.5046, 2.2046],
|
||||||
|
type: LandmarkType(name: "Monument"),
|
||||||
|
imageURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Pantheon_of_Paris_007.JPG/1280px-Pantheon_of_Paris_007.JPG"
|
||||||
|
),
|
||||||
];
|
];
|
||||||
// sleep 10 seconds
|
// sleep 10 seconds
|
||||||
await Future.delayed(Duration(seconds: 10));
|
await Future.delayed(Duration(seconds: 5));
|
||||||
return landmarks;
|
return landmarks;
|
||||||
// } else {
|
// } else {
|
||||||
// // If the server did not return a 200 OK response,
|
// // If the server did not return a 200 OK response,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user