Prevent workflow being skipped when using push paths

Hey,

Let’s say I have an action which runs a set of tests and lints on my codebase on push, but only for changes to JS files as below:

name: JS Unit Tests and lints
on:
  push:
    paths:
      - '**.js'

Let’s say a dev pushes some new JavaScript code which fails these tests - the workflow will fail as expected. Next time they push they push a change to a CSS file, and this workflow doesn’t run. My understanding of this reasoning is that the changeset is always for the latest commit. As a consequence an important workflow has been skipped.

How do we enforce that the tests should have passed without running the workflow on every push - other than not making use of the paths property? Is there a way to compare the branch to master rather than just on the latest change? So if my branch has changes to JavaScript files I want the paths test to force the workflow every time.

Or is there another/better approach? I could also have the tests run on merge and block the merge there but that’s not a good feedback loop for a dev.

Thanks.

I’m not sure if understand what you try to achieve. If someone breaks the JavaScript code and pushes it, then the workflow runs and fails as expected. The developer now knows that something is wrong and can fix the problem. In the meantime, another dev pushes a CSS change. Do you want the JS workflow to run and fail because there is a bad JavaScript code in the current state, even though the person who pushed a CSS change doesn’t have anything to do with this?

On a technical level, I think you want the workflow to indicate that there’s a problem with the JS code for as long as the problem exists, even if someone else pushes unrelated changes, but without running the JS unit tests and linter on every push. This sounds like it could be done with actions/cache and no push paths. So you would basically trigger the workflow on every push, but skip the unit test and linter part if it was executed before (and failed) for as long as the JS code doesn’t change. Then you would run these again. The cache key could be like ${{ runner.os }}-${{ hashFiles('**.js') }}. The cache action has an output cache-hit that tells you whether the cache is used.