**********************
Building and Releasing
**********************
This guide explains the build system of OpenRocket (Gradle), and how to release a new version of OpenRocket.
.. contents:: Table of Contents
:depth: 2
:local:
----
Gradle
======
`Gradle `__ is the build system for OpenRocket. It is used to compile the source code, run tests, and create the JAR file.
Key features of Gradle are:
- **Incremental builds**: Gradle only rebuilds what is necessary, which makes the build process faster.
- **Dependency management**: Gradle has a robust dependency management system capable of handling project and third-party libraries.
- **Performance**: Gradle uses techniques like build caching and parallel execution to improve performance of the build process.
The root directory of the OpenRocket repository contains several Gradle files:
- ``build.gradle``: This is the main build script file where you define your project configuration and tasks such as compile and run tasks, dependency management, plugins usage, and more.
- ``settings.gradle``: Used for multi-project build configurations to include which sub-projects should be part of the build.
For OpenRocket, this file is used to identify the ``core`` and ``swing`` sub-projects.
- ``gradle.properties``: Contains project-wide properties that can be accessed from the build script. For example, the version number of OpenRocket can be defined here.
- ``gradlew`` and ``gradlew.bat``: These are Gradle Wrapper scripts for Unix-based and Windows systems respectively.
It allows users to run Gradle builds without requiring Gradle to be installed on the system.
The ``core`` and ``swing`` sub-projects contain their own ``build.gradle`` and ``gradle.properties`` files that define the tasks specific to those sub-projects.
Gradle in IntelliJ
------------------
If you use IntelliJ IDEA, you can access the Gradle tasks within the IDE. First, open the Gradle tool window by going to
:menuselection:`View --> Tool Windows --> Gradle` or by clicking on the Gradle icon in the right-hand side of the window:
.. figure:: /img/dev_guide/building_releasing/gradle_in_intellij.png
:align: center
:width: 80%
:alt: Opening the Gradle tool window in IntelliJ IDEA.
Opening the Gradle tool window in IntelliJ IDEA.
This shows the following window:
.. figure:: /img/dev_guide/building_releasing/intellij_gradle_window.png
:align: center
:width: 30%
:alt: The Gradle tool window in IntelliJ IDEA.
The Gradle tool window in IntelliJ IDEA.
Here's a breakdown of the Gradle tasks:
- *info.openrocket*: the root project
- *Tasks*: Gradle tasks specific to the root project.
- *application*: Contains tasks related to running or debugging your application from within the IDE.
- *build*: Includes tasks for building the entire project.
- *build setup*: Tasks for initializing a new Gradle build, such as creating new Gradle files.
- *distribution*: Tasks for assembling the application distribution, like creating zips or tarballs of the build outputs.
- *documentation*: Tasks for generating documentation, typically using tools like Javadoc.
- *help*: Provides tasks that list other tasks or project properties.
- *info.openrocket*: Custom tasks specific to the 'info.openrocket' module.
- *other*: Any other tasks that do not fit into the predefined categories.
- *shadow*: Related to the Shadow plugin, which packages the project’s artifacts along with its dependencies into a single "fat" JAR.
- *verification*: Tasks for testing and verifying the project, such as running unit tests.
- *Dependencies*: Lists the dependencies of the project.
- *Run Configurations*: Gradle run configurations that can be used in IntelliJ.
- *core*: the core module
- *Tasks*: Gradle tasks specific to the 'core' module.
- *Dependencies*: Lists the dependencies of the 'core' module.
- *swing*: the swing module
- *Tasks*: Gradle tasks specific to the 'swing' module.
- *Dependencies*: Lists the dependencies of the 'swing' module.
Most Important Gradle Tasks
---------------------------
Here are some of the most important Gradle tasks for OpenRocket:
.. list-table:: Most Important Gradle Tasks
:widths: 25 25 50
:header-rows: 1
* - Module
- Task
- Description
* - root (*info.openrocket*)
- ``clean``
- Deletes the build directory and all its contents (basically cleans up the project).
* - root (*info.openrocket*)
- ``run``
- Runs the OpenRocket application.
* - root (*info.openrocket*)
- ``check``
- Runs the unit tests and checks the code quality using the Checkstyle static analysis tool.
* - root (*info.openrocket*)
- ``build``
- Compiles the source code, runs the unit tests, and creates the JAR file for the *core* and *swing* module.
* - root (*info.openrocket*)
- ``dist``
- Creates a distributable JAR file of OpenRocket (a combination of the *core* and *swing* JAR) at :file:`openrocket/build/libs/OpenRocket-.jar`.
* - core
- ``serializeEngines``
- Fetch the latest thrust curves from ThrustCurve.org and serialize them to the OpenRocket format. The resulting serialized file is saved in the ``src`` dir so it can be used for a build.
* - core
- ``serializeEnginesDist``
- Same as ``serializeEngines``, but loads the serialized file to the distribution directory (:file:`openrocket/build`) so it can be used in the final build.
* - core
- ``submoduleUpdate``
- Updates the submodule dependencies of the *core* module.
You can run these tasks from the command line using the Gradle Wrapper scripts. For example for the task ``run``, run the
following command in the root directory of the OpenRocket repository:
.. code-block:: bash
# On macOS and Linux:
./gradlew run
# On Windows:
gradlew.bat run
install4j
=========
`install4j `__ is used to create the packaged installers for OpenRocket from the JAR file.
install4j generously provides a free license for open source projects, including OpenRocket. Currently, only the OpenRocket administrators have access
to the install4j license.
Code Signing
------------
An important part of generating the installers is `code signing `__.
This is done to ensure that the installer is not tampered with between the time it is created and the time it is run by the user.
Once the OpenRocket installer has been code signed, users will receive no more (or the minimum amount of) warnings from
their operating system that the installer is from an unknown source and may contain malware.
More information on how to do code signing in install4j can be found `here `__.
Only the OpenRocket administrators have access to the code signing certificates.
Code signing for Windows is done using a digital certificate from Sectigo. More information on the code signing procedure,
including whitelisting OpenRocket by Microsoft, see the `README file on GitHub `__.
For macOS, the code signing is done using an Apple Developer ID. Besides code signing, the OpenRocket app also needs to
be notarized. Luckily, install4j takes care of this. More information on the code signing procedure for macOS can be found in the
`README file on GitHub `__.
Linux does not require code signing.
Creating the Installers
-----------------------
First you need to build the project using Gradle (see above). This will create the JAR file that will be used to create the installers.
Then, open install4j (requires a license) and load the project file *openrocket/install4j//openrocket-.install4j*
from the repository. Go to the :menuselection:`Build` tab and click on the :guilabel:`Start Build` button. This will create the installers in
the *openrocket/install4j//media/* directory.
.. figure:: /img/dev_guide/building_releasing/install4j_build.png
:align: center
:width: 80%
:alt: Building the installers in install4j.
Building the installers in install4j.
If you do not have access to the code signing certificates, you can create the installers without code signing by
enabling the checkboxes ``Disable code signing`` and ``Disable notarization`` in the ``Build`` tab.
Release Procedure
=================
The release procedure for OpenRocket is as follows:
1. Update the `ReleaseNotes.md `__ with the changes that are part of the new release.
This includes new features, bug fixes, and other changes that are part of the release. Make sure to include the version number and the release date.
Take a look at the previous release notes to see how it should be formatted.
2. Update the component database and thrustcurves by running the gradle tasks ``subModuleUpdate`` and ``serializeEnginesDist`` respectively.
3. **Update the version number** in ``openrocket/core/src/main/resources/build.properties`` to the correct version number.
For official releases, the version number should use the format ``YY.MM`` (*year.month*). For example, if the software is released in
September 2023, the version number should be ``23.09``. If there are multiple releases in the same month, add an incremental number
to the version number, e.g. ``23.09.01``.
If a new release contains significant changes, it may be necessary to release alpha or beta versions first. In that case, the version
number should be appended with ``.alpha.`` or ``.beta.`` plus an incremental number. For example, if the software is in beta stage
in September 2023, the version number should be ``23.09.beta.01``. In general, alpha releases are not necessary. This is only for very rough releases.
Beta releases are only necessary if there are significant changes that need to be tested by the community before the final release.
One final option is to release a release candidate (RC) version. This is a version that is considered to be the final version,
but needs to be tested by the community before the final release. The version number should be appended with ``.RC.`` plus an incremental number.
For example, if the software is in RC stage in September 2023, the version number should be ``23.09.RC.01``.
The official release that comes after the beta release should have the same version number as the beta release, but without the ``.beta.`` part.
For instance, if the beta testing started in September 2023 with version number ``23.09.beta.01``, the final release should have version number ``23.09``,
even if the final release is in November 2023. This is to ensure consistency in the version numbering and to link the beta release(s) to the final release.
4. **Build the project JAR file** using Gradle (see above).
5. **Test the JAR file** to ensure that it works correctly and that the new version number is applied to the splash screen and under :menuselection:`Help --> About`.
6. **Create the packaged installers** using install4j (see above).
.. warning::
Make sure to **enable code signing** for the installers.
Make sure that `DS_Store `__ for the macOS
installer is updated. Instructions can be found `here `__.
7. **Test the installers** to ensure that they work correctly.
8. **Prepare the website** *(for official releases only, not for alpha, beta, or release candidate releases)*.
The `source code for the website `__ needs to be updated to point to the new release.
Follow these steps:
- Add the release to `downloads_config.json `__.
- Update the ``current_version`` in `_config `__.
- Add a new entry to `_whats_new `__ for the new release.
Create a ``wn-.md`` file with the changes that are part of the new release. Please take a close look to the previous entries to see how it should be formatted.
- Update the `release notes `__
(which is a link to the What's new file that you just created). Again, take a close look at the previous entries to see how it should be formatted.
.. warning::
Make sure to **update the website on the** ``development`` **branch**. The ``master`` branch is the branch that is live
on the website. First update the ``development`` branch and test the changes on the website. In a later step, the
changes will be merged to the ``master`` branch.
9. **Publish the release on GitHub**.
Go to the `releases page `__. Click *Draft a new release*.
Select *Choose a tag* and enter a new tag name, following the format ``release-``, e.g. ``release-23.09``.
The title should follow the format ``OpenRocket ()``, e.g. ``OpenRocket 23.09 (2023-11-16)``.
Fill in the release text, following the `ReleaseNotes.md `__.
If you want to credit the developers who contributed to the release, you can tag them anywhere in the release text using the `@username` syntax.
They will then be automatically displayed in the contributors list on the release page.
Finally, upload all the packaged installers and the JAR file to the release. The source code (zip and tar.gz) is
automatically appended to each release, you do not need to upload it manually.
If this is an alpha, beta, or release candidate release, tick the *Set as a pre-release* checkbox.
Click *Publish release*.
10. **Push the changes to the website**
First, build the ``development`` branch locally to verify that the changes that you made in step 8 are correct.
If everything is working (test the download links, the release notes, and the What's new page), create a new PR
that merges the changes from the ``development`` branch to the ``master`` branch.
11. **Send out the release announcement**.
Send out the release announcement to the OpenRocket mailing list, the TRF forum, and the OpenRocket social media channels
(Discord, Facebook...).
The announcement should include the new features, bug fixes, and other changes that are part of the new release.
Make sure to include the download links to the new release. Here is an `example announcement `__.
12. **Merge the** ``unstable``` **branch to the** ``master``` **branch**.
After the release is published, merge the changes from the `unstable `__ branch
to the `master `__ branch.
13. **Upload the new release to** `SourceForge `__.
The downloads page on SourceForge is still very actively used, so be sure to upload the new release there as well.
14. **Update package managers** (e.g. snap, Chocolatey, Homebrew) with the new release.