From 6fe47b3441bccc6f5dd0860738fe3b520849f40e Mon Sep 17 00:00:00 2001 From: m133225 Date: Fri, 19 Aug 2016 14:53:01 +0800 Subject: [PATCH] Some documentation about learning basics of gradle. --- docs/addressbook/CloudSimulation.md | 78 --------- docs/addressbook/KeyboardShortcuts.md | 22 --- docs/devops/gradle/Configuring Travis CI.md | 37 ++++ docs/devops/gradle/Introduction to Gradle.md | 39 +++++ docs/{testing => devops/gradle}/Testing.md | 0 docs/images/Release Cycle.jpg | Bin 46942 -> 0 bytes docs/images/flick_repository_switch.png | Bin 0 -> 11224 bytes docs/images/signing_in.png | Bin 0 -> 15718 bytes .../releases/Automatic Update Architecture.md | 40 ----- docs/releases/Launcher.md | 2 - docs/releases/Release.md | 163 ------------------ docs/releases/Updater.md | 10 -- 12 files changed, 76 insertions(+), 315 deletions(-) delete mode 100644 docs/addressbook/CloudSimulation.md delete mode 100644 docs/addressbook/KeyboardShortcuts.md create mode 100644 docs/devops/gradle/Configuring Travis CI.md create mode 100644 docs/devops/gradle/Introduction to Gradle.md rename docs/{testing => devops/gradle}/Testing.md (100%) delete mode 100644 docs/images/Release Cycle.jpg create mode 100644 docs/images/flick_repository_switch.png create mode 100644 docs/images/signing_in.png delete mode 100644 docs/releases/Automatic Update Architecture.md delete mode 100644 docs/releases/Launcher.md delete mode 100644 docs/releases/Release.md delete mode 100644 docs/releases/Updater.md diff --git a/docs/addressbook/CloudSimulation.md b/docs/addressbook/CloudSimulation.md deleted file mode 100644 index 048cf3e750d3..000000000000 --- a/docs/addressbook/CloudSimulation.md +++ /dev/null @@ -1,78 +0,0 @@ -In order to simulate the idea of a cloud and our interactions with it, we have implemented 3 key components: `RemoteManager`, `RemoteService` and `CloudSimulator` - -They are arranged as follows: -> ... -> SyncManager <---> RemoteManager <---> RemoteService <---> CloudSimulator - -# Key responsibilities -## RemoteManager -- Provides a high-level API for the local model to communicate with the server without having to be involved in too many details -- Responsible for converting API calls into the cloud calls - - Uses paged requests to get the full list of resources (`Tag` and `Person`) -- Keeps track of information likely needed for the next update request to the remote e.g. **last** updated `time`, `ETag` and list of `Tags` - -## RemoteService -- Responsible for converting cloud responses into localised responses - - Parses the stream of the content returned from the cloud (which is originally in JSON format). This applies to both the header and the body content -- Deals with both local model and service model, and converts between them when needed -- Returns an `ExtractedRemoteResponse`, which contains the limit details as well as the returned (and converted) content that has been instantiated in memory - -## CloudSimulator -- Provides a similar set of API as GitHub -- Writes the content of addressbooks into individual files, based on their names - - For example, an addressbook `myContacts` will be written into `cloud/myContacts` and an addressbook `hisContacts` will be written into `cloud/hisContacts`. -- Maintains the API count of the current session - - Similar to GitHub (authenticated), it has an API limit of 5000 by default, and resets at every hour's mark - - The reset is based on a `TickingTimer` running in the background i.e. the reset is run after a given time delay -- Responses are returned as `RemoteResponse` - - ALWAYS (almost) contains the rate limit information. e.g. rate limit remaining and its next reset time - - The only time it doesn't is if there is an `internal server error` (500) - - ALWAYS contains the response code that indicates the status of the request. This response code is similar to its respective HTTP status code - - May contain content such as a `CloudPerson` object in JSON form, depending on the query and its success status -- If initialised with a `true` boolean, there will be chance of data modifications before the result is returned - - For lists, there may be `additions` and `modifications` - - For single objects, there may be `modifications` - - `additions` and `modifications` are both considered `mutations` - -# Notes -## Response code -- Behaves similarly to `GitHub` - - `20x` if request is successful. `x` depends on the type of request - - `304` if there are no changes since the last response - - These responses will not include the page relations - - `400 - Bad Request` if the arguments given are invalid - - `403 - Forbidden` if there is no more API quota left - - `500 - Internal Server Error` if there is an error on the cloud. e.g. error reading from the cloud file - -## CloudAddressBook -- Just a simple wrapper for cloud data, so that a single addressbook can be stored in a single cloud file - -## CloudPerson -- Whenever its field are updated, `lastUpdatedAt` will also be set to the current time. -- Whenever it is deleted, it still remains in the list with `isDeleted` set to true - -## CloudTag -- Whenever it is deleted, it is completely removed from the list of tags -- Does not have a `lastUpdatedAt` field - -# Other notes related to HT -- `Last-Modified` and `If-Modified-Since` headers do not seem to be useful - -`Last-Modified` (response) and `If-Modified-Since` (request) headers seem to only apply to single-objects that have the `updatedAt` field (`issues` and `milestones`). The `Last-Modified` header field will also have the same value as `updatedAt`. This means that these do not provide us more information than we already have. - -- We can check updates for `labels` and `collaborators` without incurring API usage (Invariant: they do not scale, at least not quickly) - -We need to simply save the `ETag` of the requests and use them in further calls. If the responses are that they are `304 Not Modified`, then it will not incur API usage. - -- We are able to reduce the number of API calls for getting updated issues -For `issues` and `issue comments`, we can try to do something similar to `labels` and `collaborators` (see above). However, since the requests are paged, we have increased workload if we were to use `ETag`s to check for updates. For example, having 1000 issues will require up to 10 requests using the old `ETag`s, to ensure that none of the pages have changed. Results will also have to in descending order, since new issues will change all pages' `ETag`s if in ascending order) - -We can instead just make a new `updated-since` request based on the date saved together with the last ETag. Any update requests will result in **>=1 (number of updated issues/issues per page)** API usage. However, even if there are no updates, 1 API quota will be used. - -Note: HT has not implemented retrieval of `issue comments` yet. The indicator we have now on the issue card is simply a count, which is included in the issue's information. - -## Problem: milestones -`Milestones` is a scalable resource (grows with the repo), and yet we are unable to retrieve `milestones` that have been modified after a certain time, like we can do with `issues` and `issue comments`. -One way to get around this is probably to extract information from the obtained `issues`, where each contains its assigned `milestone` information, and attempt to determine how the list of `milestones` has changed. -- Then, how do we know if a milestone has been unassigned? I guess the only way is to verify against the local model every time an issue has been updated, which may cost additional performance -- If a milestone of 1 issue is changed and the issue is demilestoned, we won't know that the milestone has changed since the issue updates won't reflect that. -- Maybe the best way is still to follow how we obtain updates for `labels` and `collaborators`, but the update may be slow. Could be mitigated by having a lower frequency of milestone updates diff --git a/docs/addressbook/KeyboardShortcuts.md b/docs/addressbook/KeyboardShortcuts.md deleted file mode 100644 index 4d58885aa315..000000000000 --- a/docs/addressbook/KeyboardShortcuts.md +++ /dev/null @@ -1,22 +0,0 @@ -#Key Bindings -> Note: On Mac OS, use in place of Ctrl - -##Shortcuts - -| Shortcut | Action | -| ------------------------------------: |--------| -| A | t**A**g the selected person | -| D | **D**elete the selected person | -| E | **E**dit the selected person | -| G,B | **G**o to **B**ottom of the list | -| G,T | **G**o to **T**op of the list | -| Ctrl + Down | Jump from filter box to person list | -| Ctrl + Number | Jump to Nth item in the person list, N=1..9 | - -##Hotkeys -Unlike keyboard shortcuts given above, hotkeys work even when the app is not in focus. - -| Shortcut | Action | -| ------------------------------------: |--------| -| Ctrl + Alt + X | Minimize app | -| Ctrl + Shift + X | Toggle between maximum and default app Window sizes| diff --git a/docs/devops/gradle/Configuring Travis CI.md b/docs/devops/gradle/Configuring Travis CI.md new file mode 100644 index 000000000000..6db71bae7a77 --- /dev/null +++ b/docs/devops/gradle/Configuring Travis CI.md @@ -0,0 +1,37 @@ +# Travis CI + +## Background +[Travis CI](https://travis-ci.org/) is a continuous integration platform for GitHub projects. + +We are able to setup Travis CI such that it is able to run the projects' tests automatically whenever there is a new update. This is to ensure that existing functionality and features have not been broken with the new commits. + +See [Travis CI Documentation](https://docs.travis-ci.com/) for more details. + +## Setting up Travis CI + +1. Fork the repository to your own organization. +2. Go to https://travis-ci.org/ and click `Sign in with GitHub`, then enter your GitHub account details if needed. +![Signing into Travis CI](../../images/signing_in.png) + +3. Head to the travis [Accounts](https://travis-ci.org/profile) page, and find the travis CI switch for the forked repository. + - If repository cannot be found, click `Sync account` +4. Activate the travis CI switch. +![Activate the switch](../../images/flick_repository_switch.png) +5. Create the following `travis.yml` file in the main folder +``` +language: java +matrix: + include: + - jdk: oraclejdk8 +script: ./gradlew clean headless allTests coverage coveralls -i +before_install: + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" + +addons: + apt: + packages: + - oracle-java8-installer +``` + +To see the CI in action, push a commit to the master branch! \ No newline at end of file diff --git a/docs/devops/gradle/Introduction to Gradle.md b/docs/devops/gradle/Introduction to Gradle.md new file mode 100644 index 000000000000..affdac70cdc9 --- /dev/null +++ b/docs/devops/gradle/Introduction to Gradle.md @@ -0,0 +1,39 @@ +# Gradle + +## Background +[Gradle](https://gradle.org/) is an integration technology that addressbook uses for continuous integration: +- building the application JAR +- handling project dependencies +- testing (including coverage of test cases) +- checking for bugs & code style violations + +We have wrapped our project in a [Gradle Wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html), so that anyone who has cloned the repository can perform the same gradle tasks to manage dependencies or perform automated testing. +The gradle details are defined in `build.gradle`, which is a Groovy script. You can start learning them from [Build Scripts Basics](https://docs.gradle.org/current/userguide/tutorial_using_tasks.html). + + +## Gradle Tasks + +There are default gradle tasks provided for each plugin (e.g. `java`, `checkstyle`) used in the gradle script. In addition, we are able to define custom gradle tasks if required. (See [Testing.md](./Testing.md)) +See Gradle's [Java Plugin](https://docs.gradle.org/current/userguide/java_plugin.html)'s `Figure 45.1` to see the hierarchical overview of common gradle tasks. + +### Managing Dependencies + +To manage dependencies, we simply have to define [maven repositories](https://maven.apache.org/guides/introduction/introduction-to-repositories.html) in `build.gradle` to download each of them. +This will allow us to avoid adding dependencies into the repository. +- Consistent version of dependencies between developers +- If there are updates to the dependencies, developers will be able to download the latest versions (only if specified in the script) without having to update the script +- Less bloated repository + +The following tasks are related to ensuring that the required dependencies are downloaded and used. + +#### `compileJava` +`assemble`, `build`, `jar` are **examples** of tasks that will call `compileJava`. +This will check whether the project has the required dependencies to run the main program, and download any missing dependencies before compiling the classes. + +See `build.gradle` -> `allprojects` -> `dependencies` -> `compile` for the list of dependencies required. + +#### `compileTestJava` +`test` is an **example** of a task that will call `compileTestJava`. +This will check whether the project has the required dependencies to perform testing, and download any missing dependencies before compiling the test classes. + +See `build.gradle` -> `allprojects` -> `dependencies` -> `testCompile` for the list of dependencies required. \ No newline at end of file diff --git a/docs/testing/Testing.md b/docs/devops/gradle/Testing.md similarity index 100% rename from docs/testing/Testing.md rename to docs/devops/gradle/Testing.md diff --git a/docs/images/Release Cycle.jpg b/docs/images/Release Cycle.jpg deleted file mode 100644 index aa0340f1d7d0a52af5af0172b2004d9d4d475e77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46942 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 ZQd)Q(Rx?%eZM}IBcy?^yfMEImHv#n_BKrUU diff --git a/docs/images/flick_repository_switch.png b/docs/images/flick_repository_switch.png new file mode 100644 index 0000000000000000000000000000000000000000..a6009dd44cdb966db6b982516a852a96b206dd40 GIT binary patch literal 11224 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 literal 0 HcmV?d00001 diff --git a/docs/images/signing_in.png b/docs/images/signing_in.png new file mode 100644 index 0000000000000000000000000000000000000000..6d1ad4fe26f3ff978b42b63ca5e03bd76719cebc GIT binary patch literal 15718 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 LWQ8lg>j(ZH=GRuS literal 0 HcmV?d00001 diff --git a/docs/releases/Automatic Update Architecture.md b/docs/releases/Automatic Update Architecture.md deleted file mode 100644 index 57196d88518d..000000000000 --- a/docs/releases/Automatic Update Architecture.md +++ /dev/null @@ -1,40 +0,0 @@ -# Update Architecture -We enabled our application to be self-updatable, and downloads only the required components when doing so. - -For more detailed information of the individual components, please see: - - [Launcher](Launcher.md) - - [Updater](Updater.md) - -For more detailed information on how we make a release with this architecture, please see: - - [Release](Release.md) - -## Application Usage Flow - From downloading to updating -1. The user downloads the `installer` from the website, and saves it in a desired directory. -2. Upon execution of the `installer`, it unpacks the required files for the application into the same directory. - - Launcher - - Library files (including the main application) - - Config file -3. `Installer` also starts the `launcher` before it closes. -4. `Launcher` launches the `main application` with its run-time dependencies, as well as any desired arguments. -5. The `main application` runs, and checks for updates in the background. - - If there is an update, it will download any required libraries, produce a specification file with information about these files and extract an internal `updater` resource in preparation for the upgrade. Required libraries may also include a new version of the `launcher`. -6. Upon exit of the main application, the extracted `updater` resource is executed. - - This JAR is a fat JAR and already contains required dependencies e.g. to read the specification file. -7. The `updater` resource will read the specification file, and perform the needed operations for version upgrade. - - After updating, this resource will close and be left in the directory, and will probably be overwritten in the next update - -## Constraints and Considerations - -Here are some of the constraints we faced during the design of the update architecture: - -- On Windows, dependencies used during program runtime cannot be modified - - A separate executable has to be used to perform updates to the application. - - - Possible solution A: Create a launcher that checks for new versions and performs updates. - - However, we would also like to make updates to this separate executable. - - Possible solution B: Also have an update component in the main application, so the main application and the executable can update each other perpetually. - - However, this will result in duplicate update codes, and the update status cannot be shown on the main application. (At least not in a straightforward way. I guess we could still write the update status to a file and make the main app poll for status changes.) - - - Current solution: Main application extracts an internal resource which is launched to perform the update. - - Drawbacks: We cannot update only the updater itself, and the main application will be slightly bloated since it requires some similar dependencies as the updater. - - Possible optimization: Change updater into a non-fat JAR. Its dependencies could be copied by the main application into the same directory as the extracted updater jar. diff --git a/docs/releases/Launcher.md b/docs/releases/Launcher.md deleted file mode 100644 index 88e50fcddc9d..000000000000 --- a/docs/releases/Launcher.md +++ /dev/null @@ -1,2 +0,0 @@ -# Launcher -We compiled a simple launcher to launch our main application, typically with the name `addressbook-V...jar`. This is so that we are able to customize launch arguments for the main application. \ No newline at end of file diff --git a/docs/releases/Release.md b/docs/releases/Release.md deleted file mode 100644 index 60a3c01ed7a5..000000000000 --- a/docs/releases/Release.md +++ /dev/null @@ -1,163 +0,0 @@ -# Release - -## Background Information -### Versioning -An `addressbook` version has the format of `V..` with suffix of `ea` if it is an early access, e.g. -`V1.0.0ea` for early access version and `V1.0.0` for stable version. - -- `MAJOR` version is bumped up when a release introduces major changes to the application. -- `MINOR` version is bumped up on every release when `MAJOR` version does not change. -- `PATCH` version is bumped up when there is a hotfix needed for the current release version. - -This versioning system is loosely based on [Semantic Versioning](http://semver.org/). - -### Release cycle -`addressbook` has 3 branches for release, namely `master`, `early-access` and `stable`: -- `master` : development will occur in this branch. -- `early-access`: when we have a release candidate from master, the latest commit in `master` will be merged to this -branch and an early access release will be made for people to try out the new features. This release candidate will be -polished in this branch, i.e. any bug fixes to early access version will go to this branch, increasing the `PATCH` version number -(e.g. from `V1.1.-0-ea` to `V1.1.-1-ea`). This change is then merged back to master. - - If there are more features to be published for people to try out, a new early access release will be created with a bump -in `MINOR` version number, resetting the `PATCH` version number to 0. - - This release channel is not meant for production use. Those who are interested to try out the latest (possibly unstable) -features of Addressbook should use this early access version. -- `stable` : Once `early-access` version has enough polished features to be included in the new version for -production use, it will be released as a stable version with the same version number as the `early-access` version, -excluding the `ea` mark of `early-access` version. If there is any hotfix to stable version, it will be done in this branch, -bumping up the `PATCH` version number (e.g. from `V1.1.-1-` to `V1.1.-2-`). This change is then merged to `early-access` -branch with a bump in `early-access` `PATCH` version number from whatever it is (e.g. from `V1.2.-0-ea` to `V1.2.-1-ea`) -and this will then be merged to `master`. - -To illustrate, look at the diagram below. - - - -Development in master does not stop, even after creating an early access release. Version does not matter as well in master. - -On creating an early access release, merge the `master` branch to `early-access` branch and create a release (instruction below) -with the `PATCH` version of 0, like `V1.0.0ea` and `V1.1.0ea` in the diagram. If the release has a bug, it will be fixed in -`early-access` branch, and the bug fix needs to be merged back `master` branch as shown in `V1.0.1ea`. - -When `early-access` version has a set of new features that is well polished, we will create a stable release by merging -`early-access` branch to `stable` branch and create a release. The version of the release uses the latest `early-access` -version without early access flag (from `V1.0.2ea` to `V1.0.2` and from `V1.1.2ea` to `V1.1.2` in the diagram). - -If the stable release requires a bug fix, the bug fix will be done in `stable` branch. A re-release will be done with -a bump in `PATCH` version, as shown in `V1.0.3` in the diagram. This bug fix will be merged back to `early-access` branch -in which we will re-release the early access version with a bump in early access `PATCH` version, as shown in `V1.1.0ea` -to `V1.1.1ea` in the diagram (and not to `V1.0.3ea`). This bug fix will also be merged to `master` branch from -`early-access` branch. - - -References to how teams have multiple release channel: -- http://blog.atom.io/2015/10/21/introducing-the-atom-beta-channel.html -- https://docs.google.com/presentation/d/1uv_dNkPVlDFG1kaImq7dW-6PasJQU1Yzpj5IKG_2coA/present?slide=id.i0 -- http://blog.rust-lang.org/2014/10/30/Stability.html - -## Creating a Release - -### How to create a release -1. Merge the appropriate branches - - Releasing an early-access version: Merge `master` branch to `early-access` branch. -Releasing a stable version: Merge `early-access` branch to `stable` branch. - - Use `git merge --no-commit --no-ff` (LOCALLY) so that a merge commit won't be made, in which you can make relevant changes (e.g. changing version number and early access flag) before committing with the version of the software as the commit message. -2. Update version numberings - - Update the versions of the application and its dependencies in `MainApp` and in `build.gradle`. - - If the main application is an early access version, set `IS_EARLY_ACCESS` in `MainApp` as `true` and add `ea` at the end of version in `build.gradle`. - - For custom dependencies, manually check the commits to see if its package has been modified since the last release. If it has, modify its version numbering (usually bumping the minor or major version, according to semantic versioning). -3. Compile the custom dependencies - - Run `gradle` task `createInstallerJar` -4. Update version data - - Generate partially-updated `VersionData.json` containing the list of libraries and information - - Run `gradle` task `generateVersionData` - - Information of unchanged libraries will be copied from the old `VersionData.json` - - The console will print a list of libraries which needs to be manually updated for the new version - - Upload all updated libraries - - Upload them to https://github.com/HubTurbo/addressbook/releases/tag/Resources - - Update `VersionData.json` - - Open `VersionData.json` and manually update the new fields accordingly - - Fill in the links to download the new libraries. - - Change the OS compatibility of the new libraries to ensure that only the libraries relevant to an OS will be loaded and checked -5. Create a new commit - - Commit and push the files for release - name the commit `V..` (with suffix `ea` if it's an early access version) - - This is so that the following GitHub release (done in Step 7) will appropriately tag this commit containing the updated `VersionData.json` -6. Create the release JAR by running the Gradle task `createInstallerJar` - - this must be run again to use the updated `VersionData.json` -7. Draft a new release in [GitHub](https://github.com/HubTurbo/addressbook/releases) and tag the corresponding branch (`early-access` or `stable`) - - Use the version number for both the tag and the title. -8. Upload the generated `installer-V*.*.*.jar` found at `build/libs` to the latest release. -9. Publish! - -## More About Release -The main application of `addressbook` is configured to be released as a [non-fat JAR](http://stackoverflow.com/questions/19150811/what-is-a-fat-jar), -that is, libraries that it depends on will not be included inside the `addressbook` JAR itself. Instead, the JARs of these libraries -will be put in `lib` folder which can then be included during runtime by setting the classpath to include the `lib` folder. - -For example: -``` -addressbook/ - |-> launcher.jar - |-> lib/ - |-> apache-commons-io.jar - |-> apache-logging.jar - |-> jxbrowser.jar - |-> resource.jar -``` - -This set-up is used to reduce the size of updates to be downloaded whenever a new version of `addressbook` is released. With -this set-up, only main application JAR and libraries that need to be updated will be downloaded, essentially reducing the -time taken to download updates. - -For convenience, the whole set-up mentioned above is packed into 1 JAR file -which will self-unpack itself on first run. It can be deleted after installation, and the main application can be launched through the launcher instead. - -Several gradle tasks have been prepared to make it effortless to create a release of `addressbook` with the set-up mentioned above. - -### Gradle Tasks for Release - -The following explains the Gradle tasks that are required for a release. - -#### generateVersionData -Generates the version data (VersionData.json) which will be used by user's application instance to know if it has an update -and what to update. It reads the dependencies of the latest version of `addressbook` and put those dependencies into the version data. To make it easier for developers, it will use previous version's values for libraries that did not change. Developers then need to manually update the new dependencies information (e.g. download link, OS they are meant for). - -`generateVersionData` has its own source set which includes everything and its dependencies are extended from main application compile dependencies. This is to make it easier for generateVersionData to read any information it needs to create version data. The main class it uses is `addressbook/util/VersionDataGenerator.java` - -#### createCommonsJar -Creates the commons jar dependency. This jar contains the classes found in the `commons` package, including `FileUtil` and `OsDetector`, and is used as a dependency for most components. - -#### createUpdaterJar -Creates the updater jar dependency. This file contains the components which are required for the migration of the application to a newer version. - -See: [Updater](Updater.md) - -#### createLauncherJar -Creates launcher executable file, to launch the main application with custom arguments. - -See: [Launcher](Launcher.md) - -#### createInstallerJar -Creates the executable packed JAR for the user to download and use. The packed JAR contains the main application and all the libraries needed for the main application to run. - -Note that running this will also run the other mentioned tasks in a specified order. See `build.gradle` for more details (`dependsOn`/`mustRunAfter`). - -On first run, it unpacks the libraries and the main application, then runs the launcher. On subsequent runs, it simply attempts to restore any missing files if the current version is not newer than the installer's (i.e. has not been updated) then simply runs the launcher. However, it is expected that the user will delete this file after installation. - -### Possible Improvements - -#### Automate generateVersionData -Ideally, we don't need to host those libraries JAR on our own in GitHub release. We can grab the JARs from the Maven repositories -that `gradle` uses to get those libraries. Unfortunately, the lack of documentation of `gradle` makes it impossible to -get the URL of those JAR in the Maven repositories, hence the manual need to update the download links and upload the new -libraries to GitHub release. - -#### GUI for generateVersionData -Instead of having to deal with text file of update data which is prone to error, we can have a GUI which generateUpdateData -uses to show what libraries have been changed in the latest version with fields to update the download links. Also, -we can have a dropdown option for the OS which the libraries are needed in so developers don't need to type them manually. - -#### Installer dependencies -Use of ShadowJAR should be considered to enable logging. diff --git a/docs/releases/Updater.md b/docs/releases/Updater.md deleted file mode 100644 index 137ec19d4c91..000000000000 --- a/docs/releases/Updater.md +++ /dev/null @@ -1,10 +0,0 @@ -# Updater -A separate updater jar which contains key classes to perform data migration from one version to another. It is typically named as `updater.jar`. - -## How does the update work -The main application has the updater jar as an internal resource. - -1. After the main application finishes the downloading of updates, it will extract the updater jar in preparation for doing the update migration. -2. At exit of the main application, the updater jar is executed. It will attempt to perform updates for several times, expecting the main application to hog the resources to be replaced for a short while. - - Updater jar reads from the specification file created by the main application to know which files have to be moved - \ No newline at end of file