From 8503a625b569b79ccbf303b4aa5ed001a1696206 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 19 Jul 2018 13:27:35 +0200 Subject: [PATCH 1/8] show toast if user tries to update, but Data/WiFi settings disallow it --- app/src/main/java/org/fdroid/fdroid/UpdateService.java | 4 ++++ app/src/main/res/values/strings.xml | 1 + 2 files changed, 5 insertions(+) diff --git a/app/src/main/java/org/fdroid/fdroid/UpdateService.java b/app/src/main/java/org/fdroid/fdroid/UpdateService.java index e87b7e725..1b875a341 100644 --- a/app/src/main/java/org/fdroid/fdroid/UpdateService.java +++ b/app/src/main/java/org/fdroid/fdroid/UpdateService.java @@ -123,6 +123,10 @@ public class UpdateService extends JobIntentService { * @see JobIntentService#enqueueWork(Context, Class, int, Intent) */ private static void enqueueWork(Context context, @NonNull Intent intent) { + if (!Preferences.get().isOnDemandDownloadAllowed()) { + Toast.makeText(context, R.string.updates_disabled_by_settings, Toast.LENGTH_LONG).show(); + } + enqueueWork(context, UpdateService.class, JOB_ID, intent); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4169e1415..60ff065fe 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -129,6 +129,7 @@ This often occurs with apps installed via Google Play or other sources, if they Download update for %1$d app. Download updates for %1$d apps. + All updates disabled by Data/WiFi Settings OK From e44ca193dd0adcbc5e240410aec4c681f5053dae Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 19 Jul 2018 11:57:37 +0200 Subject: [PATCH 2/8] save result of Preferences.get() to speed up start up times The initial start time is getting pretty slow, so hopefully this will save a little bit. It also makes it consistent with other places in the code, like UpdateService. --- .../java/org/fdroid/fdroid/FDroidApp.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java index 19c097646..5b01a816d 100644 --- a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java +++ b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java @@ -349,8 +349,9 @@ public class FDroidApp extends Application { } Preferences.setup(this); Languages.setLanguage(this); + Preferences preferences = Preferences.get(); - if (Preferences.get().promptToSendCrashReports()) { + if (preferences.promptToSendCrashReports()) { ACRA.init(this); if (isAcraProcess() || HidingManager.isHidden(this)) { return; @@ -359,16 +360,15 @@ public class FDroidApp extends Application { PRNGFixes.apply(); - curTheme = Preferences.get().getTheme(); - Preferences.get().configureProxy(); + curTheme = preferences.getTheme(); + preferences.configureProxy(); // bug specific to exactly 5.0 makes it only work with the old index // which includes an ugly, hacky workaround // https://gitlab.com/fdroid/fdroidclient/issues/1014 if (Build.VERSION.SDK_INT == 21) { - Preferences p = Preferences.get(); - p.setExpertMode(true); - p.setForceOldIndex(true); + preferences.setExpertMode(true); + preferences.setForceOldIndex(true); } InstalledAppProviderService.compareToPackageManager(this); @@ -376,7 +376,7 @@ public class FDroidApp extends Application { // If the user changes the preference to do with filtering rooted apps, // it is easier to just notify a change in the app provider, // so that the newly updated list will correctly filter relevant apps. - Preferences.get().registerAppsRequiringRootChangeListener(new Preferences.ChangeListener() { + preferences.registerAppsRequiringRootChangeListener(new Preferences.ChangeListener() { @Override public void onPreferenceChange() { getContentResolver().notifyChange(AppProvider.getContentUri(), null); @@ -386,14 +386,14 @@ public class FDroidApp extends Application { // If the user changes the preference to do with filtering anti-feature apps, // it is easier to just notify a change in the app provider, // so that the newly updated list will correctly filter relevant apps. - Preferences.get().registerAppsRequiringAntiFeaturesChangeListener(new Preferences.ChangeListener() { + preferences.registerAppsRequiringAntiFeaturesChangeListener(new Preferences.ChangeListener() { @Override public void onPreferenceChange() { getContentResolver().notifyChange(AppProvider.getContentUri(), null); } }); - Preferences.get().registerUnstableUpdatesChangeListener(new Preferences.ChangeListener() { + preferences.registerUnstableUpdatesChangeListener(new Preferences.ChangeListener() { @Override public void onPreferenceChange() { AppProvider.Helper.calcSuggestedApks(FDroidApp.this); @@ -457,16 +457,16 @@ public class FDroidApp extends Application { FDroidApp.initWifiSettings(); WifiStateChangeService.start(this, null); // if the HTTPS pref changes, then update all affected things - Preferences.get().registerLocalRepoHttpsListeners(new ChangeListener() { + preferences.registerLocalRepoHttpsListeners(new ChangeListener() { @Override public void onPreferenceChange() { WifiStateChangeService.start(getApplicationContext(), null); } }); - configureTor(Preferences.get().isTorEnabled()); + configureTor(preferences.isTorEnabled()); - if (Preferences.get().isKeepingInstallHistory()) { + if (preferences.isKeepingInstallHistory()) { InstallHistoryService.register(this); } @@ -492,7 +492,7 @@ public class FDroidApp extends Application { atStartTime.edit().putInt("build-version", Build.VERSION.SDK_INT).apply(); final String queryStringKey = "http-downloader-query-string"; - if (Preferences.get().sendVersionAndUUIDToServers()) { + if (preferences.sendVersionAndUUIDToServers()) { HttpDownloader.queryString = atStartTime.getString(queryStringKey, null); if (HttpDownloader.queryString == null) { UUID uuid = UUID.randomUUID(); From 0d386b824fc58cf296ba28fec466cc2beffca062 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 19 Jul 2018 13:42:49 +0200 Subject: [PATCH 3/8] merges triedEmptyUpdate and lastUpdateCheck prefs into one useful one This merges the triedEmptyUpdate preference into the lastUpdateCheck pref, and uses that to determine whether the index update has ever run. It seems that lastUpdateCheck used to be used for that, but was semi-disabled. Then triedEmptyUpdate was added. This merges the two into lastUpdateCheck, which also tracks the timestamp of the last index update. --- .../java/org/fdroid/fdroid/FDroidApp.java | 6 +++- .../java/org/fdroid/fdroid/Preferences.java | 30 ++++++++++++------- .../java/org/fdroid/fdroid/UpdateService.java | 8 +---- .../java/org/fdroid/fdroid/data/DBHelper.java | 4 +-- .../fdroid/views/main/MainActivity.java | 4 +-- 5 files changed, 28 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java index 5b01a816d..640d3f6f1 100644 --- a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java +++ b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java @@ -403,7 +403,6 @@ public class FDroidApp extends Application { CleanCacheService.schedule(this); notificationHelper = new NotificationHelper(getApplicationContext()); - UpdateService.schedule(getApplicationContext()); bluetoothAdapter = getBluetoothAdapter(); // There are a couple things to pay attention to with this config: memory usage, @@ -452,7 +451,12 @@ public class FDroidApp extends Application { .build(); ImageLoader.getInstance().init(config); + if (preferences.isIndexNeverUpdated()) { + // force this check to ensure it starts fetching the index on initial runs + networkState = ConnectivityMonitorService.getNetworkState(this); + } ConnectivityMonitorService.registerAndStart(this); + UpdateService.schedule(getApplicationContext()); FDroidApp.initWifiSettings(); WifiStateChangeService.start(this, null); diff --git a/app/src/main/java/org/fdroid/fdroid/Preferences.java b/app/src/main/java/org/fdroid/fdroid/Preferences.java index 68def793a..ce0413c7e 100644 --- a/app/src/main/java/org/fdroid/fdroid/Preferences.java +++ b/app/src/main/java/org/fdroid/fdroid/Preferences.java @@ -101,7 +101,6 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh public static final String PREF_PROXY_PORT = "proxyPort"; public static final String PREF_SHOW_NFC_DURING_SWAP = "showNfcDuringSwap"; public static final String PREF_POST_PRIVILEGED_INSTALL = "postPrivilegedInstall"; - public static final String PREF_TRIED_EMPTY_UPDATE = "triedEmptyUpdate"; public static final String PREF_PREVENT_SCREENSHOTS = "preventScreenshots"; public static final String PREF_PANIC_EXIT = "pref_panic_exit"; public static final String PREF_PANIC_HIDE = "pref_panic_hide"; @@ -114,10 +113,14 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh public static final int OVER_NETWORK_ON_DEMAND = 1; public static final int OVER_NETWORK_ALWAYS = 2; + // not shown in Settings + private static final String PREF_LAST_UPDATE_CHECK = "lastUpdateCheck"; + // these preferences are not listed in preferences.xml so the defaults are set here @SuppressWarnings("PMD.AvoidUsingHardCodedIP") public static final String DEFAULT_PROXY_HOST = "127.0.0.1"; // TODO move to preferences.xml public static final int DEFAULT_PROXY_PORT = 8118; // TODO move to preferences.xml + private static final int DEFAULT_LAST_UPDATE_CHECK = -1; private static final boolean DEFAULT_SHOW_NFC_DURING_SWAP = true; private static final boolean DEFAULT_POST_PRIVILEGED_INSTALL = false; private static final boolean DEFAULT_PANIC_EXIT = true; @@ -321,18 +324,23 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh } } - /** - * Used the first time F-Droid is installed to flag whether or not we have tried to request - * apps from the repo. This is used so that when there is no apps available, we can differentiate - * between whether the repos actually have no apps (in which case we don't need to continue - * asking), or whether there is no apps because we have never actually asked to update the repos. - */ - public boolean hasTriedEmptyUpdate() { - return preferences.getBoolean(PREF_TRIED_EMPTY_UPDATE, IGNORED_B); + public long getLastUpdateCheck() { + return preferences.getLong(PREF_LAST_UPDATE_CHECK, DEFAULT_LAST_UPDATE_CHECK); } - public void setTriedEmptyUpdate(boolean value) { - preferences.edit().putBoolean(PREF_TRIED_EMPTY_UPDATE, value).apply(); + public void setLastUpdateCheck(long lastUpdateCheck) { + preferences.edit().putLong(PREF_LAST_UPDATE_CHECK, lastUpdateCheck).apply(); + } + + public void resetLastUpdateCheck() { + setLastUpdateCheck(DEFAULT_LAST_UPDATE_CHECK); + } + + /** + * The first time the app has been run since fresh install or clearing all data. + */ + public boolean isIndexNeverUpdated() { + return getLastUpdateCheck() == DEFAULT_LAST_UPDATE_CHECK; } public boolean getUnstableUpdates() { diff --git a/app/src/main/java/org/fdroid/fdroid/UpdateService.java b/app/src/main/java/org/fdroid/fdroid/UpdateService.java index 1b875a341..3759f61ed 100644 --- a/app/src/main/java/org/fdroid/fdroid/UpdateService.java +++ b/app/src/main/java/org/fdroid/fdroid/UpdateService.java @@ -29,7 +29,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.SharedPreferences; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; @@ -41,7 +40,6 @@ import android.support.annotation.NonNull; import android.support.v4.app.JobIntentService; import android.support.v4.app.NotificationCompat; import android.support.v4.content.LocalBroadcastManager; -import android.support.v7.preference.PreferenceManager; import android.text.TextUtils; import android.util.Log; import android.widget.Toast; @@ -82,7 +80,6 @@ public class UpdateService extends JobIntentService { public static final int STATUS_ERROR_LOCAL_SMALL = 4; public static final int STATUS_INFO = 5; - private static final String STATE_LAST_UPDATED = "lastUpdateCheck"; private static final int JOB_ID = 0xfedcba; private static final int NOTIFY_ID_UPDATING = 0; @@ -498,10 +495,7 @@ public class UpdateService extends JobIntentService { } } - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext()); - SharedPreferences.Editor e = prefs.edit(); - e.putLong(STATE_LAST_UPDATED, System.currentTimeMillis()); - e.apply(); + fdroidPrefs.setLastUpdateCheck(System.currentTimeMillis()); if (errorRepos == 0) { if (changes) { diff --git a/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java b/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java index ee39e383e..7e60661b9 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java +++ b/app/src/main/java/org/fdroid/fdroid/data/DBHelper.java @@ -1095,7 +1095,7 @@ public class DBHelper extends SQLiteOpenHelper { private static void resetTransient(SQLiteDatabase db) { Utils.debugLog(TAG, "Removing all index tables, they will be recreated next time F-Droid updates."); - Preferences.get().setTriedEmptyUpdate(false); + Preferences.get().resetLastUpdateCheck(); db.beginTransaction(); try { @@ -1147,7 +1147,7 @@ public class DBHelper extends SQLiteOpenHelper { return; } - Preferences.get().setTriedEmptyUpdate(false); + Preferences.get().resetLastUpdateCheck(); db.execSQL("drop table " + AppMetadataTable.NAME); db.execSQL("drop table " + ApkTable.NAME); diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java index fcf90e1c2..beb172523 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java @@ -164,10 +164,8 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB * don't try to do it automatically again. */ private void initialRepoUpdateIfRequired() { - Preferences prefs = Preferences.get(); - if (!prefs.hasTriedEmptyUpdate()) { + if (!Preferences.get().isIndexNeverUpdated()) { Utils.debugLog(TAG, "We haven't done an update yet. Forcing repo update."); - prefs.setTriedEmptyUpdate(true); UpdateService.updateNow(this); } } From 048d5531bea900fcc4e45eff8116b78f19cd2236 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 19 Jul 2018 13:43:19 +0200 Subject: [PATCH 4/8] only first trigger initial repo update if it is not already happening I was seeing double index updates on first start. --- app/src/main/java/org/fdroid/fdroid/UpdateService.java | 5 +++-- .../java/org/fdroid/fdroid/views/main/MainActivity.java | 7 +------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/UpdateService.java b/app/src/main/java/org/fdroid/fdroid/UpdateService.java index 3759f61ed..05f459e11 100644 --- a/app/src/main/java/org/fdroid/fdroid/UpdateService.java +++ b/app/src/main/java/org/fdroid/fdroid/UpdateService.java @@ -84,6 +84,7 @@ public class UpdateService extends JobIntentService { private static final int NOTIFY_ID_UPDATING = 0; + private static UpdateService updateService; private static Handler toastHandler; private NotificationManager notificationManager; @@ -189,6 +190,8 @@ public class UpdateService extends JobIntentService { /** * Whether or not a repo update is currently in progress. Used to show feedback throughout * the app to users, so they know something is happening. + * + * @see set a global variable when it is running that your client can check */ public static boolean isUpdating() { return updateService != null; @@ -240,8 +243,6 @@ public class UpdateService extends JobIntentService { } - private static UpdateService updateService; - public static void stopNow(Context context) { if (updateService != null) { updateService.stopSelf(JOB_ID); diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java index beb172523..888dd0aec 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/MainActivity.java @@ -158,13 +158,8 @@ public class MainActivity extends AppCompatActivity implements BottomNavigationB bottomNavigation.selectTab(adapter.adapterPositionFromItemId(selectedMenuId)); } - /** - * The first time the app is run, we will have an empty app list. To deal with this, we will - * attempt to update with the default repo. However, if we have tried this at least once, then - * don't try to do it automatically again. - */ private void initialRepoUpdateIfRequired() { - if (!Preferences.get().isIndexNeverUpdated()) { + if (Preferences.get().isIndexNeverUpdated() && !UpdateService.isUpdating()) { Utils.debugLog(TAG, "We haven't done an update yet. Forcing repo update."); UpdateService.updateNow(this); } From 339afa1e7253ec3ad2869e937485c316bfa57c3b Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 19 Jul 2018 14:33:25 +0200 Subject: [PATCH 5/8] show indeterminite progress if doing initial index update #509 --- .../fdroid/fdroid/views/main/WhatsNewViewBinder.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/full/java/org/fdroid/fdroid/views/main/WhatsNewViewBinder.java b/app/src/full/java/org/fdroid/fdroid/views/main/WhatsNewViewBinder.java index acb91388a..2ad7c0115 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/main/WhatsNewViewBinder.java +++ b/app/src/full/java/org/fdroid/fdroid/views/main/WhatsNewViewBinder.java @@ -13,8 +13,9 @@ import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.ProgressBar; import android.widget.TextView; - import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.R; import org.fdroid.fdroid.UpdateService; @@ -124,6 +125,14 @@ class WhatsNewViewBinder implements LoaderManager.LoaderCallbacks { } private void explainEmptyStateToUser() { + if (Preferences.get().isIndexNeverUpdated() && UpdateService.isUpdating()) { + LinearLayout linearLayout = (LinearLayout) appList.getParent(); + linearLayout.addView(new ProgressBar(activity, null, android.R.attr.progressBarStyleLarge)); + emptyState.setVisibility(View.GONE); + appList.setVisibility(View.GONE); + return; + } + StringBuilder emptyStateText = new StringBuilder(); emptyStateText.append(activity.getString(R.string.latest__empty_state__no_recent_apps)); emptyStateText.append("\n\n"); From 34c788681bb7f4fa0c0017044e321ed364eee81d Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 20 Jul 2018 10:34:35 +0200 Subject: [PATCH 6/8] ensure single progressbar is shown while doing first index update --- .../org/fdroid/fdroid/views/main/WhatsNewViewBinder.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/full/java/org/fdroid/fdroid/views/main/WhatsNewViewBinder.java b/app/src/full/java/org/fdroid/fdroid/views/main/WhatsNewViewBinder.java index 2ad7c0115..c53932349 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/main/WhatsNewViewBinder.java +++ b/app/src/full/java/org/fdroid/fdroid/views/main/WhatsNewViewBinder.java @@ -41,6 +41,8 @@ class WhatsNewViewBinder implements LoaderManager.LoaderCallbacks { private final TextView emptyState; private final RecyclerView appList; + private ProgressBar progressBar; + WhatsNewViewBinder(final AppCompatActivity activity, FrameLayout parent) { this.activity = activity; @@ -126,8 +128,13 @@ class WhatsNewViewBinder implements LoaderManager.LoaderCallbacks { private void explainEmptyStateToUser() { if (Preferences.get().isIndexNeverUpdated() && UpdateService.isUpdating()) { + if (progressBar != null) { + return; + } LinearLayout linearLayout = (LinearLayout) appList.getParent(); - linearLayout.addView(new ProgressBar(activity, null, android.R.attr.progressBarStyleLarge)); + progressBar = new ProgressBar(activity, null, android.R.attr.progressBarStyleLarge); + progressBar.setId(R.id.progress_bar); + linearLayout.addView(progressBar); emptyState.setVisibility(View.GONE); appList.setVisibility(View.GONE); return; From 2040d885f2549b2a63c1c6784862c7a9aa1ba8c7 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 20 Jul 2018 10:41:27 +0200 Subject: [PATCH 7/8] do not show Data/WiFi Settings Toast if device has no internet Before, if the Data/WiFi Settings made it so the update process is not allowed to run and the device was not offline or in Airplane Mode, it would show this Toast then it would show the "your device is offline" Toast. --- app/src/main/java/org/fdroid/fdroid/UpdateService.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/UpdateService.java b/app/src/main/java/org/fdroid/fdroid/UpdateService.java index 05f459e11..2e41694fe 100644 --- a/app/src/main/java/org/fdroid/fdroid/UpdateService.java +++ b/app/src/main/java/org/fdroid/fdroid/UpdateService.java @@ -116,12 +116,16 @@ public class UpdateService extends JobIntentService { } /** - * Add work to the queue for processing now + * Add work to the queue for processing now. + *

+ * This also shows a {@link Toast} if the Data/WiFi Settings make it so the + * update process is not allowed to run and the device is attached to a + * network (e.g. is not offline or in Airplane Mode). * * @see JobIntentService#enqueueWork(Context, Class, int, Intent) */ private static void enqueueWork(Context context, @NonNull Intent intent) { - if (!Preferences.get().isOnDemandDownloadAllowed()) { + if (FDroidApp.networkState > 0 && !Preferences.get().isOnDemandDownloadAllowed()) { Toast.makeText(context, R.string.updates_disabled_by_settings, Toast.LENGTH_LONG).show(); } From 25016fdb2f1a3e84f634e2c15ab0e40a80d327d1 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 20 Jul 2018 12:26:33 +0200 Subject: [PATCH 8/8] gitlab-ci: switch to 24 emulator to get some useful results The emulator support seems to have totally melted down, so this is a step back towards the old working setup. --- .gitlab-ci.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 09eeaf944..605135467 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -70,8 +70,7 @@ errorprone: - ./gradlew connectedCheck || (adb -e logcat -d '*:E' > logcat.txt; exit 1) connected24: - only: - - fdroid/fdroidclient@master + retry: 1 <<: *test-template variables: AVD_SDK: "24" @@ -79,10 +78,6 @@ connected24: AVD_PACKAGE: "system-images;android-${AVD_SDK};${AVD_TAG};armeabi-v7a" <<: *connected-template -connected25: - <<: *test-template - <<: *connected-template - deploy_nightly: stage: deploy only: