ruby-on-railscirclecisprocketsrails-sprockets

New Rails 7 app with Sprockets can't find application.js file (Circle CI)


has anyone noticed that new Rails apps seem to fail on circleCI with this error:

Sprockets::Rails::Helper::AssetNotFound in Home#index
The asset "application.js" is not present in the asset pipeline.

steps to reproduce: rails new --javascript=esbuild so it uses JSBundling with ESbuild

• Install rspec

• configure CircleCI

• add app to your circle CI pipeline.

• Add a basic hello world controller that simply prints "Hello world"

• Add the root route to the hello world controller

• Add a spec:

require 'rails_helper'

describe "can load the homepage" do
  it "should load the homepage" do
    visit "/"
    expect(page).to have_content("Hello world")
  end
end

there’s a file in app/assets/config/manifest.js which tells Sprockets where to load assets from. I tried adding this

//= link_directory ../../javascript .js

(notice that the default location of the javascript folder is in app/ not in app/assets)

the app works fine locally and deploys to Heroku just fine, I only see this error on CircleCi. Anyone seen this before?

my CircleCI config looks like this:

version: 2.1 # Use 2.1 to enable using orbs and other features.


# Declare the orbs that we'll use in our config.
# read more about orbs: https://circleci.com/docs/2.0/using-orbs/
orbs:
  ruby: circleci/ruby@1.0
  node: circleci/node@2
  browser-tools: circleci/browser-tools@1.2.3

jobs:
  build: # our first job, named "build"

    docker:
      - image: cimg/ruby:3.1.2-browsers # use a tailored CircleCI docker image.
        auth:
          username: mydockerhub-user
          password: $DOCKERHUB_PASSWORD  # context / project UI env-var reference
      - image: redis:6.2.6

    steps:
      - checkout # pull down our git code.
      - ruby/install-deps # use the ruby orb to install dependencies
      # use the node orb to install our packages
      # specifying that we use `yarn` and to cache dependencies with `yarn.lock`
      # learn more: https://circleci.com/docs/2.0/caching/
      - node/install-packages:
          pkg-manager: yarn
          cache-key: "yarn.lock"
      - run:
          name: Build assets
          command: bundle exec rails assets:precompile

  test:  # our next job, called "test"
    parallelism: 1
    # here we set TWO docker images.
    docker:

      - image: cimg/ruby:3.1.2-browsers # this is our primary docker image, where step commands run.
        auth:
          username: mydockerhub-user
          password: $DOCKERHUB_PASSWORD  # context / project UI env-var reference
      - image: redis:6.2.6
      - image: circleci/postgres:9.5-alpine
        auth:
          username: mydockerhub-user
          password: $DOCKERHUB_PASSWORD  # context / project UI env-var reference
        environment: # add POSTGRES environment variables.
          POSTGRES_USER: circleci-demo-ruby
          POSTGRES_DB: VDQApp_test
          POSTGRES_PASSWORD: ""
    # environment variables specific to Ruby/Rails, applied to the primary container.
    environment:
      BUNDLE_JOBS: "3"
      BUNDLE_RETRY: "3"
      PGHOST: 127.0.0.1
      PGUSER: circleci-demo-ruby
      PGPASSWORD: ""
      RAILS_ENV: test
    # A series of steps to run, some are similar to those in "build".
    steps:
      - browser-tools/install-chrome
      - browser-tools/install-chromedriver
      - checkout
      - ruby/install-deps
      - node/install-packages:
          pkg-manager: yarn
          cache-key: "yarn.lock"
      # Here we make sure that the secondary container boots
      # up before we run operations on the database.
      - run:
          name: Wait for DB
          command: dockerize -wait tcp://localhost:5432 -timeout 1m
      - run:
          name: Load schema
          command: bin/rails db:schema:load RAILS_ENV=test
      # Run rspec in parallel
      - ruby/rspec-test

# We use workflows to orchestrate the jobs that we declared above.
workflows:
  version: 2
  build_and_test:     # The name of our workflow is "build_and_test"
    jobs:             # The list of jobs we run as part of this workflow.
      - build         # Run build first.
      - test:         # Then run test,
          requires:   # Test requires that build passes for it to run.
            - build   # Finally, run the build job.


Solution

  • Ok I figured this out.

    The Circle CI config must told to execute the esbuild, whih is done like so:

    esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds --public-path=assets
    

    that command lives in your yarn package script, so you can run it as yarn build

    In the .circleci/config file, look for the jobs > test > steps stanza

    You will want to add this step for yarn build after the step for node/install-packages

          - run:
              name: Yarn build
              command: yarn build
    
        steps:
          - browser-tools/install-chrome
          - browser-tools/install-chromedriver
          - checkout
          - ruby/install-deps
    
          - node/install-packages:
              pkg-manager: yarn
              cache-key: "yarn.lock"
    
          - run:
              name: yarn build
              command: yarn build
    
          # Here we make sure that the secondary container boots
          # up before we run operations on the database.
          - run:
              name: Wait for DB
              command: dockerize -wait tcp://localhost:5432 -timeout 1m
          - run:
              name: Load schema
              command: bin/rails db:schema:load RAILS_ENV=test
          # Run rspec in parallel
          - ruby/rspec-test
    
    

    thanks to @Archronic for this addition:

    Found the answer. jsbundling-rails enhances the assets:precompile rake task only for production. For test, it enhances test:prepare task. If you're not running test:prepare then it counts on you running yarn build to ensure assets are available in test.