Pyrsia demo: build Maven images from source
Warning: This tutorial is aimed at developers actively contributing to the Pyrsia codebase. If you simply want to use Pyrsia, please have a look at Configure Maven to use Pyrsia
This tutorial describes how to setup a Pyrsia node that can build Maven artifacts from source with the goal to publish them in the Pyrsia network.
Ultimately, the following scenario will be used, but for now some steps (indicated below) are skipped for the purpose of this build-from-source demo:
- Setup at least 3 authorized nodes (Skipped in this demo, only one Pyrsia node is used)
- Make sure a mapping between an artifact and its source exists in the Pyrsia Mappings Repo (for Maven artifacts only)
- Set up a build pipeline per Pyrsia node and configure the nodes to use them
- Trigger a build from source for a given artifact
- Wait for the build to finish in the build pipeline
- Try to reach consensus with the other authorized nodes, which have to run the same build and verify they produce the same build result. (Skipped in this demo)
- Create a transparency log about the artifact publication
- Publish the artifact on the p2p network
See the architecture and use-cases document for more information.
Because this demo scenario results in a published Maven artifact in the Pyrsia network, we can run a final step to show the build from source worked:
- Use Pyrsia in a Maven project
Prerequisites
The following steps rely on JDK11 and maven being correctly installed. Please find and install the appropriate JDK11 and mvn before proceeding.
Compile Pyrsia
If you build for the first time or face any issues at this step, see the Development Environment document.
Download a fresh copy of the codebase by cloning the repo or updating to the
HEAD of main
.
git clone https://github.com/pyrsia/pyrsia.git
Let's call this folder PYRSIA_HOME
. We will refer to this
name in the following steps.
Build binaries by running:
cd $PYRSIA_HOME
cargo build --workspace
Run the Pyrsia node
Now we will set the following env vars and start a pyrsia node:
- RUST_LOG: to make sure we can see all the debug logs
- DEV_MODE: to make sure all non-existing directories are created on-the-fly
- PYRSIA_ARTIFACT_PATH: pointing to a directory to store artifacts. optionally remove this directory prior to starting Pyrsia if you want to start from an empty state.
RUST_LOG=pyrsia=debug DEV_MODE=on PYRSIA_ARTIFACT_PATH=/tmp/pyrsia \
cargo run --package pyrsia_node -- --pipeline-service-endpoint http://localhost:8080 --listen-only --init-blockchain
As you can see, we specified the --pipeline-service-endpoint
argument to point
to http://localhost:8080
, which is where we will run our build pipeline prototype
(see below). In a production setup, the build pipeline needs to run on its
own isolated infrastructure.
Create a mapping between the artifact and its source repository
In this demo, we will build a Maven artifact from source. Since there's no direct
connection between the Maven artifact defined as groupId:artifactId:version
and
its source repository, Pyrsia keeps a public mapping repository. For every known
artifact, this repository has a mapping file like this:
{
"package_type": "Maven2",
"package_specific_id": "groupId:artifactId:version",
"source_repository": {
"Git": {
"url": "https://github.com/organization/artifact",
"tag": "rel/artifact-version-tag"
}
},
"build_spec_url": ""
}
In case you want to build an artifact from source for which a mapping is not yet available, feel free to create a pull request to add it to the mapping repository.
In this demo we will build commons-codec:commons-codec:1.15
for which the mapping
is already available.
Run build pipeline prototype
In this demo, we use a build pipeline prototype. Eventually, Pyrsia will use industry-standard build pipeline solutions. Integration with such solutions is currently being investigated.
The most important features of the build pipeline are:
- it runs completely separate from the Pyrsia node
- it exposes an interface so Pyrsia can start a build
- it exposes an interface so Pyrsia can download the build output
The current build pipeline prototype only supports Maven builds. It takes the artifact mapping as input (see above), starts a Maven build and provides the build output as a download.
Ensure that JAVA_HOME is setup correctly
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_jdk/Contents/Home
and maven is available on the PATH
export PATH=path to your maven download location/apache-maven-3.8.6/bin:$PATH
Download or clone the prototype repo and run as follows:
cd pyrsia_build_pipeline_prototype
RUST_LOG=debug cargo run
By default, this prototype listens on http port 8080. If you run it on a different
host or port, make sure to specify its location when starting the Pyrsia node
with --pipeline-service-endpoint
(see above).
Because we will be using this prototype for building Maven artifacts, make sure
you have installed a JDK11 and configured JAVA_HOME before running cargo run
.
You will see the following output indicating that the build pipeline is ready for use
Finished dev [unoptimized + debuginfo] target(s) in 1m 07s
Running `target/debug/pyrsia_build`
INFO actix_server::builder > Starting 8 workers
INFO actix_server::server > Tokio runtime found; starting in existing Tokio runtime
Authorize the Pyrsia node as a build node
We will use the Pyrsia CLI to authorize node A as a build node. In a new terminal, while the Pyrsia node and build pipeline prototype are running, check if your Pyrsia CLI config is correct:
cd $PYRSIA_HOME/target/debug
./pyrsia config --show
Config file path: /some/path/default-config.toml
host = 'localhost'
port = '7888'
disk_allocated = '10 GB'
If you're not using the default port for your Pyrsia node, make sure to configure
the CLI using ./pyrsia config edit
.
Next you'll need to find out the peer id of the node. You can see that in its logs
or you can query the /status
endpoint like this: (assuming you have jq
installed)
curl -s http://localhost:7888/status | jq .peer_id
Once you know the peer id, authorize it like this:
./pyrsia authorize --peer <PEER_ID>
Trigger a build from source for a given artifact
In this demo we trigger a build for commons-codec:commons-codec:1.15
.
The mapping repository already contains the source repository mapping.
Then trigger the build from source, like this:
./pyrsia build maven --gav commons-codec:commons-codec:1.15
The build trigger should return immediately providing a build ID:
Build request successfully handled. Build with ID '13abff76-5aea-4d05-8f42-d625943ceb78' has been started.
Wait for the build to finish in the build pipeline
In the Pyrsia node logs, you will see that a build has been started and the Pyrsia node is now waiting for its result:
DEBUG pyrsia::build_service::service > Updated build info: BuildInfo { id: "13abff76-5aea-4d05-8f42-d625943ceb78", status: Running }
In the build pipeline prototype you should see that the build has started:
Requesting build of Maven2 for commons-codec:commons-codec:1.15
Starting build with ID 13abff76-5aea-4d05-8f42-d625943ceb78
#######################################################
#
# Starting Maven2 build for:
# commons-codec:commons-codec:1.15
#
#######################################################
Cloning into 'repo'...
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 19.787 s
[INFO] Finished at: 2022-07-15T15:59:42+02:00
[INFO] ------------------------------------------------------------------------
...
Once the build has finished, the status request from the Pyrsia node will contain:
DEBUG pyrsia::build_service::service > Updated build info: BuildInfo { id: "13abff76-5aea-4d05-8f42-d625943ceb78", status: Success { artifact_urls: ["/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15.pom.md5", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15-sources.jar.sha1", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15.pom", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15.jar", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15-tests.jar.sha1", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15.jar.sha1", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15-tests.jar.md5", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15-tests.jar", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15-test-sources.jar.sha1", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15-test-sources.jar", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15.jar.md5", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15.pom.sha1", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15-sources.jar", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15-sources.jar.md5", "/build/13abff76-5aea-4d05-8f42-d625943ceb78/artifacts/commons-codec-1.15-test-sources.jar.md5"] } }
And Pyrsia will download all build result files from the pipeline service.
Try to reach consensus with the other authorized nodes
In a regular scenario, the Pyrsia node will now try to reach consensus with the other authorized nodes, but this step is skipped in this demo.
Create a transparency log about the artifact publication
When consensus has been reached, a transparency log is created for each built artifact.
INFO pyrsia::artifact_service::service > Adding artifact to transparency log: AddArtifactRequest { package_type: Maven2, package_specific_id: "commons-codec:commons-codec:1.15", num_artifacts: 15, package_specific_artifact_id: "commons-codec/commons-codec/1.15/commons-codec-1.15.pom.md5", artifact_hash: "ff89aba3ea6e2655feba41fdff2d8388b09f421ca6ca0ff5c49dbc24e53ae86a" }
INFO pyrsia::artifact_service::service > Transparency Log for build with ID 13abff76-5aea-4d05-8f42-d625943ceb78 successfully created.
DEBUG pyrsia::transparency_log::log > Transparency log inserted into database with id: 95bd06e4-8254-437f-bc28-432883379426
Publish the artifact on the p2p network
As a final step in the build from source scenario, the artifacts are stored locally and provided on the p2p network.
INFO pyrsia::artifact_service::service > put_artifact with id: e7eb2455-51b8-4d93-b8b7-1cde8004f1e2
INFO pyrsia::artifact_service::storage > An artifact is being pushed to the artifact manager e7eb2455-51b8-4d93-b8b7-1cde8004f1e2
DEBUG pyrsia::network::client > p2p::Client::provide "e7eb2455-51b8-4d93-b8b7-1cde8004f1e2"
Now we are ready to use the published artifacts in our build workflow as shown in the sample section below.
Use Pyrsia in a Maven project
Now that we have a published Maven artifact in the Pyrsia network, we can try to use it in a Maven project.
Create a Java project:
mkdir pyrsia-maven-sample
cd pyrsia-maven-sample
mkdir -p src/main/java/org/pyrsia/sample
Create a file src/main/java/org/pyrsia/sample/Main.java
:
package org.pyrsia.sample;
import java.util.Arrays;
import org.apache.commons.codec.binary.Hex;
public class Main {
public static void main(String[] args) {
byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8 };
String hexEncodedData = Hex.encodeHexString(data);
System.out.println("Byte array " + Arrays.toString(data) + " encoded as a hex string: " + hexEncodedData);
}
}
The code in this sample uses org.apache.commons.codec.binary.Hex
from the commons-codec
library, so let's add this as dependency in our Maven build:
Create a pom.xml
file:
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.pyrsia.sample</groupId>
<artifactId>maven</artifactId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>
<name>Pyrsia Sample for Maven</name>
<repositories>
<repository>
<id>pyrsia</id>
<url>http://localhost:7888/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
As you can see, we have set the repository to http://localhost:7888/maven2
, which
will trigger the Maven build to request dependencies from this URL, which is our
Pyrsia node, acting as a Maven repository.
To make sure your local maven cache doesn't already contain this dependency, remove it first:
rm -rf ~/.m2/repository/commons-codec/commons-codec/1.15
And then run the maven build:
mvn clean package
It should show output like this:
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< org.pyrsia.sample:maven >-----------------------
[INFO] Building Pyrsia Sample for Maven 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from pyrsia: http://localhost:7888/maven2/commons-codec/commons-codec/1.15/commons-codec-1.15.pom
Downloaded from pyrsia: http://localhost:7888/maven2/commons-codec/commons-codec/1.15/commons-codec-1.15.pom (15 kB at 343 kB/s)
Downloading from pyrsia: http://localhost:7888/maven2/commons-codec/commons-codec/1.15/commons-codec-1.15.jar
Downloaded from pyrsia: http://localhost:7888/maven2/commons-codec/commons-codec/1.15/commons-codec-1.15.jar (354 kB at 9.3 MB/s)
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.925 s
[INFO] Finished at: 2022-07-15T16:33:39+02:00
[INFO] ------------------------------------------------------------------------
The dependency was downloaded from Pyrsia, which you can verify in the Pyrsia node logs:
DEBUG pyrsia::java::maven2::routes > route full path: /maven2/commons-codec/commons-codec/1.15/commons-codec-1.15.jar
DEBUG pyrsia::java::maven2::handlers::maven_artifacts > Requesting maven artifact: /maven2/commons-codec/commons-codec/1.15/commons-codec-1.15.jar
DEBUG pyrsia::java::maven2::handlers::maven_artifacts > Requesting artifact with package specific id: commons-codec:commons-codec:1.15, and package specific artifact id: commons-codec/commons-codec/1.15/commons-codec-1.15.jar. If not found a build will be requested
INFO pyrsia::artifact_service::storage > An artifact is being pulled from the artifact manager 73cee038-59dc-46f1-a325-fef83e4ff51c
INFO pyrsia_registry > 127.0.0.1:55180 "GET /maven2/commons-codec/commons-codec/1.15/commons-codec-1.15.jar HTTP/1.1" 200 "-" "Apache-Maven/3.6.3 (Java 11.0.8; Linux 5.15.0-56-generic)" 24.345381ms
Inspect the transparency logs
The transparency logs that were created as part of the build from source process, can be inspected using the Pyrsia CLI.
/pyrsia inspect-log maven --gav commons-codec:commons-codec:1.15
This results in the transparency logs for all the Pyrsia artifacts that make up the Maven library:
[
{
"artifact_hash": "ff89aba3ea6e2655feba41fdff2d8388b09f421ca6ca0ff5c49dbc24e53ae86a",
"artifact_id": "e7eb2455-51b8-4d93-b8b7-1cde8004f1e2",
"id": "95bd06e4-8254-437f-bc28-432883379426",
"node_id": "6d2faed8-88fe-4aac-8414-ea0055cb828d",
"node_public_key": "076a5a92-9052-43ff-a665-2e9b6a88df73",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15.pom.md5",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "5e58cae7-b06c-4d21-a475-fb8b188e1a3f",
"timestamp": 1671004615
},
{
"artifact_hash": "944a6c7643cc0ef821d38afdb576c3a3ea2d2308c053eb8e0bcbbc624766e345",
"artifact_id": "0f02db39-a3ae-4039-84ce-68b1726156ce",
"id": "7bf97f16-e8a6-4c56-8c4c-4d7e6adf7cfd",
"node_id": "3bf52a5a-1230-4b1d-b32f-b660d2d7a5cd",
"node_public_key": "ddd83497-e571-4282-8be2-5307df1a636d",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15-sources.jar.sha1",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "95a0ca89-dcfa-4306-9314-92e2411c5fce",
"timestamp": 1671004615
},
{
"artifact_hash": "c86ee198a35a3715487860f419cbf642e7e4d9e8714777947dbe6a4e3a20ab58",
"artifact_id": "311a547b-bce2-429a-8def-783f4e2fbc61",
"id": "2fcbefd2-c40f-4a06-8b5d-2061e7e4b6b5",
"node_id": "4899356d-f1d5-4041-a7dd-2e26dce42fd4",
"node_public_key": "5faeb8d0-0e58-4fed-a0a8-49b62ec75095",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15.pom",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "94617920-9637-4722-83e6-7850ef4e9153",
"timestamp": 1671004615
},
{
"artifact_hash": "9eb1496028b5de8910b14febc3f6a10722eb61aee79c0f2bfda3678d64381541",
"artifact_id": "73cee038-59dc-46f1-a325-fef83e4ff51c",
"id": "595a61d8-bcce-4e67-9d0e-47760838697e",
"node_id": "a61060dc-998e-4e4b-b881-34b8268525b4",
"node_public_key": "86e858cd-33ec-44b3-9465-0a330db1b901",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15.jar",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "344c7854-f0bd-47f4-9972-d490d42054f9",
"timestamp": 1671004615
},
{
"artifact_hash": "db4e82248ee9c594e63e4ad5bef30eb7063ed3c0bd498ed3af71294b0ebf7a3e",
"artifact_id": "93576736-e64f-4da2-8cee-b88034e54c4c",
"id": "7e1953a3-c2c6-4efd-b48e-56ef387b9b33",
"node_id": "6f2f1613-89b3-48c5-ba5d-39cd1cb55004",
"node_public_key": "9553c499-db8e-48c1-8370-171e106a3329",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15-tests.jar.sha1",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "e982f1a7-5d7b-4860-aab3-adaf33ce1bfb",
"timestamp": 1671004616
},
{
"artifact_hash": "9bcaba0174b9803b04312a577917b20a9152582f1c8bf3b4ca9876f5a1569164",
"artifact_id": "df34d9de-9757-4c6d-b7a6-730c1cb0e18e",
"id": "b6b0ebfb-8fed-4229-906f-7e9528601880",
"node_id": "faf9ae75-a6e4-49bc-bb4e-a3e82e1f00b4",
"node_public_key": "bae676c7-95b0-4c16-8520-b53fcfda1cdc",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15.jar.sha1",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "cb5d0c3b-4475-4b76-b039-64bceb3af222",
"timestamp": 1671004616
},
{
"artifact_hash": "2758a7c8666bc7a91cb74a042b24f8e7f0c912e4a5461dbaf5fa35b227332c65",
"artifact_id": "236c5cb0-ddf4-4f16-89bf-bc5ec1052abd",
"id": "a36faabf-d51a-40d0-b4e8-addf56cfe2f7",
"node_id": "2276b670-fed6-46b1-b8f0-fb03ed775ab6",
"node_public_key": "638f0276-ea41-4257-8dda-089ae867a5de",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15-tests.jar.md5",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "5feaa8d2-f868-4ae4-8f53-44da49a1f85e",
"timestamp": 1671004616
},
{
"artifact_hash": "4d1cf8fc05b8952412bcb436579bc335987364900e1f44194dbb98930c23eee8",
"artifact_id": "cc5a5cce-f292-4865-9dba-c96986b042d2",
"id": "5dcb88dc-0162-4a86-b3a3-80d6288290c9",
"node_id": "dfcaf577-dab4-4ada-a3b8-e4948898308a",
"node_public_key": "d2a68745-908a-4210-aea9-73138084e228",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15-tests.jar",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "b02667a1-9938-441b-9c48-1bf70219f999",
"timestamp": 1671004616
},
{
"artifact_hash": "a9be7ceaf4962f4c897239972a1dac711ca7570c2cf47a8b09b7b343950caf41",
"artifact_id": "521faabe-7205-4ef6-8cdc-f4fafb0c58d0",
"id": "1a200591-cf3c-497f-9f87-5fba40ab61a6",
"node_id": "8b6a0dfb-94ba-4122-b06b-a9daefc08c00",
"node_public_key": "aa0a16d2-6957-4107-8bd4-1936d2679e12",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15-test-sources.jar.sha1",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "3838c987-75a4-49d8-8883-4936ca6c6be0",
"timestamp": 1671004616
},
{
"artifact_hash": "997a5e8ed8c37e0c3dcdf20e76db11279c055a20c3875731390c7b8008912c4f",
"artifact_id": "7c3d7314-e455-4715-b760-a30f8496c1dc",
"id": "d371a08f-de02-4fe0-8aea-a3bd78d30504",
"node_id": "29d9a1aa-60e6-4013-aacb-51f8f9baab1e",
"node_public_key": "b4c5b976-3894-4fcc-bdf2-d98943bab7c3",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15-test-sources.jar",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "802473db-3d7b-47af-b716-dba0fd83b6cd",
"timestamp": 1671004617
},
{
"artifact_hash": "30b6bfae61e5fdf2832f1378c64bc90cc24e970b7df48e97610afcdf5dc048c7",
"artifact_id": "4057f20b-5d0b-4912-ada3-8a8fe596b175",
"id": "6ad5899b-ea66-4d1d-85fc-b7d7dd373369",
"node_id": "48e97e91-227e-42dd-9fe9-f49aeb7aebce",
"node_public_key": "ac8bd86b-6325-4305-b08d-a413574d50f4",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15.jar.md5",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "51eb79b0-29bc-4fd6-9e83-49038e355e80",
"timestamp": 1671004617
},
{
"artifact_hash": "5dc11ea7cfa14ac8e84250b21166b098f1ce57ba3316ba5cae589269b37ce54a",
"artifact_id": "2dfdfe5f-3f2b-47a2-bcff-655a27dfca57",
"id": "aa06913a-b1eb-4ab7-8e0a-91659e1ff990",
"node_id": "98f3dc15-b999-4cda-be96-e861daa6ceb7",
"node_public_key": "0bf9a398-662e-4cfd-9e34-d88256f275ed",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15.pom.sha1",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "be90b0ed-885f-40f0-b409-0de0fb4863ec",
"timestamp": 1671004617
},
{
"artifact_hash": "930b528fc1cc6ad19b719c8f79fbf494814b3572f4df9f2555186ce2527a3116",
"artifact_id": "ec0cd5d0-697e-48f3-bc8a-ef9ef9731ed9",
"id": "7c12bd6f-5784-45eb-ac10-ed9f80c1f130",
"node_id": "e0571aa3-d5d0-4d77-985e-00cf835ca496",
"node_public_key": "51c179cc-9686-4cb4-aeb2-f2cdf93c20ea",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15-sources.jar",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "a99fc485-a576-4f77-b513-aa1c5ba38647",
"timestamp": 1671004617
},
{
"artifact_hash": "53290bdbc449ae0e0230ab9f4d1d49043a3b67d0c40f49f1b6323188da2f0200",
"artifact_id": "a76ea024-dfae-443e-947c-425546944cc1",
"id": "a81459be-67d6-4eed-99ba-89800b66742c",
"node_id": "92583486-2d4f-47eb-ad7a-1e4cc874f417",
"node_public_key": "b73b0bfa-7196-4b23-9189-b320e73d7424",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15-sources.jar.md5",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "03b057cb-a078-4cc7-af86-ccf8a9acd700",
"timestamp": 1671004618
},
{
"artifact_hash": "e74339769bffce344ee5a4645a64466ad4ffe2002cf774285e3f20fdb110b503",
"artifact_id": "a1157f84-27a5-44ba-91ed-7d0b715d5cdc",
"id": "11a18760-353b-4b01-8f08-1ebd7beccc0b",
"node_id": "4ea91665-c74d-434c-b9bd-cab07f70ccd9",
"node_public_key": "e9d812d8-bac1-4920-b846-d0d3d4c305ca",
"num_artifacts": 15,
"operation": "AddArtifact",
"package_specific_artifact_id": "commons-codec/commons-codec/1.15/commons-codec-1.15-test-sources.jar.md5",
"package_specific_id": "commons-codec:commons-codec:1.15",
"package_type": "Maven2",
"source_hash": "",
"source_id": "c187d8ab-de26-4811-a2d5-8a0920eb0b9f",
"timestamp": 1671004618
}
]