npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@jsenv/github-pull-request-filesize-impact

v3.0.3

Published

Monitor pull request impact on file sizes.

Downloads

2

Readme

github-pull-request-filesize-impact

Monitor pull request impact on file sizes.

github package npm package workflow status codecov

Table of contents

Presentation

@jsenv/github-pull-request-filesize-impact comment your pull request on github to see the impact of changes on specific file sizes.

The screenshot below shows how it is integrated to a github pull request.

screenshot of pull request comment

The comment can be expanded to get more details.

screenshot of pull request comment expanded

Installation

npm install --save-dev @jsenv/github-pull-request-filesize-impact

How it works

In order to know a given pull request size impact two functions are needed: generateSnapshotFile and reportSizeImpactIntoGithubPullRequest.

generateSnapshotFile generates a .json file saving file size to compare them later. It must be runned twice:

  • Once on pull request base branch
  • Once on a state where pull request head has been merged into its base.

Then reportSizeImpactIntoGithubPullRequest can be called. It reads these two .json files, compare them and comment the pull request accordingly.

To configure this for your project check Configuration for Github workflow and Configuration outside Github workflow.

Configuration for GitHub workflow

You can see how this can be integrated in a GitHub workflow in .github/workflows/size-impact.yml

And also see several runs for this workflow at https://github.com/jsenv/jsenv-github-pull-request-filesize-impact/actions?workflow=size-impact

Fork issue

Using GitHub workflow has one drawback: When a fork opens a pull request the workflow fails. This is because the workflow is runned inside the forked repository. GITHUB_TOKEN from forked repository is not allowed to post comment inside main repository.

Check https://github.community/t5/GitHub-Actions/Token-permissions-for-forks-once-again/td-p/33839 for more information.

Configuration outside GitHub workflow

generateSnapshotFile needs to be runned twice in a given git state. To setup your git state check Configuration for Github workflow. The exact code is up to you according to your execution environment.

reportSizeImpactIntoGithubPullRequest needs special process.env values and throw if they are missing. These variables are available in a github workflow, when outside you must provide them manually. The code below shows what process.env values must be set.

import { reportSizeImpactIntoGithubPullRequest } from "@jsenv/github-pull-request-filesize-impact"

const githubToken = "github-personnal-access-token"
const githubRepository = "repository-owner/repository-name"
const pullRequestNumber = 1
const pullRequestRef = "pr-name"

process.env.GITHUB_EVENT_NAME = "pull_request"
process.env.GITHUB_REPOSITORY = githubRepository
process.env.GITHUB_REF = `refs/pull/${pullRequestNumber}/merge`
process.env.GITHUB_BASE_REF = "master"
process.env.GITHUB_HEAD_REF = pullRequestRef
process.env.GITHUB_TOKEN = githubToken

reportSizeImpactIntoGithubPullRequest({
  projectDirectoryUrl: "file:///Users/directory",
})

If you where inside travis you would write process.env.GITHUB_REPOSITORY = process.env.TRAVIS_REPO_SLUG. As documented in https://docs.travis-ci.com/user/environment-variables/#default-environment-variables

Also be sure githubToken has the right to read/write comments on issues.

generateSnapshotFile

generateSnapshotFile is an async function analysing file sizes per directory and saving the result into a json file.

import { generateSnapshotFile } from "@jsenv/github-pull-request-filesize-impact"

await generateSnapshotFile({
  projectDirectoryUrl: "file:///directory",
  trackingConfig: {
    dist: {
      "./dist/**/*.js": true,
    },
  },
  snapshotFileRelativeUrl: "./size-snapshot.json",
})

— source code at src/generateSnapshotFile.js.

projectDirectoryUrl

projectDirectoryUrl parameter is a string leading to your project root directory. This parameter is required.

logLevel

logLevel parameter controls verbosity of logs during the function execution.

The list of available logLevel values can be found on @jsenv/logger documentation

trackingConfig

trackingConfig parameter is an object used to configure group of files you want to track. This parameter is optional with a default value exported in src/jsenvTrackingConfig.js

trackingConfig keys are group names that will appear in the generated comment. trackingConfig values are specifierMetaMap as documented in https://github.com/jsenv/jsenv-url-meta#normalizespecifiermetamap.

For every group you track there will be a corresponding line in the generated pull request comment as visible in docs/comment-example.md

For example you can create two groups like this:

const trackingConfig = {
  whatever: {
    "./dist/whatever/**/*.js": true,
  },
  dist: {
    "./dist/**/*.js": true,
    "./dist/whatever/**/*.js": false,
  },
}

And the generated comment will have two expandable section.

transformations

transformations parameter is an object used to transform files content before computing their size. This parameter is optional with a default value of { none: (buffer) => bufer }.

You can use this parameter to track file size after gzip compression.

import { generateSnapshotFile, none, gzip } from "@jsenv/github-pull-request-filesize-impact"

await generateSnapshotFile({
  projectDirectoryUrl: "file:///directory",
  transformations: { none, gzip },
})

And the pull request comment now contains gzip size. Check docs/comment-example.md#introduce-gzip to see how it looks like.

You can enable none, gzip and brotli compression this way. transformations can be used to add custom transformations.

import { none, gzip } from "@jsenv/github-pull-request-filesize-impact"

const transformations = {
  none,
  trim: (buffer) => String(buffer).trim(),
}

manifestFilePattern

manifestFilePattern parameter is a string controlling if a manifest json file will be taken into account when generating snapshot. The parameter also control the name of the manifest file. This parameter is optional with a default value of ./**/manifest.json.

Manifest where introduced by webpack in https://github.com/danethurber/webpack-manifest-plugin. There is the equivalent for rollup at https://github.com/shuizhongyueming/rollup-plugin-output-manifest.

The concept is to be able to remap generated file like file.4798774987w97er984798.js back to file.js.

Without this, comparison of directories accross branches would consider generated files as always new because of their dynamic names.

reportSizeImpactIntoGithubPullRequest

reportSizeImpactIntoGithubPullRequest is an async function comparing two directory snapshots and commenting a github pull request with the comparison result.

import { reportSizeImpactIntoGithubPullRequest } from "@jsenv/github-pull-request-filesize-impact"

await reportSizeImpactIntoGithubPullRequest({
  projectDirectoryUrl: "file:///directory",
  baseSnapshotFileRelativeUrl: "../snapshot.base.json",
  headSnapshotFileRelativeUrl: "../snapshot.head.json",
  logLevel: "info",
  generatedByLink: true,
})

— source code at src/reportSizeImpactIntoGithubPullRequest.js.

baseSnapshotFileRelativeUrl

baseSnapshotFileRelativeUrl parameter is a string leading to the base snapshot file. This parameter is required.

headSnapshotFileRelativeUrl

headSnapshotFileRelativeUrl parameter is a string leading to the head snapshot file. This parameter is required.

commentSections

commentSections parameter is an object controlling which comment sections are enabled and their order. This parameter is optionnal and enable groupImpact, fileByFileImpact and cacheImpact section in that order. Check docs/comment-example.md#basic-example to see the comment sections.

You can control sections order because it follow commentSections keys order. You can also control which section are enabled at all. For instance docs/comment-example.md#group-disabled-filebyfile-enabled-cache-disabled can be generated by passing commentSections below.

const commentSections = { fileByFileImpact: true }

This parameter could be an array. Using an object was decided in case each section becomes configurable in the future.

generatedByLink

generatedByLink parameter controls if pull request comment contains a generated by message. This parameter is optionnal and enabled by default. This parameter allows someone to understand where the pull request message comes from.

formatSize

formatSize parameter controls the display of file size. This parameter is optionnal, the default value doing an english formatting of a number. Check source code if you want to pass a custom function.

Why merge

As documented in How it works generateSnapshotFile must be called in a state where the pull request is merged into its target. This part explains why it's needed.

To know impacts of a pull request changes on a given branch, these changes must be on the branch. To understand why we will simulate what happens starting from a git tree where:

  • There is a master branch
  • me branch is one commit ahead of master
  • other branch is one commit ahead of master
  • A pull request wants to merge me into master

In upcoming "schemas", a capital letter represent a commit.

Initial git tree

   ┌───D─── other (A+D)
   │
───A─────── master (A)
   │
   └───B─── me (A+B)

Now other gets merged into master

Git tree after merging other branch

   ┌───D───┐ other (A+D)
   │       │
───A───────D─── master (A+D)
   │
   └───B──── me (A+B)

Now we push a commit to me

Git tree after pushing into me branch

   ┌───D───┐ other (A+D)
   │       │
───A───────D─── master (A+D)
   │
   └───B───E─── me (A+B+E)

In this state:

  • me is 1 commit behind master and 2 commits ahead

    Pull request wants to merge B,E and does not contain D.

  • merging pull request means adding B+E into master. Master would become A+D+B+E.

    Depending how pull request gets merged order may differ but that's not important for this demonstration.

To compute the actual impact of merging me into master we must simulate the merge. Let's create a merge branch with this state.

Git tree after creating merge branch

   ┌───D───┐ other (A+D)
   │       │
───A───────D──── master (A+D)
   │       │
   │       └───┬─── merge (A+D+B+E)
   │           │
   └───B───E───┘ me (A+B+E)

If D changes overlaps with E changes, impact is analysed after these changes are merged.

Moreover D changes that are not in B or E are ignored thanks to diff between merge and master.

merge = A+D+B+E
master = A+D
merge - master = B+E