Skip to content

Commit

Permalink
updated git metadata docs page based on akit docs (wpilibsuite#2366)
Browse files Browse the repository at this point in the history
* added docs page based on akit docs

* elaborated on gradle section, added example generated file

* wording tweaks for clarity

* capitalized Gradle

* grammar and clarification

* reworded explanation of DIRTY

* fixed lint violation

* edits for clarity

---------

Co-authored-by: Lewy Seiden <[email protected]>
  • Loading branch information
Lewis-Seiden and Lewy Seiden authored Jan 5, 2024
1 parent fa67075 commit 57731c9
Showing 1 changed file with 41 additions and 86 deletions.
127 changes: 41 additions & 86 deletions source/docs/software/advanced-gradlerio/deploy-git-data.rst
Original file line number Diff line number Diff line change
@@ -1,113 +1,68 @@
Including Git Data in Deploy
============================

This article will go over how to include information from Git, such as branch name or commit hash, into the robot code. This is necessary for using such information in robot code, such as printing out commit hash and branch name when the robot starts.
This article will explain how to include metadata from Git in robot code using the `gversion <https://github.com/lessthanoptimal/gversion-plugin>`__ Gradle plugin. This generates a file which can be used for accessing Git metadata in robot code. This can be used to track what revision of code is on the robot, such as by printing or logging it.

.. note:: Git must be in the path for this to work. This should be enabled by default when `installing Git <https://git-scm.com/downloads>`__.
Installing gversion
-------------------

Deploying Branch Name
---------------------

This example uses `git rev-parse <https://git-scm.com/docs/git-rev-parse>`__ to extract data the name of the current branch. The Git command used for this is:

.. code-block:: console
$ git rev-parse --abbrev-ref HEAD
The ``--abbrev-ref`` flag tells Git to use a short version of the name for the current commit that ``rev-parse`` is acting on. When HEAD is the most recent commit on a branch, this will return the name of that branch.

Next, create a new task in the ``build.gradle`` file that will run the above Git command and write it to a file in the ``src/main/deploy`` directory. For example, the following is an example task named ``writeBranchName`` that will write the branch name to a file named ``branch.txt``.
To install gversion add the following line to the plugins block of ``build.gradle``. This tells Gradle to use gversion in the project.

.. code-block:: groovy
tasks.register("writeBranchName") {
// Define an output stream to write to instead of terminal
def stdout = new ByteArrayOutputStream()
// Execute the git command
exec {
commandLine "git", "rev-parse", "--abbrev-ref", "HEAD"
// Write to the output stream instead of terminal
standardOutput = stdout
}
plugins {
// ...
id "com.peterabeles.gversion" version "1.10"
}
// Parse the output into a string
def branch = stdout.toString().trim()
// Create a new file
new File(
// Join project directory and deploy directory
projectDir.toString() + "/src/main/deploy",
// File name to write to
"branch.txt"
).text = branch // Set the contents of the file to the variable branch
}
This registers a `Gradle task <https://docs.gradle.org/current/userguide/tutorial_using_tasks.html>`__ that uses the above Git command, saves the output to a variable, and then writes it to a file. Since it was written to the ``src/main/deploy`` directory, it will be included in the jar file deployed to the robot and accessible in code.

The next step is to make the deploy task depend on the task you created, so that it will automatically run before the code is deployed. This example uses the task name ``writeBranchName`` from the previous example, but it should be replaced with the name of the task in your ``build.gradle``.
In order to generate the file when building the project, add the following block to the bottom of ``build.gradle``.

.. code-block:: groovy
deploy.targets.roborio.artifacts.frcStaticFileDeploy.dependsOn(writeBranchName)
Deploying Commit Hash
---------------------
project.compileJava.dependsOn(createVersionFile)
gversion {
srcDir = "src/main/java/"
classPackage = "frc.robot"
className = "BuildConstants"
dateFormat = "yyyy-MM-dd HH:mm:ss z"
timeZone = "America/New_York" // Use preferred time zone
indent = " "
}
Similar to the previous example, ``git rev-parse`` will be used to parse the current commit hash. The Git command used for this is:
The ``srcDir``, ``classPackage``, and ``className`` parameters tell the plugin where to put the manifest file, and what to name it. The ``timeZone`` field can be set to your team's time zone based on `this list of timezone IDs <https://docs.oracle.com/middleware/12211/wcs/tag-ref/MISC/TimeZones.html>`__. The ``dateFormat`` parameter is based on `this Java class <https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html>`__.

.. code-block:: console
To test this, run a build of your project through the WPILib menu in the top right. Once the code has finished building, there should be a file called ``BuildConstants.java`` in your ``src/main/java`` folder. The following is an example of what this file should look like:

$ git rev-parse --short HEAD
.. code-block:: Java
Similar to the previous Git command, ``rev-parse`` is used to find information about the commit at HEAD. However, instead of using ``--abbrev-ref`` to find the branch name associated with that commit, ``--short`` is used to find the 7-character commit hash.
package frc.robot;
.. note:: If you wish to use the full commit hash instead of the 7-character version, you can leave out the ``--short`` flag.
/**
* Automatically generated file containing build version information.
*/
public final class BuildConstants {
public static final String MAVEN_GROUP = "";
public static final String MAVEN_NAME = "GitVersionTest";
public static final String VERSION = "unspecified";
public static final int GIT_REVISION = 1;
public static final String GIT_SHA = "fad108a4b1c1dcdfc8859c6295ea64e06d43f557";
public static final String GIT_DATE = "2023-10-26 17:38:59 EDT";
public static final String GIT_BRANCH = "main";
public static final String BUILD_DATE = "2023-10-27 12:29:57 EDT";
public static final long BUILD_UNIX_TIME = 1698424197122L;
public static final int DIRTY = 0;
Next is to create a task in ``build.gradle`` that runs this command and writes the output to a file. This is largely the same as the first example, except the task is named ``writeCommitHash``, the new Git command is used, and it is written to ``commit.txt`` instead of ``branch.txt``.

.. code-block:: groovy
private BuildConstants(){}
}
tasks.register("writeCommitHash") {
def stdout = new ByteArrayOutputStream()
exec {
commandLine "git", "rev-parse", "--short", "HEAD"
standardOutput = stdout
}
def commitHash = stdout.toString().trim()
new File(
projectDir.toString() + "/src/main/deploy",
"commit.txt"
).text = commitHash
}
deploy.targets.roborio.artifacts.frcStaticFileDeploy.dependsOn(writeCommitHash)
``DIRTY`` indicates whether there are uncommitted changes in the project. A value of 0 indicates a clean repository, a value of 1 indicates that there are uncommitted changes, and a value -1 indicates an error.

Ignoring Generated Files with Git
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Since these files include data that is already tracked by Git and are regenerated every time code is deployed, it is recommended to not track these changes with Git by using the `gitignore <https://git-scm.com/docs/gitignore>`__ file. This file should exist by default in any project generated by the WPILib VS Code extension. Below is an example that continues to use the ``branch.txt`` and ``commit.txt`` file names:
These files are regenerated every time code is built or deployed, so it isn't necessary to track them with Git. The aptly named `.gitignore <https://git-scm.com/docs/gitignore>`__ file tells Git not to track any listed files and should exist by default in any project generated by the WPILib VS Code extension. Below is the line you should add to ``.gitignore`` to ignore the generated file:

.. code-block::
src/main/deploy/branch.txt
src/main/deploy/commit.txt
...
Using Deployed Files
--------------------

In order to access files that were written to the deploy directory in code, you have to use the ``getDeployDirectory()`` method of the `Filesystem <https://github.wpilib.org/allwpilib/docs/beta/java/edu/wpi/first/wpilibj/Filesystem.html>`__ class in Java, or the ``GetDeployDirectory()`` function of the `frc::filesystem <https://github.wpilib.org/allwpilib/docs/beta/cpp/namespacefrc_1_1filesystem.html>`__ namespace in C++. Below is an example of opening both files from the previous examples:

.. note:: Opening and reading the files is slow and should not be performed during any periodic methods. Since the file will only change on deploy, it only needs to be read once.

.. code-block:: java
File deployDir = Filesystem.getDeployDirectory();
File branchFile = new File(deployDir, "branch.txt");
File commitFile = new File(deployDir, "commit.txt");
For more information on how to interact with the file objects, see the documentation of the `File <https://docs.oracle.com/javase/7/docs/api/java/io/File.html>`__ class.
src/main/java/frc/robot/BuildConstants.java

0 comments on commit 57731c9

Please sign in to comment.