Code Monkey home page Code Monkey logo

compressed-size-action's Introduction

compressed-size-action

A GitHub action that reports changes in compressed file sizes on your PRs.

  • Automatically uses yarn, pnpm, bun, or npm ci when lockfiles are present
  • Builds your PR, then builds the target and compares between the two
  • Doesn't upload anything or rely on centralized storage
  • Supports custom build scripts and file patterns

Usage:

Add a workflow (.github/workflows/main.yml):

name: Compressed Size

on: [pull_request]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
      - uses: preactjs/compressed-size-action@v2

Customizing the Installation

By default, compressed-size-action will install dependencies according to which lockfiles are present, if any. However, if you need to run a different installation command, you can pass a custom script to do so. For example, to use npm ci with the --workspace option:

name: Compressed Size

on: [pull_request]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - uses: preactjs/compressed-size-action@v2
      with:
+       install-script: "npm ci --workspace=packages/my-subpackage"

Customizing the Build

By default, compressed-size-action will try to build your PR by running the "build" npm script in your package.json.

If you need to perform some tasks after dependencies are installed but before building, you can use a "postinstall" npm script to do so. For example, in Lerna-based monorepo:

{
  "scripts": {
    "postinstall": "lerna bootstrap",
    "build": "lerna run build"
  }
}

It is also possible to define a "prebuild" npm script, which runs after "postinstall" but before "build".

You can also specify a completely different npm script to run instead of the default ("build"). To do this, add a build-script option to your yml workflow:

name: Compressed Size

on: [pull_request]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - uses: preactjs/compressed-size-action@v2
      with:
+       build-script: "ci"

Clean up state between builds

For repositories or custom monorepo setups where files are modified in ways that are not reset by npm ci && npm run build, it may be necessary to define a custom "clean" script. This script resets any file modifications after the upstream (target) build ends and your PR code (HEAD) is checked out, but before installation of npm dependencies for HEAD:

name: Compressed Size
on: [pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: preactjs/compressed-size-action@v2
      with:
        repo-token: "${{ secrets.GITHUB_TOKEN }}"
+       clean-script: "clean"
// package.json
{
  "scripts": {
    // example - a simple nested node_modules setup:
    "postinstall": "cd packages && npm i",
    // between the two builds, we need to delete the inner node_modules:
    "clean": "rm -rf packages/node_modules"
  }
}

Customizing the list of files

compressed-size-action defaults to tracking the size of all JavaScript files within dist/ directories - anywhere in your repository, not just at the root. You can change the list of files to be tracked and reported using the pattern and exclude options, both of which are minimatch patterns:

name: Compressed Size
on: [pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: preactjs/compressed-size-action@v2
      with:
+       pattern: "./build-output/**/*.{js,css,html,json}"
+       exclude: "{./build-output/manifest.json,**/*.map,**/node_modules/**}"

Files are collected by finding matches for pattern, then any of those that match exclude are ignored. For that reason, most projects don't need to modify exclude. The default values for pattern and exclude are as follows:

with:
  # Any JS files anywhere within a dist directory:
  pattern: "**/dist/**/*.js"

  # Always ignore SourceMaps and node_modules:
  exclude: "{**/*.map,**/node_modules/**}"

Dealing with hashed filenames

A strip-hash option was added in v2 that allows passing a custom Regular Expression pattern that will be used to remove hashes from filenames. The un-hashed filenames are used both for size comparison and display purposes.

By default, the characters matched by the regex are removed from filenames. In the example below, a filename foo.abcde.js will be converted to foo.js:

strip-hash: "\\b\\w{5}\\."

This can be customized further using parens to create submatches, which mark where a hash occurs. When a submatch is detected, it will be replaced with asterisks. This is particularly useful when mix of hashed and unhashed filenames are present. In the example below, a filename foo.abcde.chunk.js will be converted to foo.*****.chunk.js:

strip-hash: "\\.(\\w{5})\\.chunk\\.js$"

Increasing the required threshold

By default, a file that's been changed by a single byte will be reported as changed. If you'd prefer to require a certain minimum threshold for a file to be changed, you can specify minimum-change-threshold in bytes:

minimum-change-threshold: 100

In the above example, a file with a delta of less than 100 bytes will be reported as unchanged.

Compression

By default, files are compared after gzip compression, but it's possible to use other compression algorithms (gzip/brotli/none) or disable the compression.

compression: "none"

compressed-size-action's People

Contributors

andrewiggins avatar apazzolini avatar arendjr avatar bartlomiejzuber avatar coliff avatar denniskigen avatar developit avatar dstaley avatar einselbst avatar estherkim avatar fisker avatar gavinsharp avatar jack-weilage avatar jeffreys-cat avatar jonny-puma avatar jovidecroock avatar marvinhagemeister avatar maxdesiatov avatar michaeldeboey avatar mister-ben avatar mmckenziedev avatar rschristian avatar sasurau4 avatar schliflo avatar slorber avatar spencerkordecki avatar teodragovic avatar turbo87 avatar vikingtristan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

compressed-size-action's Issues

Doesn't find build artifacts in nested folder in dist

I have a bit of an edge case setup where:

  1. it's a monorepo, building multiple packages into dist at once
  2. each package's build artifact goes into /dist/package-1/index.esm.js

It seems like compressed-size-action isn't finding the /dist/package-1/index.esm.js. Looking into the code here, it seems like the default glob pattern (i.e. **/dist/**/*.js) should match my files.

Below is a screenshot of my test in globster where the highlighted files are the matched files.

image

If it helps, you can see the result my CI run here.

Hope that helps fix this issue and thanks a bunch for this awesome action!

Inaccurate looking reports

I'm having trouble producing reports that look accurate.

I have a build that outputs a dist directory containing compiled (not minified) files structured like this:

index.js
A/
  index.js
  some.js
  helper.js
  files.js
B/
  index.js
  some.js
  helper.js
  files.js

I have a workflow setup like this:

name: Compressed Size
on: [pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: preactjs/compressed-size-action@v2
      with:
        pattern: "./dist/{index.js,**/index.js}"
        repo-token: "${{ secrets.GITHUB_TOKEN }}"

And it produces reports like this:

/index.js | 821 B
/A/index.js | 833 B
/B/index.js | 444 B

Users are expected to import the modules like this:

import A from 'package/A'

Some of the modules share the same internal dependencies, or have dependencies on each other. That's fine because I'm more interested in what the maximum potential cost of each module is, rather than showing that using A + B is less than the sum of their bundle sizes.

However, I know the values in the report are wrong in terms of the actual size contributes to bundles from importing say A/index.js. At first I assumed the action was only looking at the files themselves and not including their internal imports in the size calculation. But if I change the pattern to dist/**, not only do the reported sizes of the index.js files change but the plugin also reports size values for the directory itself (i.e., A). And some of the internal helper files also seem to have incorrect values. One standalone helper file was reported as being 4.5KB, but it's a small file and compressing it myself showed it to be 476 bytes.

minimum-change-threshold not taking effect

Hey,

We have this config

            - name: Check toolbar bundle size
              if: needs.changes.outputs.frontend == 'true'
              uses: preactjs/compressed-size-action@v2
              with:
                  build-script: 'build'
                  compression: 'none'
                  pattern: 'frontend/dist/toolbar.js'
                  minimum-change-threshold: 100

The action runs correctly. But we added the minimum-change-threshold: 100 and it isn't taking effect.

You can see here that we're getting the comment despite 0B change PostHog/posthog#19014 (comment)

Am I doing something silly?

Directory support for monorepo

Unfortunately, GitHub Actions does nose support the combination of working-directory and uses & with.
So, we can not use this action for subdirectory package like monorepo .

name: builder size
on: [pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: checkout
        uses: actions/checkout@v2
      - name: setup Node
        uses: actions/setup-node@v1
      - name: size check
        uses: preactjs/compressed-size-action@v2
        working-directory: ./packages/foo # This is invalid syntax
        with:
          repo-token: '${{ secrets.GITHUB_TOKEN }}'
          pattern: './build-output/**/*.js'
          build-script: 'build'

Probably, directory option or shell-script option will resolve this issue.

Currently, build-script specify npm run-script.
If this action provide shell-script, it allow us to write shell-script: cd packages/foo && npm run build.

git checkout fails when switching to base commit

I am getting the following error:

Screenshot 2020-03-13 at 20 41 24

A possible fix probably is using git reset --hard ${baseRef} instead of git checkout ${baseRef} here:

await exec(`git checkout ${baseRef}`);

Is there a way for me to easily test this fix without publishing my own fork as an action? I'd be happy to create a PR, but I don't see a way to test this properly...

Duplicate comments when using bot account

We have an issue where we want our organization bot account to be responsible for making the comment on the pull request. This can easily be done by changing the repo-token. However, there's a check in the code checking if the comment is posted by a bot user (https://github.com/preactjs/compressed-size-action/blob/master/src/index.js#L202). Regular bot accounts are not marked as bots, so this fails, and instead of updating the existing comment it instead posts a new.

The other check should be sufficient enough. Would you accept a PR that removes the bot-check?

Best regards

only supports being run on "[pull_request]"

Thanks for the cool action!

I tried adding it on my existing push-triggered workflow, and got a confusing error on my first try:

Run preactjs/compressed-size-action@v1
  with:
    repo-token: ***
    build-script: build
    show-total: true
    collapse-unchanged: true
##[error]Cannot read property 'base' of undefined

Looking into the code, it appears to be because the action depends on context.payload.pull_request:

const pr = context.payload.pull_request;

which presumably doesn't exist on push-triggered workflows.

I wanted the action run on push because a PR can go through multiple iterations and I wanted the compressed size reported for every iteration.

Ideal would be to support both types of triggers (it appears there is some commented out code to use the octokit API to fetch PR data), but at the very least it would be nice to fail a bit more gracefully (with a clearer error message).

Release v2.1.0 is not on the marketplace

I've tried using this action in my repo, but it seems like the latest version (v2.1.0) is not available on the marketplace. This is what I got in my GitHub workflow:

Error: Unable to resolve action `preactjs/[email protected]`, unable to find version `v2.1.0`

It seems to be missing from GitHub's marketplace page too:

Screen Shot 2021-04-04 at 11 11 14 AM

I'm guessing there's just a step missing since the release already exists in this repo?

Fails to report stats for PRs from a fork

Currently certain PR's coming from forks result in the action running in the context of the fork, which means it can't post a comment or a PR review to the PR/issue.

Possible workarounds:

  1. Report the size table back using a Status Check
    • Not sure if GitHub's UI will handle this
    • Not sure if status checks have the same permissions issue
    • Not sure if status checks for the HEAD or merge commit on a PR show on the PR itself

Size change always 0 Bytes

Looking at this action (and any other on my project) the size change is always 0 B:

**Size Change:** 0 B 🆕

**Total Size:** 0 B

https://github.com/libremesh/lime-app/actions/runs/4828080867/jobs/8601485901?pr=370#step:4:332

The size on the current build for index.html is 869 B:

https://github.com/libremesh/lime-app/actions/runs/4828080867/jobs/8601485901?pr=370#step:4:157

Instead for the base is 567 B:

https://github.com/libremesh/lime-app/actions/runs/4828080867/jobs/8601485901?pr=370#step:4:291

Not sure if I' doing something bad? Is using node 16.

Allow running with multiple configurations

Our application (https://github.com/WordPress/openverse-frontend) generates two distinct bundle groups during the build process, a "modern" and "universal" bundle (this is a concept we inherit by using Nuxt). We'd like to have separate compressed size checks for each of the two build types, however, when you try to run the compressed-size-check action twice in one PR, it overwrites the comment.

You can observe the issue in this PR: WordPress/openverse-frontend#1378

If you check the edit history of the bot's comment, you can see that it overwrote itself.

Would y'all accept a PR to add an optional "key"/"id"/"comment-key" (names are hard) input that could be used to specify the comment to update?

Essentially my idea would be to update this conditional to additionally check for the new input in the body: https://github.com/preactjs/compressed-size-action/blob/master/src/index.js#L202-L205

For example, instead of just compressed-size-check being in the body, it could be compressed-size-check::${key} or something along those lines.

Thanks!

Document missing inputs?

Hey! I was reading through the README and couldn’t quite figure out how this action worked… there didn’t seem to be any configuration about where to look for the output of the build. I thought maybe it automagically figured it out by only comparing untracked file (not checked in to Git) Then I read through the source and found there are pattern and exclude inputs.

Is there a reason those aren’t documented in action.yml and the README? 🤔

% change value is incorrect

If you have a 1KB file, reduced by 0.5KB, it reports the change as 100% rather than 50%.

This line needs to use the original size as the divisor, so delta + size rather than size.

The tag v2 is too old

Thank you to release the version 2.6.0.

The tag v2 still points the tag 2.5.0. Please update the tag.

cf. #93

Support running on [push]

As requested on Twitter and in #6, it would be nice to allow running this action on push, in addition to the pull_request workflow. The action should comment on the push with size deltas from its parent commit.

Support `working_directory` option

Hi, thanks for this action. My npm package is not in the root of the repo.

WDYT about adding working_directory option - good idea or not?

add --legacy-peer-deps for npm install script

Hi there,
Since our project has some external deps which config peerDeps but not really need that. Current build will failed since peer check. Please add --legacy-peer-deps mark or provide a config to enable ignore the peer check.

Thanks

Does not work with pull_request_target

Edit: make sure to check my security issue comment here: #54 (comment)


When using pull_request_target, the action compares master against master, instead of comparing master against the PR.

This bug repo PR demonstrates the problem:
#53

I expect changes to be reported in comments according to my changes but no changes were reported.

image

We can also see the problem in the Action logs:

https://github.com/preactjs/compressed-size-action/runs/1929330272?check_suite_focus=true

image

The commit hash is used 2 times and is the current HEAD of master:

image

cc @developit

Local dir is not clean up properly before switching to target branch

We found a scenario where this action is not completely cleaning up local directory before switching to the target branch, resulting in an invalid build:

Let's say I have a master branch that has a single dep, and two packages (one root, one nested):

./package.json
./node_mooules/[email protected]
./packages/some-package/package.json

And then imagine I have a branch that updates lib dependency in my nested package, so npm i generates:

./package.json
./node_mooules/[email protected]
./packages/some-package/package.json
./packages/some-package/node_modules/[email protected]

So far so good. The above structure is valid and works without problems. However, when using this action it will essentially do (the build step is not important):

  • Checkout branch
  • Run npm ci
  • Checkout master
  • Run npm ci

Running npm ci cleans ./node_modules, but it does not clean ./packages/some-package/node_modules (tested with npm 6.14.12), so when checking out master there is still a leftover /packages/some-package/node_modules/[email protected] present, and it is never clean up. The resulting combination may break and fail to compile (in fact, it did in WordPress/gutenberg#31476 (comment), where we found the issue).

I think the solution would be to do a manual rm -fr **/node_modules before checking out the target branch.

Support yarn

It would be nice to support installing deps with Yarn rather than npm. Alternatively just doing npm install rather than npm ci for projects without package-lock.json files would work

Enabling tracking of non-js files

Currently it appears this compress-size-action only contains the ability to track changes in .js files. Is it possible to expand this to track all changed build file types? Or at least provide a regex or list which identifies all filetypes to track? For example, a generic angular project build file will contain a mixture of js, css, json, and html files (along with a few other minor extension types).

Compare against the state of the target branch at the moment the branch was created.

Hi and thanks for this great github action.

At the moment, if you want to have the right diff numbers, the PR branch need to be fresh compared to the target branch (rebased). In a fast-moving repository, this can be hard to ensure consistently, so you end up with numbers that doesn't make a lot of sense.

I was wondering if it's possible to diff against the PR branch minus its commits (the hash just before the first commit of the PR branch) instead of comparing against the current state of the target branch.

Thanks.

Reported size change doesn't account for new files

I noticed that if a diff deletes a file and adds a new one, the deletion contributes to the "Size change" value but the addition does not. The new file is listed under "View unchanged". The "Total size" is accurate but unless someone pays attention to what the total size was in the last PR, they may be misled by a PR that claims to make a lot of savings but actually moves code around into new files and doesn't reduce the total size by much at all

[BUG] Task fails if `base` build fails

If the base build fails then the task fails, regardless of whether the current branch build is successful.

I would expect this to pass if the [current] build is valid, or at least provide an option to bypass this

Comments are not stripped from compressed files

JavaScript comments are not removed from the built files and contribute to reported file size. I think comments should be stripped to provide realistic data that reflects what a production build would do.

Better support for monorepos

In a monorepo one might use multiple actions on a PR to report changes on different modules.

  • If using comments, each of those actions will override/"update" the previous comment.
  • If using "use-check" the behaviour is wrong as well

Proposed solution:

  • Introduce an input that will dedup those comments (e.g. label or something). One could pass label="App 1", label="App2" (this could also be displayed in the final markdown for better UI/UX) which would additionally be used to dedup the comments.

Usage with Next.js?

next build generates a variety of file formats and using a single regex seems near impossible to match things properly. Here are some of the static build files Next.js creates:

.next/static/EWRdXUQq4dZmLtDf6_2AJ/pages/home.js
.next/static/chunks/018f516e3e474ffd4b3ae00965a7b7def9dd6244.aff82a9664f27ba4ff5a.js
.next/static/runtime/main-98aa32f16d7d5354970b.js
.next/static/runtime/polyfills-895c6aa13952c0a67e69.js

Any suggestions/ideas how to use the strip-hash regex or something else to get a normalized list of changed files?

Related question: is there a way to customize the output display of the action? Would be nice to have all assets collapsed by default including changed files.

Allow skipping install.

Using zero-install PnP with yarn doesn't play well when intalling using --frozen-lockfile.
Allow opting out of installing all together.

Don't mind doing the PR if it's ok.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.