A tool for displaying historical metrics about a project's dependencies. Run the Freshli CLI on your project to see how its dependency freshness changes over time.
freshli
is only distributed in binary form via a Docker container image. The Docker container image includes the freshli-agent-java
executable. As new language agents are released, these will be added to the container image as well.
If you don’t want to use Docker, you’ll need to build from source and configure your environment appropriately.
Use the docker pull
command to retrieve the latest version of the container image.
docker pull corgibytes/freshli-cli:latest
It’s a good idea to run this command periodically to check for new versions.
Next pass the --version
option to check the version that’s been retrieved.
docker run --rm corgibytes/freshli-cli --version
The analyze
command is used to compute LibYear metrics from a local or remote Git repository. The LibYear metric is computed for every package found in every dependency manifest file for the entire history of the repository branch that is being analyzed.
Data is sent to the Freshli app website via API calls. You need to visit the link that’s provided in the analyze
command’s output to view the results. There is no other supported way to access the collected data at this time.
❗ Warning
The
analyze
command may take a long time to complete. For some projects, it may take well over an hour. How long it takes is dependent on several variables, such as the amount of history in the Git repository and the number of packages that are found at each point in time. The performance characteristics of the computer running the command is also a factor.
📝 Suggestion
On Windows, you will see performance benefits if you exclude the cache directory (default
$HOME/.freshli
) from real-time security analysis by the malware engine that's built into Windows. You can do this by opening a PowerShell session as an administrator and running the following command:Add-MpPreference -ExclusionPath $HOME/.freshli
If you're working with this repository as a developer, then you'll also want to add an exclusion for the
./tmp
directory, which is used by the test suite.
To analyze a remote Git repository, provide a Git URL that can be used to clone the repository, such as https://github.com/corgibytes/freshli-fixture-java-test
.
docker run --rm corgibytes/freshli-cli analyze https://github.com/corgibytes/freshli-fixture-java-test
Unless a branch name is provided with the --branch
option, the default branch will be used.
To analyze a local Git repository, one that has already been cloned, provide a file system path to the location of the repository. The branch that is checked out is the one that will be analyzed.
git clone https://github.com/corgibytes/freshli-fixture-java-test
docker run --rm corgibytes/freshli-cli analyze freshli-fixture-java-test
By default, the analyze
command computes metrics at one month intervals. This value can be changed with the --history-interval
option. Valid values are in the form of <number><unit>
, where <number>
is a positive integer and <unit>
is either y
for years, m
for months, w
for weeks, or d
for days.
The following command sets the history interval to 2 weeks.
docker run --rm corgibytes/freshli-cli analyze --history-interval=2w https://github.com/corgibytes/freshli-fixture-java-test
It is possible for some commits to get skipped depending on the history interval that is selected. Specifying the --commit-history
option will instruct the analyze
to compute metrics for every commit regardless of the history interval value.
Example:
docker run --rm corgibytes/freshli-cli analyze --commit-history https://github.com/corgibytes/freshli-fixture-java-test
For times when you would like to prevent the collection of historical metrics, use the --latest-only
option.
Example:
docker run --rm corgibytes/freshli-cli analyze --latest-only https://github.com/corgibytes/freshli-fixture-java-test
The analyze
command, like many freshli
commands, employs background workers to make full use of available CPU resources. You can use the --workers
option to control the number of background workers that are used.
Example:
docker run --rm corgibytes/freshli-cli --workers=2 analyze https://github.com/corgibytes/freshli-fixture-java-test
This command is used to determine the language agents that are available to freshli
.
docker run --rm corgibytes/freshli-cli agents detect
This command is used to determine if the the language agents behave in the way that Freshli
expects.
docker run --rm corgibytes/freshli-cli agents verify
The freshli
executable does not have built-in support for processing dependency manifest files. Language-specific agent programs, executables with names starting with freshli-agent-
, provide the ability to process dependency manifests from different language ecosystems.
Here is a list of language agents that have been developed so far and are included in the Docker container image mentioned above.
Language | Agent | Dependency Manager |
---|---|---|
Java | freshli-agent-java |
Maven |
Please let us know what other dependency managers and/or manifest files you would like use to support via the contact information in the Contributing section.
The freshli analyze
command computes the LibYear metric.
The libyear for a dependency is calculated by dividing the days between the current version and latest version by 365. Yes we know we shouldn't always use 365, we will fix it in a future release. For example, if the days between the current dependency and the latest is 42 days then the libyear is:
42 / 365 = 0.1151
Say you have 4 dependencies that are 128, 256, 512, and 1024 the libyear would be:
(128 / 365) + (256 / 365) + (512 / 365) + (1024 / 365) =
0.3507 + 0.7014 + 1.4027 + 2.8055 =
5.2603
That means you dependencies are 5.3 libyears out of date or 5 libyears and 109.5 libdays.
Note: The latest dependency is determined based on date the check is run. For example, if a dependency has the following release dates:
Jan 1, 2019 (v1.0.0)
Jan 26, 2019 (v1.0.1)
Apr 3, 2019 (v1.1.0)
Sep 15, 2019 (v1.2.0)
Oct 31, 2019 (v1.2.1)
When checking the libyear on May 1, 2019 Freshli will use v1.1.0 (Apr 3rd, 2019) as the latest dependency. So if as of May 1, 2019 your project uses v1.1.0 your libyear is zero as v1.2.0 was not released until Sep. If on May 1st your project is using v1.0.0 then your libyear is days between Apr 3, 2019 and Jan 1, 2019 which is 93 days so you get a libyear of:
93 / 365 = 0.2548
If you have v1.0.1 installed then your libyear when checking on May 1, 2019 is 68 days for a libyear of:
68 / 365 = 0.1863
The headings for column output are localized such that the culture settings of the user's computer are used. (This is found in the CurrentUICulture). Currently there are English and Spanish translations with English being the default.
Data (such as dates and numeric formatting) are NOT localized. Dates and numeric formats use the CurrentCulture which is explicitly set to the invariant culture.
We are not sure how to handle documentation, such as this ReadMe, in different languages. If you have any suggestions or would like to help with translations please let us know using the contact information in the Contributing section.
By default all logs are set to WARN level and sent to the console output.
Log levels can be adjusted by using the --logLevel <level>
option when running the application. The level can be any level that is supported by NLog:
- Trace
- Debug
- Info
- Warn
- Error
- Fatal
Logs can be redirected to a file instead by using the --logfile <file_path_and_name>
option when running the application.
⚙️ Prerequisites
- The scripts in the
bin/
directory requireruby
version 3.1 or later to be installed. - Make sure you have the latest .NET 7.0 SDK installed before attempting to run any of the commands below.
The project can be built using the bin/build.rb
script.
To build manually, you first need to install the DotNet tools that are used by the project with:
dotnet tool restore
Then you can build the freshli
executable and place it in the exe
directory (where the acceptance tests expect it to be located) with:
dotnet build -o exe
We use a few different automatted tools tools to help us keep the code in this repository in compliance with the Freshli project style guide.
All of the following linters (with the exception of codeclimate
) can be run together by running the bin/lint.rb
script. You can also run the bin/format.rb
script if you want to instruct the linters to correct any issues that are found. (Note: not all of the linters provide an auto-correct mechanism.)
The eclint
project helps us validate that the files in the project are formatted consistently with respect to the rules that have been defined in the .editorconfig
file.
After making sure the eclint
executable's in your path, it can be run with:
eclint
The rubocop
project help us validate that the Ruby code we're writing conforms with the Ruby Style Guide that it is based on.
After running bundle install
, the following will run rubocop
:
bundle exec rubocop
The dotnet format
command helps us make sure that our code is formatted consistent with the .NET/C# specific settings that are present in the .editorconfig
file along with sets of validation rules that the project has been configured to use.
To determine if any style changes are needed, you can run:
dotnet format --verify-no-changes --severity info
To instruct dotnet format
to attempt to correct the issues that it has found, you can run:
dotnet format --severity info
If you encounter linter errors that persist despite being explicitly suppressed, try clearing the cache for JetBrains inspect code. On Windows the cache is located here
%LocalAppData%\JetBrains\Transient\InspectCode\v212\SolutionCaches
On Linux and macOS the cache is located here~/.local/share/JetBrains/Transient/InspectCode/v221/SolutionCaches
There are two ways to run the codeclimate
linter, by using the codeclimate
CLI or by using docker
. For both options, you'll need docker
installed, because the codeclimate
CLI is just a wrapper that makes it easy to run the codeclimate
Docker image.
-
Using the
codeclimate
CLINote: This option will not work if you're working with the DevContainer.
With the
codeclimate
CLI in your path, simply run the following to execute the CodeClimate analysis:codeclimate analyze
-
Using
docker
Since
codeclimate
CLI is a wrapper around thecodeclimate
docker image the following command can be used to run the analysis:docker run \ --interactive --tty --rm \ --env CODECLIMATE_CODE="$PWD" \ --volume "$PWD":/code \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume /tmp/cc:/tmp/cc \ codeclimate/codeclimate analyze
The above command will need to be changed if you're attempting to run
codeclimate
from within the DevContainer. This is because$PWD
in the command above will expand to be the path to the project source code as it is mounted in the container. Thedocker
command needs the path to the source code on your host system.To address this you'll need to start the DevContainer with an environment variable that contains the path to the source code on the host system. Here, we'll use
$CODE_FOLDER
.Another thing that needs to be done is to mount the socket that's used for communicating with Docker on the host system.
docker build -t freshli-cli-dev .devcontainer docker run \ --interactive --tty --rm \ --env CODE_FOLDER=$PWD \ --volume $PWD:/code \ --volume /var/run/docker.sock:/var/run/docker.sock \ --user vscode \ --workdir /code \ freshli-cli-dev bash
And then from within that shell environment you can run
codeclimate
with:sudo docker run \ --interactive --tty --rm \ --env CODECLIMATE_CODE="$CODE_FOLDER" \ --volume "$CODE_FOLDER":/code \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume /tmp/cc:/tmp/cc \ codeclimate/codeclimate analyze
Also, note in the above command that we're using
sudo
to run thedocker
command. This is because of the permissions that are required to access the Docker socket from the host system.
docker run \
--interactive --tty --rm \
--env CODECLIMATE_CODE="$CODE_FOLDER" \
--volume "$CODE_FOLDER":/code \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume /tmp/cc:/tmp/cc \
codeclimate/codeclimate analyze
You can run the unit, integration, and acceptance tests by running the bin/test.rb
script.
⚠️ Important NoteSome of the integration tests require
freshli-agent-java
to be correctly installed in the path.
You'll need to have the Eclipse Temurin version of Java 17 installed before running the following commands. And you'll need Maven for some of the agent commands.
cd /tmp
git clone https://github.com/corgibytes/freshli-agent-java
cd freshli-agent-java
./gradlew installDist
mkdir -p /usr/local/share/freshli-agent-java
cp -r build/install/freshli-agent-java/* /usr/local/share/freshli-agent-java
ln -s /usr/local/share/freshli-agent-java/bin/freshli-agent-java /usr/local/bin/freshli-agent-java
cd ~
rm -rf /tmp/freshli-agent-java
The project's unit and integration tests can be run with:
dotnet test
Freshli's acceptance test suite, built using Aruba and Cucumber, is pre-configured in the repository.
You will need Ruby installed on your system, and then run:
gem install bundler
bundle
From then on, you can run the Aruba tests with:
dotnet build -o exe && bundle exec cucumber
Code coverage data can be collected for the acceptance tests. This activity is performed by the project's continuous integration environment where the collected data is sent to CodeClimate for further tracking. You can also run the code coverage collection locally.
First you'll need to make sure that the correct version of the Coverlet code coverage tool is installed:
dotnet tool restore
📙 Take Note
Make sure you run
bin/build.rb
before running any of the following commands.
The following command can be used to compute the total test coverage across the .NET-based unit and integration tests combined with the Cucumber-based acceptance tests.
dotnet coverlet --target "./bin/test.rb" --targetargs "--skip-build" ./exe
The following command will report the code coverage of the tests that are authored using the .NET-based testing tools.
dotnet coverlet --target "dotnet" --targetargs "test exe/Corgibytes.Freshli.Cli.Test.dll" ./exe
The following command will list the code coverage for the Cucumber-based tests.
dotnet coverlet --target "bundle" --targetargs "exec cucumber" ./exe
This project uses DevContainer to assist with creating a full configured development environment.
There are two paths to working with this DevContainer setup.
-
Install the
devcontainer
CLI and then rundevcontainer build
followed bydevcontainer open
. That will open Visual Studio Code running from inside of a container with everything needed to build the project. -
Run
docker
directly. Rundocker build -t freshli-cli-dev .devcontainer/
to build the container. Then you'll be able to rundocker run --rm -it -v $PWD:/code -w /code freshli-cli-dev bash
to create a shell session inside of a running container with everything set up for you. (Note, you may need to runbundle install
when you first start the container to install the ruby-based dependencies. This step is performed for you if you use thedevcontainer
CLI to open a Visual Studio Code instance.)
A production-ready container can be created from the Dockerfile
in this project by running:
docker build -t freshli-cli .
You can then run the container with:
docker run --rm freshli-cli agents detect
You should see output that looks similar to:
❯ docker run --rm freshli-cli agents detect
+------------------+---------------------------------+
|Agent file |Agent path |
+------------------+---------------------------------+
|freshli-agent-java|/usr/local/bin/freshli-agent-java|
+------------------+---------------------------------+
Docker images are built and published to DockerHub by the CI process whenever a commit is added to the main
or release/*
branches (assuming that all of the tests have passed).
Follow these instructions if you need to produce a build manually.
-
Log into DockerHub
The account that you login with will need to have write permissions for the
corgibytes/freshli
project.docker login
-
Create a local buildx node
docker buildx create --use
-
Build and publish
This will create images that can run on Intel/AMD 64-bit or ARM 64-bit processors.
You'll need to update the tag list with the specific tag list to include the specific tags that you want to publish.
docker buildx build \ --push \ --platform linux/arm64/v8,linux/amd64 \ --tag corgibytes/freshli-cli:latest \ .
This project uses C#'s Code First Migrations: https://docs.microsoft.com/en-us/ef/ef6/modeling/code-first/migrations/ Migrations allow us to keep track of changes we make to models saved in a database, and it keeps our databases up-to-date.
From the CLI:
dotnet ef migrations add [name]
By default it'll update to the latest available migration.
From the CLI:
dotnet ef database update
Reverting a migration is done similarly as to updating the database though we are now specifying til what point in time we want to revert.
From the CLI:
dotnet ef database update [specific migration name]
See the documentation for Activities and Events, which includes a diagram showing the relationships between the current set of activities and events.
The diagram referenced above is generated as part of our continuous integration process. This ensures that it stays up-to-date as changes are made to the application.
To update the contents of docs/activities-and-events.md
with an updated diagram, you can simply run:
bin/generate-diagram.rb
If you want just the raw diagram text, you can run:
dotnet run --project diagram-generator
The text that is output can be pasted into mermaid.live to see the rendered diagram.
If you have any questions, notice a bug, or have a suggestion/enhancment please let us know by opening a issue or pull request.
See the Contributing guide guide for developer documentation.