Get composer outdated packages w/o install
Tags: php, python, productivity
Published: 2020-09-28 23:02:40

Recently, I wanted to get a list of direct dependencies in our php source code that are outdated.
[final result](https://github.com/rishirajpurohit/composerOutdatedNoInstall/blob/master/outdated.py)

The initial thought was running dependabot, while it opens a `pr` for each minor upgrades, I thought it would be cool to see how I can do the same.

Initially, I found the composer command for the same, we can run:
```
composer outdated --direct -f json
```
To get a list of outdated packages in a nice format 😍

The next thought was to put it behind a service or have it on a server, which brought me to the next hurdle.

I do not want to install the packages, or have post-install commands runs in a server that I won't be using for anything else.🤷🏻‍♂️

🤔 How do we get a list of outdated packages without installing the packages, and do we even need composer for this?

After some thought, I decided to use `composer.json` and `composer.lock` to get some info and find an API for package information from the packagist.🤞🏻

The API is more of a url with json extension🤫. For example, to get package details for `monolog/monolog` you can just append `.json` at the end of the url. 
The url in packagist are pretty well formatted so for a package like `monolog/monolog` the url becomes: `https://packagist.org/packages/monolog/monolog.json`

Now, equipped with constraints, current version and package information, it was time to write a script.🤓

## Step 1: Parsing the files
I used `json` library available in python to get the data out of those files.
{% gist https://gist.github.com/rishirajpurohit/27318cd5ecc7c38919a508fd3e00a72f %}

## Step 2: Reading metadata from packagist
I used the repo subdomain, but direct url works as well.
{% gist https://gist.github.com/rishirajpurohit/b782298b1375dc4262351f4df27541fd %} 

## Step 3: Working with *semantic versions* 😯
* [Semantic Versioning](https://semver.org/)🤓
* [Library Used, readthedocs.io](https://python-semanticversion.readthedocs.io/en/latest/reference.html)
* [semver package at npm for NpmSpec](https://docs.npmjs.com/misc/semver.html)

This was the trickiest part because we need to handle different cases and there were some packages which referenced to git commit😒. But after some try-catch and playing around with `semantic-version` library I was able to get the parsing handled. Once done with parsing, comparing versions and preparing the final result was a breeze.🥳
{% gist https://gist.github.com/rishirajpurohit/03cf47a2fc95359e5c9ac941754325f7 %}

*Note:* I had to switch to class `NpmSpec` instead of `SimpleSpec` to better handle the versions. This library uses the semantic version defined by [npm-semver](https://docs.npmjs.com/misc/semver.html)

While the script is just a starting point, it was quite fun to write and maybe I'll expand it to make it object oriented add test cases along with other bells and whistles 😉

Hope you enjoyed reading it, and it provided you nice tools 💪🏻 to use when dealing with semantic versioning in your code. Let me know in comments if I should have explained the process differently.

Make sure you follow, clap, throw some unicorns at me and share this post with your friends, family, neighbours and everyone you meet on road. 😄