CrazyChaoz / gradle-dot-nix

This flake can generate the full maven repo required to build a gradle app from gradle/verification-metadata.xml, all in the sandbox, without code generation.
MIT License
4 stars 2 forks source link
gradle nix

sandbox friendly gradle builds in nix

This flake provides a way to build gradle projects in sandboxed nix environments.

No configuration should be needed, just import the flake and use the provided outputs.

Yes there are still IFDs left in the code. If you have any idea how to get rid of them, please let me know or open a PR.

Sample Project

A sample project that uses this flake can be found here.

Usage

(The following descriptions assume you use a pretty default gradle project structure. If you have a more complex setup, you might need to adjust accordingly.)

To start using this flake, you need to generate a gradle/verification-metadata.xml file in your project and check it into your VCS.

This file can be generated by running the following command in your project:

gradle -M sha256 build

This will generate a gradle/verification-metadata.xml file that contains the sha256 hashes of all the dependencies used in the build.

Note: I have not tried it with more custom verification-metadata.xml files, so I cannot guarantee that it will work with those. If you run into any such problem please open an issue.

Gradle init script

There is a gradle-init output that can be used to create a gradle init script. This is a more straightforward way to use the flake, as it does not require any configuration in the actual project.

gradle-init-script = 
    (import gradle-dot-nix {
        inherit pkgs;
        gradle-verification-metadata-file = ./gradle/verification-metadata.xml;
    }).gradle-init;

This init script can be used like this:

gradle -I ${gradle-init-script} build

There should be no need to modify any files in the project to use this. The generated init script will automatically set the maven repository for the project and remove repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) from the settings.

Maven repository

If you want to have a sandbox friedly maven repository, you can use the mvn-repo output.

This is useful if you already use a version of such a maven repo in your project.

maven-repo = 
    (import gradle-dot-nix {
        inherit pkgs;
        gradle-verification-metadata-file = ./gradle/verification-metadata.xml;
    }).mvn-repo;

This maven repo can be used in your build.gradle file like this:

repositories {
    if(project.hasProperty("nixMavenRepo")) {
        maven { url = nixMavenRepo }
    }
}

or in .kts files like this:

repositories {
    val nixMavenRepo: String? by settings
    if (nixMavenRepo != null) {
        maven { url = uri(nixMavenRepo!!) }
    }
}

And then you can build your project with the following command:

gradle -PnixMavenRepo=${maven-repo} build

Custom Public Repositories

If you don't want to use the standard repositories gradle uses, you can set the optional public-maven-repos input to a JSON array that contains the repositories you want to query.


gradle-dot-nix-instance = 
    import gradle-dot-nix {
        inherit pkgs;
        gradle-verification-metadata-file = ./gradle/verification-metadata.xml;
        public-maven-repos = ''        
        [
            "https://dl.google.com/dl/android/maven2",
            "https://repo.maven.apache.org/maven2",
            "https://plugins.gradle.org/m2",
            "https://maven.google.com"
        ]
        '';
    };

Custom Local Repositories

If some your dependencies are already available locally, you can set the optional local-maven-repos input to an array of store paths. This is especially useful for react-native apps, where some maven repos are available through NPM.

gradle-dot-nix-instance = 
    import gradle-dot-nix {
        inherit pkgs;
        gradle-verification-metadata-file = ./gradle/verification-metadata.xml;
        local-maven-repos = [
            "${nodeModules}/node_modules/jsc-android/dist"
        ];
    };

Private Repositories (WIP)

Implementing proper support for private repositories is a bit more complex, as the credentials should not be leaked into the nix store.

The current plan is to use the maven standard settings.xml file to configure the repositories, and to give the content of that via an impure environment variable to the fetcher.

In the meantime you should either:

Implementation Details

The project currently uses python3 to parse the gradle/verification-metadata.xml file and to fetch the dependencies from the maven repository. This is done to simplify the nix expressions and to avoid having to deal with the xml in nix. It also speeds up the development process, as the python scripts are easier to write and debug than nix expressions.

The python scripts are not very complex and should be easy to understand nixify if you want to do that. I don't have any motivation to do that myself, but I would be happy to accept a PR that does that.

A starting point for that would be to convert the python scripts to bash scripts, as they are self-contained and don't do too much magic.

IFDs

There are several IFDs that (need to?) exist in the code.

  1. The gradle/verification-metadata.xml file gets read to determine the further derivations. There shouldn't be a way around this, as the dependencies are variable and the derivations thus need to be determined at runtime.
  2. nixpkgs.symlinkJoin collects multiple store paths into one. Store paths are not known before evaluation and need to be determined at runtime.

Structure

Special Thanks

Acknowledgment

This work has been carried out within the scope of Digidow, the Christian Doppler Laboratory for Private Digital Authentication in the Physical World and has partially been supported by the LIT Secure and Correct Systems Lab. We gratefully acknowledge financial support by the Austrian Federal Ministry of Labour and Economy, the National Foundation for Research, Technology and Development, the Christian Doppler Research Association, 3 Banken IT GmbH, ekey biometric systems GmbH, Kepler Universitätsklinikum GmbH, NXP Semiconductors Austria GmbH & Co KG, Österreichische Staatsdruckerei GmbH, and the State of Upper Austria.

License

This flake is licensed under the MIT license. See the LICENSE file for details.