Skip to content

Commit

Permalink
feat: use npm for managing js packages
Browse files Browse the repository at this point in the history
  • Loading branch information
G-Rath committed Nov 24, 2024
1 parent f9be057 commit 1c237f5
Show file tree
Hide file tree
Showing 19 changed files with 72 additions and 155 deletions.
34 changes: 6 additions & 28 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version-file: '.node-version'
cache: 'yarn'
- run: yarn install
- run: yarn run format-check
cache: 'npm'
- run: npm ci
- run: npm run format-check

rubocop:
permissions:
Expand Down Expand Up @@ -79,24 +79,6 @@ jobs:
# how many fail)
fail-fast: false
matrix:
js_package_manager:
- name: npm
installer: npm
- name: yarn_berry
installer: yarn
linker: pnp
- name: yarn_berry
installer: yarn
linker: node-modules
- name: yarn_berry
installer: yarn
linker: pnpm
- name: yarn_classic
installer: yarn
- name: pnpm
installer: pnpm
- name: bun
installer: bun
variant:
- name: defaults
config_path: 'ackama_rails_template.config.yml'
Expand Down Expand Up @@ -173,8 +155,8 @@ jobs:
with:
node-version-file: '.node-version'

- name: install package manager
run: npm i -g ${{ matrix.js_package_manager.installer }}
- name: Install latest version of npm
run: npm i -g npm

# We don't cache gems or JS packages because we are actually testing how
# installation and setup works in this project so, while caching would
Expand All @@ -192,8 +174,7 @@ jobs:
git config --global user.email "[email protected]"
git config --global user.name "Your Name"
# prettier-ignore
- run: ./ci/bin/create-fake-js-package-managers ${{ matrix.js_package_manager.installer }}
- run: ./ci/bin/create-fake-js-package-managers npm

- name: Run CI script
env:
Expand All @@ -207,7 +188,4 @@ jobs:
PGUSER: postgres
PGPASSWORD: postgres
PGHOST: localhost
PACKAGE_JSON_FALLBACK_MANAGER: ${{ matrix.js_package_manager.name }}
PACKAGE_JSON_YARN_BERRY_LINKER:
${{ matrix.js_package_manager.linker }}
run: ./ci/bin/build-and-test
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Where possible we stick to Rails defaults.

- General
- [puma](https://github.com/puma/puma) as application server
- [Yarn](https://yarnpkg.com/) for managing JS packages
- [npm](https://www.npmjs.com/) for managing JS packages
- PostgreSQL as database. This template only supports PostgreSQL.
- A much-improved `bin/setup` script
- Install [dotenv](https://github.com/bkeepers/dotenv)
Expand Down Expand Up @@ -155,7 +155,7 @@ our other templates:
Before running this template, you must have the following installed on your
machine:

- Yarn v1.21.0 or later
- NPM v10.0.0 or later
- Rails 7.1.x

The following are not strictly required to run the template but you will need it
Expand Down
38 changes: 38 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

74 changes: 5 additions & 69 deletions template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -264,67 +264,7 @@ def apply_prettier_all_over
git commit: ". -m 'Run prettier one last time'"
end

# Sets Yarn Berry up in the project directory by initializing it with what is probably Yarn Classic.
#
# This is required as the Berry binary is actually downloaded and committed to the codebase, and
# the global yarn command passes through to it when detected (even if its Yarn Classic).
#
# This also requires us to temporarily create a package.json as otherwise Yarn Berry will
# look up the file tree and initialize itself in every directory that has a yarn.lock
def setup_yarn_berry
# safeguard against parent directories having a yarn.lock
File.write("package.json", "{}") unless File.exist?("package.json")

run "yarn init -2"
run "yarn config set enableGlobalCache true"
run "yarn config set nodeLinker #{ENV.fetch("PACKAGE_JSON_YARN_BERRY_LINKER", "node-modules")}"

ignores = <<~YARN
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
YARN
File.write(".gitignore", ignores, mode: "a")

# this will be properly (re)created later
File.unlink("package.json")
end

# Bun uses a binary-based lockfile which cannot be parsed by shakapacker or
# osv-detector, so we want to configure bun to always write a yarn.lock
# in addition so that such tools can check it
def setup_bun
File.write("bunfig.toml", <<~TOML)
[install.lockfile]
print = "yarn"
TOML
end

def add_yarn_package_extension_dependency(name, dependency)
return unless File.exist?(".yarnrc.yml")

require "yaml"

yarnrc = YAML.load_file(".yarnrc.yml")

yarnrc["packageExtensions"] ||= {}
yarnrc["packageExtensions"]["#{name}@*"] ||= {}
yarnrc["packageExtensions"]["#{name}@*"]["dependencies"] ||= {}
yarnrc["packageExtensions"]["#{name}@*"]["dependencies"][dependency] = "*"

File.write(".yarnrc.yml", yarnrc.to_yaml)
end

def package_json
if @package_json.nil?
setup_yarn_berry if ENV.fetch("PACKAGE_JSON_FALLBACK_MANAGER", nil) == "yarn_berry"
setup_bun if ENV.fetch("PACKAGE_JSON_FALLBACK_MANAGER", nil) == "bun"
end

@package_json ||= PackageJson.new
end

Expand All @@ -346,8 +286,7 @@ def build_engines_field(existing)
node_version = File.read("./.node-version").strip

existing.merge({
"node" => "^#{node_version}",
"yarn" => "^1.0.0"
"node" => "^#{node_version}"
})
end

Expand All @@ -361,26 +300,23 @@ def cleanup_package_json
}
end

# TODO: this doesn't work when using pnpm even though it shouldn't matter? anyway, replace with 'exec' support
# run "npx -y sort-package-json"

# ensure the lockfile is up to date with any changes we've made to package.json
package_json.manager.install!
end

# Adds the given <code>packages</code> as dependencies using <code>yarn add</code>
# Adds the given <code>packages</code> as dependencies using the preferred package manager
#
# @param [Array<String>] packages
def yarn_add_dependencies(packages)
def add_js_dependencies(packages)
puts "adding #{packages.join(" ")} as dependencies"

package_json.manager.add!(packages)
end

# Adds the given <code>packages</code> as devDependencies using <code>yarn add --dev</code>
# Adds the given <code>packages</code> as devDependencies using the preferred package manager
#
# @param [Array<String>] packages
def yarn_add_dev_dependencies(packages)
def add_js_dev_dependencies(packages)
puts "adding #{packages.join(" ")} as dev dependencies"

package_json.manager.add!(packages, type: :dev)
Expand Down
8 changes: 0 additions & 8 deletions variants/accessibility/spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,3 @@
Lighthouse::Matchers.chrome_flags = %w[headless=new no-sandbox]
OPTIONS
end

if File.exist?(".yarnrc.yml")
insert_into_file "spec/rails_helper.rb", after: /# Lighthouse Matcher options\n/ do
<<~OPTIONS
Lighthouse::Matchers.lighthouse_cli = "yarn run lighthouse"
OPTIONS
end
end
2 changes: 1 addition & 1 deletion variants/accessibility/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
apply "spec/system/home_feature_spec.rb"
copy_file "spec/support/shared_examples/an_accessible_page.rb"

yarn_add_dev_dependencies %w[lighthouse]
add_js_dev_dependencies %w[lighthouse]
7 changes: 2 additions & 5 deletions variants/backend-base/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ RUN apt-get update -qq &&\
/usr/share/locales \
/var/cache/apt/archives

# Use NPM to install Yarn.
RUN npm install -g yarn

# Install gem and NPM dependencies. These are baked into the image so the image can run
# standalone provided valid configuration. When running in docker-compose, these
# dependencies are stored in a volume so the image does not need rebuilding when the
Expand All @@ -56,10 +53,10 @@ USER deploy

# Add just the dependency manifests before installing.
# This reduces the chance that bundler or NPM will get a cold cache because some kind of application file changed.
ADD Gemfile* package.json yarn.lock /usr/src/app/
ADD Gemfile* package.json package-lock.json /usr/src/app/
WORKDIR /usr/src/app
RUN bundle check || bundle install &&\
yarn install --frozen-lockfile
npm ci

# Add all application code to /usr/src/app and set this as the working directory
# of the container
Expand Down
4 changes: 2 additions & 2 deletions variants/frontend-base-typescript/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ def rename_js_file_to_ts(file)
node@18
].map { |name| "@types/#{name}" }

yarn_add_dependencies types_packages + %w[@babel/preset-typescript typescript]
yarn_add_dev_dependencies %w[
add_js_dependencies types_packages + %w[@babel/preset-typescript typescript]
add_js_dev_dependencies %w[
@typescript-eslint/eslint-plugin@7
@typescript-eslint/parser@7
]
Expand Down
6 changes: 2 additions & 4 deletions variants/frontend-base/js-lint/template.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# Javascript code linting and formatting
# ######################################

add_yarn_package_extension_dependency("eslint-plugin-prettier", "eslint-config-prettier")

yarn_add_dev_dependencies %w[
add_js_dev_dependencies %w[
eslint@8
eslint-config-ackama
eslint-plugin-node
Expand Down Expand Up @@ -54,7 +52,7 @@
end

# SCSS Linting
yarn_add_dev_dependencies %w[
add_js_dev_dependencies %w[
postcss
stylelint
stylelint-scss
Expand Down
2 changes: 1 addition & 1 deletion variants/frontend-base/sentry/template.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Setup Sentry
# ############

yarn_add_dependencies %w[@sentry/browser dotenv-webpack]
add_js_dependencies %w[@sentry/browser dotenv-webpack]

prepend_to_file "app/frontend/packs/application.js", "import * as Sentry from '@sentry/browser';"

Expand Down
4 changes: 2 additions & 2 deletions variants/frontend-base/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
gsub_file! "app/views/layouts/application.html.erb", "<body>", body_open_tag_with_img_example, force: true

# shakapacker will automatically configure webpack to use these so long as the dependencies are present
yarn_add_dependencies %w[
add_js_dependencies %w[
css-loader
css-minimizer-webpack-plugin
mini-css-extract-plugin
Expand All @@ -104,7 +104,7 @@
]

# Setup Turbo
yarn_add_dependencies %w[
add_js_dependencies %w[
@hotwired/turbo-rails
]
prepend_to_file "app/frontend/packs/application.js" do
Expand Down
2 changes: 1 addition & 1 deletion variants/frontend-bootstrap-typescript/template.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
source_paths.unshift(File.dirname(__FILE__))

yarn_add_dependencies %w[@types/bootstrap]
add_js_dependencies %w[@types/bootstrap]

rename_js_file_to_ts "app/frontend/js/bootstrap"
2 changes: 1 addition & 1 deletion variants/frontend-bootstrap/template.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
source_paths.unshift(File.dirname(__FILE__))

yarn_add_dependencies(["bootstrap", "@popperjs/core"])
add_js_dependencies(["bootstrap", "@popperjs/core"])

copy_file "app/frontend/js/bootstrap.js", force: true
insert_into_file "app/frontend/packs/application.js", "import '../js/bootstrap';", before: 'import "../stylesheets/application.scss";'
Expand Down
2 changes: 1 addition & 1 deletion variants/frontend-react-typescript/template.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
source_paths.unshift(File.dirname(__FILE__))

package_json.manager.remove!(["prop-types"])
yarn_add_dependencies %w[@types/react @types/react-dom]
add_js_dependencies %w[@types/react @types/react-dom]

rename_js_file_to_ts "app/frontend/packs/server_rendering"

Expand Down
6 changes: 2 additions & 4 deletions variants/frontend-react/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,20 @@

run "rails generate react:install"

add_yarn_package_extension_dependency("@testing-library/user-event", "@testing-library/dom")

# prefer importing from the more specific package for consistency
gsub_file! "app/frontend/test/stimulus/controllers/add_class_controller.test.js",
"'@testing-library/dom'",
"'@testing-library/react'"

yarn_add_dependencies %w[
add_js_dependencies %w[
@babel/preset-react
babel-plugin-transform-react-remove-prop-types
react
react-dom
prop-types
]

yarn_add_dev_dependencies %w[
add_js_dev_dependencies %w[
@testing-library/react
eslint-plugin-react
eslint-plugin-react-hooks
Expand Down
11 changes: 2 additions & 9 deletions variants/frontend-stimulus-typescript/template.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
source_paths.unshift(File.dirname(__FILE__))

add_yarn_package_extension_dependency("@testing-library/jest-dom", "@types/aria-query")
add_yarn_package_extension_dependency("ts-jest", "@jest/transform")
add_yarn_package_extension_dependency("ts-jest", "@jest/types")
add_yarn_package_extension_dependency("@jest/test-result", "jest-haste-map")
add_yarn_package_extension_dependency("@jest/test-result", "jest-resolve")
add_yarn_package_extension_dependency("jest-cli", "@types/yargs")

yarn_add_dependencies ["@babel/plugin-transform-typescript"]
yarn_add_dev_dependencies [
add_js_dependencies ["@babel/plugin-transform-typescript"]
add_js_dev_dependencies [
"@types/jest@#{JEST_MAJOR_VERSION}",
"ts-jest@#{JEST_MAJOR_VERSION}",
"ts-node"
Expand Down
Loading

0 comments on commit 1c237f5

Please sign in to comment.