1
0
Fork 0
mirror of https://github.com/syncthing/syncthing-android.git synced 2024-12-23 11:21:29 +00:00

Merge branch 'automatic-release'

This commit is contained in:
Felix Ableitner 2016-09-20 11:27:01 +09:00
commit 1e9c9b4cea
10 changed files with 192 additions and 152 deletions

View file

@ -29,6 +29,8 @@ Set the `ANDROID_NDK` environment variable to the Android NDK folder (e.g. `expo
Build Go and Syncthing using `./make-all.bash`.
Use `./gradlew assembleDebug` in the project directory to compile the APK.
To prepare a new release, execute `./prepare-release.bash`, and follow the instructions.
To check for updated gradle dependencies, run `gradle dependencyUpdates`. Additionally, the git submodule in `ext/syncthing/src/github.com/syncthing/syncthing` may need to be updated.

View file

@ -26,6 +26,8 @@ dependencies {
compile 'com.google.zxing:android-integration:3.2.1'
compile 'com.google.code.gson:gson:2.7'
compile 'org.mindrot:jbcrypt:0.3m'
testCompile 'junit:junit:4.12'
testCompile 'org.robolectric:robolectric:3.1.2'
androidTestCompile 'com.squareup.okhttp:mockwebserver:2.4.0'
}

79
prepare-release.bash Executable file
View file

@ -0,0 +1,79 @@
#!/bin/bash
set -e
NEW_VERSION_NAME=$1
OLD_VERSION_NAME=$(grep "versionName" "build.gradle" | awk '{print $2}')
if [[ -z $NEW_VERSION_NAME ]]
then
echo "New version name is empty. Please set a new version. Current version: $OLD_VERSION_NAME"
exit
fi
echo "
Checking for Syncthing Update
-----------------------------
"
PROJECT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "ext/syncthing/src/github.com/syncthing/syncthing/"
git fetch
CURRENT_TAG=$(git describe)
LATEST_TAG=$(git describe $(git rev-list --tags --max-count=1))
if [ $CURRENT_TAG != $LATEST_TAG ]
then
git checkout -f $LATEST_TAG
cd $PROJECT_DIR
git add "ext/syncthing/src/github.com/syncthing/syncthing"
git commit -m "Updated Syncthing to $LATEST_TAG"
./gradlew cleanNative buildNative
fi
cd $PROJECT_DIR
echo "
Updating Translations
-----------------------------
"
tx push -s
tx pull -a
./gradlew deleteUnsupportedPlayTranslations publishListingFatRelease
git add -A "src/fat/play/"
git add -A "src/main/res/values-*/strings.xml"
if ! git diff --cached --exit-code;
then
git commit -m "Imported translations"
fi
echo "
Running Tests
-----------------------------
"
./gradlew lint
./gradlew connectedFatDebugAndroidTest
./gradlew testFatDebugUnitTest
echo "
Updating Version
-----------------------------
"
OLD_VERSION_CODE=$(grep "versionCode" "build.gradle" -m 1 | awk '{print $2}')
NEW_VERSION_CODE=$(($OLD_VERSION_CODE + 1))
sed -i "s/versionCode $OLD_VERSION_CODE/versionCode $NEW_VERSION_CODE/" build.gradle
OLD_VERSION_NAME=$(grep "versionName" "build.gradle" | awk '{print $2}')
sed -i "s/$OLD_VERSION_NAME/\"$1\"/" build.gradle
git add "build.gradle"
git commit -m "Bumped version to $NEW_VERSION_NAME"
echo "
Update ready.
1. Run \`git push --follow-tags\`
2. Enter release notes at https://github.com/syncthing/syncthing-android/releases
3. Enter release notes at https://android.syncthing.net/job/Syncthing-Android-Release/configure
4. Start build at https://android.syncthing.net/job/Syncthing-Android-Release
"

View file

@ -11,9 +11,8 @@ import java.util.List;
public class MockRestApi extends RestApi {
public MockRestApi(Context context, String url, String apiKey,
String guiUser, String guiPassword,
OnApiAvailableListener listener) {
super(context, url, apiKey, guiUser, guiPassword, listener, null);
super(context, url, apiKey, listener, null);
}
@Override

View file

@ -49,7 +49,7 @@ public class MockSyncthingService extends SyncthingService {
@Override
public RestApi getApi() {
return new MockRestApi(this, null, null, null, null, null);
return new MockRestApi(this, null, null, null);
}
@Override

View file

@ -26,7 +26,6 @@ public class RestApiTest extends AndroidTestCase {
new SyncthingRunnable(new MockContext(getContext()), SyncthingRunnable.Command.main);
ConfigXml config = new ConfigXml(new MockContext(getContext()));
config.changeDefaultFolder();
String httpsCertPath = getContext().getFilesDir() + "/" + SyncthingService.HTTPS_CERT_FILE;
@ -39,7 +38,6 @@ public class RestApiTest extends AndroidTestCase {
}
}.execute(config.getWebGuiUrl());
mApi = new RestApi(getContext(), config.getWebGuiUrl(), config.getApiKey(),
null, null,
new RestApi.OnApiAvailableListener() {
@Override
public void onApiAvailable() {

View file

@ -1,121 +0,0 @@
package com.nutomic.syncthingandroid.test.syncthing;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.test.ServiceTestCase;
import com.nutomic.syncthingandroid.syncthing.SyncthingService;
import com.nutomic.syncthingandroid.syncthing.SyncthingServiceBinder;
import com.nutomic.syncthingandroid.test.MockContext;
import com.nutomic.syncthingandroid.test.Util;
import com.nutomic.syncthingandroid.util.ConfigXml;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* These tests assume that syncthing keys have already been generated. If not, tests may fail
* because startup takes too long.
*/
public class SyncthingServiceTest extends ServiceTestCase<SyncthingService> {
private Context mContext;
public SyncthingServiceTest() {
super(SyncthingService.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = new MockContext(getContext());
}
@Override
protected void tearDown() throws Exception {
Util.deleteRecursive(mContext.getFilesDir());
PreferenceManager.getDefaultSharedPreferences(getContext()).edit().clear().commit();
super.tearDown();
}
public void testFirstStart() {
setContext(mContext);
startService(new Intent(mContext, SyncthingService.class));
assertTrue(getService().isFirstStart());
}
public void testNotFirstStart() throws IOException {
setContext(mContext);
startService(new Intent(mContext, SyncthingService.class));
new File(mContext.getFilesDir(), SyncthingService.PUBLIC_KEY_FILE).createNewFile();
assertFalse(getService().isFirstStart());
}
public void testBindService() throws InterruptedException {
SyncthingServiceBinder binder = (SyncthingServiceBinder)
bindService(new Intent(getContext(), SyncthingService.class));
SyncthingService service = binder.getService();
final CountDownLatch latch = new CountDownLatch(2);
getService().registerOnWebGuiAvailableListener(new SyncthingService.OnWebGuiAvailableListener() {
@Override
public void onWebGuiAvailable() {
latch.countDown();
}
});
getService().registerOnApiChangeListener(new SyncthingService.OnApiChangeListener() {
@Override
public void onApiChange(SyncthingService.State currentState) {
latch.countDown();
}
});
latch.await(1, TimeUnit.SECONDS);
assertNotNull(service);
}
public void testImportExportConfig() {
setContext(mContext);
SyncthingServiceBinder binder = (SyncthingServiceBinder)
bindService(new Intent(getContext(), SyncthingService.class));
SyncthingService service = binder.getService();
File config = new File(mContext.getFilesDir(), ConfigXml.CONFIG_FILE);
File privateKey = new File(mContext.getFilesDir(), SyncthingService.PRIVATE_KEY_FILE);
File publicKey = new File(mContext.getFilesDir(), SyncthingService.PUBLIC_KEY_FILE);
try {
config.createNewFile();
privateKey.createNewFile();
publicKey.createNewFile();
} catch (IOException e) {
fail();
}
service.exportConfig();
config.delete();
privateKey.delete();
publicKey.delete();
service.importConfig();
assertTrue(config.exists());
assertTrue(privateKey.exists());
assertTrue(publicKey.exists());
}
public void testPassword() throws InterruptedException {
startService(new Intent(getContext(), SyncthingService.class));
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
assertNotNull(sp.getString("gui_user", null));
assertEquals(20, sp.getString("gui_password", null).length());
}
}, 5000);
}
}

View file

@ -38,17 +38,4 @@ public class ConfigXmlTest extends AndroidTestCase {
assertTrue(mConfig.getWebGuiUrl().startsWith("https://127.0.0.1:"));
}
/**
* Just make sure the file is actually changed.
*
* This is not ideal, but way less complicated than starting up syncthing and accessing the API.
*/
public void testCreateCameraFolder() {
long oldTime = ConfigXml.getConfigFile(mContext).lastModified();
long oldSize = ConfigXml.getConfigFile(mContext).length();
mConfig.changeDefaultFolder();
assertNotSame(oldTime, ConfigXml.getConfigFile(mContext).lastModified());
assertNotSame(oldSize, ConfigXml.getConfigFile(mContext).lastModified());
}
}

View file

@ -59,8 +59,6 @@ public class ConfigXml {
*/
public static final String CONFIG_FILE = "config.xml";
private static final String INVALID_CONFIG_FILE = "config.xml.invalid";
private static final int OPEN_CONFIG_MAX_TRIES = 10;
private final Context mContext;
@ -83,19 +81,9 @@ public class ConfigXml {
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
mConfig = db.parse(mConfigFile);
} catch (SAXException | ParserConfigurationException | IOException e) {
Log.w(TAG, "Failed to open config, moving to " + INVALID_CONFIG_FILE +
" and creating blank config");
File dest = new File(mConfigFile.getParent(), INVALID_CONFIG_FILE);
if (dest.exists())
dest.delete();
mConfigFile.renameTo(dest);
generateKeysConfig(context);
isFirstStart = true;
mConfigFile = getConfigFile(context);
throw new OpenConfigException();
}
}
if (mConfig == null)
throw new OpenConfigException();
if (isFirstStart) {
changeDefaultFolder();

View file

@ -0,0 +1,106 @@
package com.nutomic.syncthingandroid.syncthing;
import android.content.SharedPreferences;
import android.os.Handler;
import android.preference.PreferenceManager;
import com.nutomic.syncthingandroid.BuildConfig;
import com.nutomic.syncthingandroid.util.ConfigXml;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
/**
* These tests assume that syncthing keys have already been generated. If not, tests may fail
* because startup takes too long.
*/
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class)
public class SyncthingServiceTest {
private SyncthingService mService;
@Before
public void setup() {
mService = Robolectric.buildService(SyncthingService.class).get();
mService.onCreate();
}
@Test
public void testFirstStart() {
assertTrue(mService.isFirstStart());
}
@Test
public void testNotFirstStart() throws IOException {
new File(mService.getFilesDir(), SyncthingService.PUBLIC_KEY_FILE).createNewFile();
assertFalse(mService.isFirstStart());
}
@Test
public void testBindService() throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(2);
mService.registerOnWebGuiAvailableListener(new SyncthingService.OnWebGuiAvailableListener() {
@Override
public void onWebGuiAvailable() {
latch.countDown();
}
});
mService.registerOnApiChangeListener(new SyncthingService.OnApiChangeListener() {
@Override
public void onApiChange(SyncthingService.State currentState) {
latch.countDown();
}
});
latch.await(1, TimeUnit.SECONDS);
assertNotNull(mService);
}
@Test
public void testImportExportConfig() {
File config = new File(mService.getFilesDir(), ConfigXml.CONFIG_FILE);
File privateKey = new File(mService.getFilesDir(), SyncthingService.PRIVATE_KEY_FILE);
File publicKey = new File(mService.getFilesDir(), SyncthingService.PUBLIC_KEY_FILE);
try {
config.createNewFile();
privateKey.createNewFile();
publicKey.createNewFile();
} catch (IOException e) {
fail();
}
mService.exportConfig();
config.delete();
privateKey.delete();
publicKey.delete();
assertTrue(mService.importConfig());
assertTrue(config.exists());
assertTrue(privateKey.exists());
assertTrue(publicKey.exists());
}
@Test
public void testPassword() throws InterruptedException {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mService);
assertNotNull(sp.getString("gui_user", null));
assertEquals(20, sp.getString("gui_password", null).length());
}
}, 5000);
}
}