foriequal0 / git-trim

Automatically trims your branches whose tracking remote refs are merged or stray
MIT License
490 stars 14 forks source link

Distribute binaries as NPM package #159

Closed Spunkie closed 4 years ago

Spunkie commented 4 years ago

I would be nice if you could distribute the release binaries as an NPM package. So people could simply run npm install git-trim/yarn add git-trim to get up and running instantly.

It would allow a team to easily install git-trim, integrate it with a typicode/husky git hook, commit that logic to git, and distribute that logic to the rest of the teams build system. No worries about where to download the release, having to keep the binary up to date by manually checking and notifying team members, adding logic in the hook for a missing binary, etc...

foriequal0 commented 4 years ago

I'm not familiar to NPM. Would you review the PR? I might be able to publish after v0.4.0-alpha.3 because I've published and unpublished v0.4.0-alpha.2 for testing.

Spunkie commented 4 years ago

Wow quick work 🎉

I'm not actually familiar with packing npm packages myself, just using them. At first pass looking at the code changes nothing stands out to me. So I just went though and tested trying to install/use it like I normally would. I'm running win10 btw.

  1. made a new dir /git-trim-npm-test/ to work in
  2. ran yarn init with all the default info to generate a package.json
  3. Then I ran yarn add https://github.com/foriequal0/git-trim#npm to install directly from your feature branch.
  4. I can confirm at this point./node_modules/.bin/ does contain a git-trim & get-trim.cmd like I would generally expect to find.
  5. I added this script to the package.json
    "scripts": {
    "test-get-trim": "git-trim"
    },
  6. I ran npm run test-get-trim
  7. I got this error Code_MjaCWJoWjTmROSQwOMQ62n2fVKZoN42M
foriequal0 commented 4 years ago

It'll work by now. tgz file was missing for Windows. I've uploaded it and tested with npm since I don't have yarn. If it prints Error: could not find repository from '.'; class=Repository (6); code=NotFound (-3), it means that it found git-trim.

Spunkie commented 4 years ago

Yup I just tested and the git-trim binary is actually running now. 🎊

Although this might be a bit outside the scope of this specific issue, but when I run the npm script "test-get-trim": "git-trim --bases master" in a real repo it complains about git@github.com: Permission denied (publickey). But I definitely have my github ssh key loaded in my pageant auth agent.

foriequal0 commented 4 years ago

I haven't used pageant on Windows. I found some possible solutions on SO https://stackoverflow.com/a/40804226/3176773 Can you try again with an environment variable GIT_SSH=<path to plink>?

Spunkie commented 4 years ago

Awesome, that works! I was able to simply pass it GIT_SSH="plink.exe" to grab it on the path. My final test script looks like:

"scripts": {
    "trim-merged-branches": "run-script-os",
    "trim-merged-branches:default": "git-trim --no-confirm -bp master",
    "trim-merged-branches:windows": "cross-env GIT_SSH=\"plink.exe\" git-trim --no-confirm -bp master"
},
"husky": {
    "hooks": {
        "post-merge": "npm run trim-merged-branches"
    }
},

I ended up using cross-env since, depending on the version, windows doesn't really allow passing in env vars like that. And run-script-os to run that windows specific cmd.


Here's a screenshot showing it working with context in my real repo and automatically triggering during a pull.

Code_xlw7aB53rEVKvMPMiOCSChotnfc6af7r


Edit: Also I guess I would add on --no-update since github is already automatically deleting the remote branch when a PR is merged?

foriequal0 commented 4 years ago

Thanks for sharing working screenshot! --no-update prevents git-trim to invoke git fetch --all --prune. Since you're using it on post-merge hook, it'll prevent you from fetching twice. However, git-trim might see deleted-on-github-but-not-pruned-on-local-yet remote tracking branches. It'll affect to the classification results. These unsynchronized branches might even be significantly differnt from its last states. I've tried to make it conservative on the branch classification (not to lose your changes), but I'm not 100% sure. I'm using git config --global fetch.prune true to make sure git pull or git fetch always prune branches.

foriequal0 commented 4 years ago

@Spunkie Sorry for saying this, but I'm considering to retract this decision. Maintaining NPM packaging seems small but I would not say it doesn't add any burdens to me as an individual developer with a full-time job to maintain unfamiliar public surfaces.

I think it would be better to run your own postinstall script and small script for trim-merged-branches. It'll also reduce your run-script-os, cross-env dependencies. I've already unified release namings and compression formats. (git-trim-(linux|mac|win)-${version}.tgz) Here's scripts for you.

// git-trim.js
const process = require("process");

const axios = require("axios");
const { Binary } = require("binary-install");

const platformMapping = {
    "linux": "linux",
    "darwin": "mac",
    "win32": "win",
};

const platform = platformMapping[process.platform];
console.assert(
    platform !== undefined && process.arch === "x64",
    "git-trim is unsupported on this platform"
);

async function getBinary() {
    for (let page = 1; ; page++) {
        const releases = await axios.get(`https://api.github.com/repos/foriequal0/git-trim/releases?page=${page}`, {
            responseType: "json",
        });

        if (releases.data.length === 0) throw new Error("git-trim release not found");

        for (const release of releases.data) {
            for (const asset of release.assets) {
                if (asset.name.startsWith(`git-trim-${platform}-`) && asset.name.endsWith(".tgz")) {
                    const url = asset.browser_download_url;
                    return new Binary(url, {
                        name: "git-trim",
                    });
                }
            }
        }
    }
}

module.exports = {
    install: () => getBinary().then(b => b.install()),
    run: () => getBinary().then(b => b.run()),
};
// postinstall.js
require("./git-trim").install();
// trim-merged-branches.js
const process = require("process");
if (process.platform == "win32") {
    process.env.GIT_SSH="plink.exe"
}
require("./git-trim").run();
{
    "scripts": {
        "postinstall": "node postinstall.js"
    },
    "husky": {
        "hooks": {
            "post-merge": "node trim-merged-branches.js --no-confirm -bp master"
        }
    },
}