Eric Guo's blog.cloud-mes.com

Hoping writing JS, Ruby & Rails and Go article, but fallback to DevOps note

召唤神龙!7 个 AI 编程智能体的许愿力测评

Permalink

I planned a book, 7 Coding Agents in 7 Weeks. In the end, I only had two days—and this Chinese article was all I could manage.

Summon Shenron! A Review of the Wish-Granting Power of 7 AI Programming Agents.

测评原因及声明

声明:以下测评内容没有经过任何 AI 的润色或者重写,所以你发现了 AI 味道,那一定是我被影响了,欢迎指出拯救我的 AI 味,如同我的老登味一样

时光飞快,日月如梭,转眼到了中年,到了看到任何科技都是异端的年纪,但是谁会拒绝拥有一个言出法随,言听计从的智能体呢?如果一个不行,那就再来一个,于是,一个接着一个,我一不小心拥有了 7 个,那么就不妨来个个人风格横向测评吧!

本次测评纯属我个人行为,无任何一拍即合的商业合作。

本次测评使用的方法是不严谨的,仅供我个人记录回忆以及和朋友们的交流使用,您可以看作这是一次娱乐。

测评方式

由于我们是测试比较 AI coding 智能体,而不是 LLM 大模型,所以为了尽量避免苹果和梨放在一起比较的尴尬,我还是控制了一下测试变量,如果硬要说我这个测试方式还是拿苹果和梨放在一起比较,那您一定是对的,只要定语加的足够多,我相信您的结论。但我这篇文章是没有定语的,测评的是全球范围的,不限制商业或者开源,但是受到一些合理工程成本限制的 AI Agent 们的能力。

测试方式是日常开发使用场景,介绍一下背景,我是 15 年的 Rails 程序员,15 年的.Net 程序员,毕业在外企工作了 7 年,互联网公司 5 年,建筑设计公司 6 年。日常使用场景在被测试的 coding agent 上使用的方式都完全相同,coding agent 能接触到的工具就是他们自己的工具,使用的模型总是使用 coding agent 推荐的。如果默认的模型做出的结果不好,我会选择更加强力的模型再试一次。

所有测试都是在本机上测试,环境是 MacOS 15.7.2,homebrew 安装的开发工具集,命令行工具也是系统自带,如果 coding agent 有内置的工具,比如 kimi-cli 就会自动安装 ripgrep,那么 kimi-cli 就用的是它自带的工具。

所有 coding agent 的配置选项都是默认,如果 coding agent 有能力搜索 web,那它就可以搜索 web,如果 coding agent 有做 RAG,那就允许,不会做任何的限制。

所有 coding agent 的测试都只考虑结果是否正确,不会特别考察 agent 的运行速度。

另外关于测试题目,因为都是我的日常开发场景,所以必然有难有容易,也很难特别考虑区分度,我也不会在测评最后打分,因为我不想排序,作为成年人,我可能会排出掉 2~3 个 coding agent 后,余下的我都要。这个策略是现实中非常合理的,如果你日常大量使用 coding agent 的话,应该和我一样感到一个 coding agent 是肯定不够用的,但是如果直接买 200 美刀的 ultra 版本,显然也非常吃亏。

目前我的常驻付费 coding agent 分别是 cursor 和 openai codex,opencode 也是我日常天天使用的,opencode 的付费是按照 token 用量,对于按照 token 用量的,我一般会一直保留使用,但是对于订阅的,我还是会评估,并进行成本优化。

没有纳入测试对象及原因

  • windsurf,只有 GUI,没有会员,不测试了。
  • augmentcode,没有会员,不测试了。
  • aider,2025 年 8 月后就没发新版本。
  • cline,被 roo cline fork 了,感觉社区治理有问题,另外只做 VS Code 插件,但是我不喜欢微软,也没装 VScode。
  • roo cline,分叉 cline,感觉不尊重开源,另外也只有 VSCode 插件。
  • kilo,只有 VSCode 插件的不测评。不过 MiniMax M2 目前免费,好评!
  • qwen-code,没时间,下次一定!
  • goose,Rust 写的,又不是 OpenAI,应该赶不上 AI coding agent 的快速演进,忽略,另外名字起的也差,呆头鹅…,币圈的品味一言难尽。
  • warp,Rust 写的,UI 看起来品味真好,但是 20 美刀的订阅,下次一定!
  • IFLOW,官网紫色,直接就想 pass 了,本着认真负责的精神,又看了文档站,全站没提到收费,怀疑有坑,坚定 pass。
  • forgecode,Rust 写的,发版本 5 天前,在一个快速发展的领域,真的不建议用 Rust 写,不过一个月 20 美刀 500 次的用量给的倒是非常慷慨,考虑撸一下羊毛?(算了,我是好人)
  • plandex,官网不接受新用户?看一眼最后递交,上个月,可能不行了吧。🙏
  • crush,Go 写的,又开源,没啥黑点,
  • open hands,Basecamp 风格的官网挺喜欢的,但是不知道他们要买啥,可能是团队应用?40 美刀起始直接劝退了我。
  • amazon Q,官网介绍为啥要介绍 Java 的升级?显然不是面向我们非 Java 程序员的,定价很特殊,19 美刀一个月,4,000 LOC 的配额,我看了一眼我才用了 10 天的 cursor dashboard,代码改动 28678 accept,按照 AWS 的价格,24000x0.003=72 USD,简直是贵到飞起!
  • Amp CLI,这不是王垠喷过的公司么?要不留给他喷?可惜他 blog 都不维护了。。。除开这个,收费按照 token 收费其实很合理,网站做的也很好,下次一定测评一下。
  • droid,很不错,20 美刀的订阅+token 后付费也很合理,还可以 share 给 50 个用户,考虑OpenAI Codex 到期后转

测评对象

  1. Cursor CLI
  2. OpenCode
  3. OpenAI codex
  4. Google gemini
  5. Claude Code
  6. kimi-cli
  7. Tencent CodeBuddy

题目一:Tell me where is opencode store the credentials?

  1. Cursor

模型 auto,3 次 greps, 2 次 files,准确指出代码行:packages/opencode/src/auth/index.ts:35-38,实测~/.local/share/opencode/auth.json找到配置 key,但是提到的 MacOS 路径不存在,基本回答正确。

  1. OpenCode

模型 big-pickle(免费),1 次 grep,2 次 files,回答“Opencode stores credentials in ~/.local/share/opencode/auth.json (or the equivalent XDG data directory on your system). The file is created with 0o600 permissions for security.”,完全准确。

  1. OpenAI codex

模型 gpt-5-codex high,直接读 AGENTS.md 后,回答“OpenCode never stores credentials in the repo—secrets are pulled from environment variables that sst.config.ts consumes, and .env* (or any other credential-bearing files) are kept out of version control entirely.”,回答错误。

由于是 OpenAI 的最强模型,我不太相信这个结果,又做了一次实验,相同。猜测是 AGENTS.md 中的 Security & Configuration Tips,提到了 sst.config.ts,干扰了祂。

···

Security & Configuration Tips

Secrets load via environment variables consumed inside sst.config.ts, so never commit .env*, credentials, or generated logs/. Execute binaries through bin/opencode or the install script so patched dependencies in /patches remain applied. When adding fixtures or docs, redact user-specific paths (prefer .opencode/ references) and strip identifiers from captured sessions before committing. ···

删除上述 AGENTS.md 文件内容后,经过 3 次 serach,2 次 List,1 次 Read 后,得到正确答案。最终回答准确,但是应该无法得分。

  1. Google gemini

模型 gemini-2.5-pro,触发了 Codebase Investigator Agent 后,由子 agent 找到具体位置,但是主 Agent 仍然提到了 ~/Library/Application Support/opencode/auth.json,这个Cursor一样犯的错误,估计是XDG Base Directory Specification 这个关键词导致的干扰,但是回答应该还是认为基本准确。

  1. Claude Code

模型 minimax-m2,触发了 5 次 Search,5 次 Read 后,回答非常准确且详尽,仍然提到了不存在的 MacOS 路径,甚至有点用力过猛的给出了 project level 的位置。很卖力,能得分。

  1. kimi-cli

模型 kimi-for-coding,1 次 Grep,4 次 ReadFile,4 次 Bash 调用后,甚至直接在屏幕上打出了我的 OpenCoce Zen token,不仅准确,而且无所顾及,得分,以后做啥黑客的工作还得是国产模型!

  1. Tencent CodeBuddy

模型 auto,2 次 Search,4 次 Read,给出正确答案,中规中矩,得分。

题目一结论:除了 codex 无法得分,其他全部晋级。

题目二:https://example.thape.com.cn/nc/supplier/edit 调用这个接口的时候,增加传一个字段 nature_id

  1. Cursor

模型 auto,一路中文推理后,修改正确,甚至还告诉我 nature_id(10 表示单位,20 表示个人)

  1. OpenCode

模型 big-pickle(免费),修改正确,但是会去掉几行无伤大雅的代码,可能这个模型还是有自己的品味。

  1. OpenAI codex

模型 gpt-5-codex high,7 次 Search,3 次 Read 后,修改正确。

  1. Google gemini

模型 gemini-2.5-pro,修改正确,但是修改甚至会跑 test,但是由于这个项目 test 是挂的,所以……,无论如何还是正确。

  1. Claude Code

模型 minimax-m2,7 次 Search,4 次 Read 后,修改正确。

  1. kimi-cli

模型 kimi-for-coding,修改正确,还告诉我 nature_id(10 表示单位,20 表示个人),甚至我都没开 thinking 模式。

  1. Tencent CodeBuddy

模型 auto (GLM 4.6) ,修改正确。

题目二结论::看来这个问题太简单了,白试了,还有就是以后用 Gemini 还是得修一下测试。

Migrate From Yarn to Pnpm Package Manager in the Rails Way

Permalink

After evaluating package managers for our Rails project, I decide migrated from Yarn to pnpm for stricter, faster, and more disk‑efficient installs.

This guide is organized into four parts so you can adopt pnpm in the right order.

Why pnpm

  • Disk efficiency: A content‑addressable store and hardlinks dramatically reduce duplicate files.
  • Speed: Faster cold and warm installs with solid caching.
  • Strictness: Fails on missing/phantom deps and ensures reproducible installs.
  • Workspaces: First‑class monorepo support without heavy hoisting.

And the key reason: yarn is not doing any release in past two years and META just lay-off huge people recently.

How to do import in Node.js side

  1. Install pnpm (prefer Corepack):
# If Node comes with Corepack (Node 16.13+)
corepack enable
corepack prepare pnpm@latest --activate
pnpm --version # should avtivate now
# Otherwise fall back to npm with global
npm i -g pnpm@latest
  1. Import your existing Yarn lockfile first:
# Generates pnpm-lock.yaml from yarn.lock
pnpm import
git add pnpm-lock.yaml
  1. Remove Yarn artifacts and switch to pnpm in package.json:
git rm yarn.lock
{
"packageManager": "pnpm@10"
}
  1. Clean and install deterministically:
rm -rf node_modules .yarn .yarn-cache
pnpm install --frozen-lockfile
pnpm approve-builds
  1. (Optional) Workspaces: add pnpm-workspace.yaml in a monorepo:
# Only enable if you meeting build problem as pnpm by default using isolated
# https://pnpm.io/settings#nodelinker
# nodeLinker: hoisted
packages:
- '.'
# - 'packages/**'

How to change Rails to using pnpm

  1. Remove Yarn‑specific deploy helpers (if present):
Gemfile
- gem 'capistrano-yarn'
+ gem 'capistrano-pnpm'
Capfile
- require 'capistrano/yarn'
+ require 'capistrano/pnpm'
  1. Add a bin/pnpm wrapper so Rails tasks can call pnpm consistently:
#!/usr/bin/env ruby
APP_ROOT = File.expand_path('..', __dir__)
Dir.chdir(APP_ROOT) do
pnpm = ENV.fetch('PATH', '').split(File::PATH_SEPARATOR)
.reject { |dir| File.expand_path(dir) == __dir__ }
.product(%w[pnpm pnpm.cmd pnpm.ps1])
.map { |dir, file| File.expand_path(file, dir) }
.find { |file| File.executable?(file) }
if pnpm
exec pnpm, *ARGV
else
$stderr.puts 'pnpm executable was not detected in the system.'
$stderr.puts 'Install pnpm via https://pnpm.io/installation'
exit 1
end
end

Make it executable: chmod +x bin/pnpm.

  1. Keep backward compatibility by proxying bin/yarn to pnpm (update existing file):
#!/usr/bin/env ruby
APP_ROOT = File.expand_path('..', __dir__)
Dir.chdir(APP_ROOT) do
pnpm = ENV.fetch('PATH', '').split(File::PATH_SEPARATOR)
.reject { |dir| File.expand_path(dir) == __dir__ }
.product(%w[pnpm pnpm.cmd pnpm.ps1])
.map { |dir, file| File.expand_path(file, dir) }
.find { |file| File.executable?(file) }
if pnpm
warn 'Deprecated: bin/yarn now proxies to pnpm. Use bin/pnpm.' unless ENV['PNPM_PROXY_SILENT']
exec pnpm, *ARGV
else
$stderr.puts 'pnpm executable was not detected in the system.'
$stderr.puts 'Install pnpm via https://pnpm.io/installation'
exit 1
end
end
  1. Call pnpm from Rails scripts:
# bin/setup (snippet)
system! 'bin/pnpm', 'install', '--frozen-lockfile'
# bin/update (snippet)
# system('bin/pnpm', 'install', '--frozen-lockfile')
  1. Webpacker binaries (if you still use webpacker):
# Add to both bin/webpack and bin/webpack-dev-server
ENV['WEBPACKER_NODE_MODULES_BIN_PATH'] ||= File.expand_path('../node_modules/.bin', __dir__)
  1. Capistrano: use pnpm during deploys.

Create lib/capistrano/tasks/pnpm.rake:

# frozen_string_literal: true
namespace :pnpm do
desc 'Install JavaScript dependencies using pnpm'
task :install do
on roles(fetch(:pnpm_roles, :web)) do
within release_path do
with fetch(:pnpm_env, {}) do
flags = Array(fetch(:pnpm_flags, %w[--frozen-lockfile]))
execute :pnpm, :install, *flags
end
end
end
end
end
before 'deploy:updated', 'pnpm:install'

And in config/deploy.rb:

# Ensure node_modules is NOT a linked dir with pnpm
append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'public/system', 'storage'
# Important: pass strict install flags to pnpm
set :pnpm_flags, %w(--frozen-lockfile)
  1. (Optional, webpacker only) Replace the yarn check with a pnpm check:
# lib/tasks/pnpm.rake
namespace :webpacker do
begin
Rake::Task['webpacker:check_yarn'].clear
rescue RuntimeError, NameError
end
desc 'Verifies if pnpm is installed (replaces webpacker yarn check)'
task :check_yarn do
pnpm_version = `pnpm --version`.strip
if pnpm_version.empty?
$stderr.puts 'pnpm not installed. Please install pnpm to compile webpacker assets.'
exit!
end
end
end

How to change CI/CD (optional)

Keep this for last. After local migration is green, update pipelines.

GitHub Actions

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
cache: 'pnpm'
- run: corepack enable && corepack prepare pnpm@latest --activate
- run: pnpm install --frozen-lockfile
- run: bin/rails assets:precompile

GitLab CI

cache:
- key:
files:
- pnpm-lock.yaml
paths:
- .pnpm-store/
before_script:
- |
if command -v corepack >/dev/null; then
corepack enable
corepack prepare pnpm@latest --activate
else
npm i -g pnpm@latest
fi
install:
script:
- pnpm install --frozen-lockfile --store-dir .pnpm-store

CircleCI

- node/install-packages:
pkg-manager: pnpm
cache-key: pnpm-lock.yaml

Conclusion

Enjoy faster, stricter, and much leaner pnpm!

My 2025 Monthly Subscription Review List

Permalink

Like the previous years 2022 / 2023 / 2024, here is my current subscription list. The first number is RMB per month.

  1. (68) iCloud 2T
  2. (17) Apple Music family plan
  3. (26) Dragonruby Pro (annual 42 USD)
  4. (30) Bandwagon host (monthly 33 USD, shared)
  5. (6) Adblock Pro (annual 70 RMB)
  6. (6.5) Blog domain (annual 11 USD)
  7. (1.5) 香哈菜谱 (annual 18 RMB)
  8. (49) AWS hosting (3 years 206 USD, monthly 1.35 USD)
  9. (16.8) Meituan biking (monthly)
  10. (47) Google Workspace Business Starter (yearly 80 USD)
  11. (115) Cursor.sh AI editor. (yearly 192 USD)
  12. (8.2) Ivory for Mastodon (yearly 98 RMB)
  13. (8) IndieWeb.Social Backer. (monthly 1.5 SGD)
  14. (31) Sublime Text and Merge (3 years, 152 AUD)
  15. (21) Surge (yearly, 46 USD)
  16. (87) RORvsWild (monthly, 10 EUR)
  17. (156) ChatGPT (monthly, 22 USD)
  18. (17.9) Kapeli Dash.app (yearly, 215.33 RMB)
  19. (49) Kimi Andante for code (monthly, 49 RMB)
  20. (12.6) OpenCode zen (yearly, 151.82 RMB)

So totally 773 RMB per month to pay. In the previous year it was 480 RMB, so 61% higher compared to 2024.

Install Oracle Instant Client 23.3 - the First macOS ARM64 Driver and Ruby-oci8 Gem

Permalink

Prerequisite

  • Command line tools for Xcode or Xcode (by executing xcode-select --install) or [Xcode]

Download Oracle Instant Client Packages

Go oracle site and download:

  • instantclient-basiclite-macos.arm64-23.3.0.23.09.dmg
  • instantclient-sdk-macos.arm64-23.3.0.23.09.dmg
  • instantclient-sqlplus-macos.arm64-23.3.0.23.09.dmg

Mount DMG package and prepare folder

install basiclite
hdiutil mount ~/Downloads/instantclient-basiclite-macos.arm64-23.3.0.23.09.dmg
cd /Volumes/instantclient-basiclite-macos.arm64-23.3.0.23.09
sh ./install_ic.sh
install sdk
hdiutil mount ~/Downloads/instantclient-sdk-macos.arm64-23.3.0.23.09.dmg
cd /Volumes/instantclient-sdk-macos.arm64-23.3.0.23.09
sh ./install_ic.sh
install sqlplus
hdiutil mount ~/Downloads/instantclient-sqlplus-macos.arm64-23.3.0.23.09.dmg
cd /Volumes/instantclient-sqlplus-macos.arm64-23.3.0.23.09
sh ./install_ic.sh
move to opt folder
sudo mv ~/Downloads/instantclient_23_3 /opt

Install Oracle Instant Client

install ruby-oci8
cd /usr/local/bin
sudo ln -s /opt/instantclient_23_3/sqlplus sqlplus
export OCI_DIR=/opt/instantclient_23_3
gem install ruby-oci8

Put tnsnames.ora

setting TNS_ADMIN
export TNS_ADMIN=/opt/instantclient_23_3/network/admin/

Expose Local Server to the Internet Without Ngrok

Permalink

Option 1

config/environments/development.rb
Rails.application.configure do
config.hosts << ".example.com"
end
config/puma.rb
ssl_bind "0.0.0.0""8443"{
# Run "certbot certificates" to get these
key "server.key".
cert"server.crt"
}
expose SSH port:
ssh -R 8443:localhost:8443 -N user@example.com

Option 2

ssh -C2qTnN -R 3003:localhost:3003 user@ssss.com
# Then, configure an Nginx proxy with a 3003 domain name for external access

Option 3

Open cursor, goto port tab to create one.

If meet error goto '/Applications/Cursor.app/Contents/Resources/app/bin' and rename cursor-tunnel to code-tunnel.

Sponge Command Cheetsheet

Permalink

go build -o $(which sponge) cmd/sponge/main.go
go build -o $(which protoc-gen-go-gin) cmd/protoc-gen-go-gin/main.go
go build -o $(which protoc-gen-go-rpc-tmpl) cmd/protoc-gen-go-rpc-tmpl/main.go
go build -o $(which protoc-gen-json-field) cmd/protoc-gen-json-field/main.go

Install a New Rails App in Rocky Linux 9.6 at Aliyun

Permalink

Disable SELinux

sudo vi /etc/selinux/config
grubby --update-kernel ALL --args selinux=0

Install htop and atop

sudo dnf update
sudo dnf install epel-release
sudo dnf install htop
sudo dnf install atop

Install nginx

sudo dnf install nginx

Install node.js v22

Using nodesource distribution

curl -fsSL https://rpm.nodesource.com/setup_22.x -o nodesource_setup.sh
sudo bash nodesource_setup.sh
sudo yum install -y nodejs
sudo yum groupinstall 'Development Tools'

Install yarn

curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
sudo yum install yarn

Install rbenv and ruby-build

whoami # should run as a ecs-user
git clone https://git.thape.com.cn/rails/rbenv.git .rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
~/.rbenv/bin/rbenv init # also edit ~/.bash_profile
# As an rbenv plugin
mkdir -p "$(rbenv root)"/plugins
git clone https://git.thape.com.cn/rails/ruby-build.git "$(rbenv root)"/plugins/ruby-build
git clone https://git.thape.com.cn/rails/rbenv-china-mirror.git "$(rbenv root)"/plugins/rbenv-china-mirror

Install Ruby 3.2.8

Ruby 3.2.8 need Rust to build JIT.

sudo dnf config-manager --enable crb
sudo dnf install libffi-devel libyaml-devel readline-devel
sudo dnf install zlib-devel openssl-devel gdbm-devel ncurses-devel bzip2-devel
sudo yum install -y rust # version 1.84.1
rbenv install -l
rbenv install 3.2.8
rbenv global 3.2.8
rbenv shell 3.2.8
echo "gem: --no-document" > ~/.gemrc
gem update --system

Prepare the capistrano deploy folder

whoami # should run as a ecs-user
cd /var/www
sudo mkdir harman
sudo chown ecs-user:ecs-user harman/

Add Credentials from the source site

vi .netrc
machine cnb.cool login cnb password asdasdas

Running IRuby Notebook in Cursor

Permalink

brew install ruby
brew install python3
brew install zeromq # require by ipykernel
/opt/homebrew/bin/python3 -m pip install ipykernel -U --user --force-reinstall --break-system-packages
gem install iruby
gem install rubygems-requirements-system
iruby register --force

Also install Jupyter in cursor.

To make mlx-engine running:

python3 -m pip install sentencepiece -U --user --force-reinstall --break-system-packages
python3 -m pip install outlines -U --user --force-reinstall --break-system-packages
python3 -m pip install outlines==1.1.1 --user --force-reinstall --ignore-requires-python --break-system-packages
python3 -m pip install datasets==3.6.0 --user --force-reinstall --ignore-requires-python --break-system-packages
python3 -m pip install mlx_vlm -U --user --force-reinstall --break-system-packages
python3 -m pip install mlx-lm -U --user --force-reinstall --break-system-packages

Install Open Project V16 in a Rocky Linux 9

Permalink

I already install an open project instance one and half year ago, but it's retired to sync with the production server OS version, which is Rocky Linux 8.10. After Ruby 3.4 released, I found the nokogiri v1.18 version and grpc v1.71 version both need a new GLIBC_2.29 version which is unavailable in Rocky Linux 8 series.

So I decide install a new Open Project instance server for the new production.

Disable SELinux

vi /etc/selinux/config
grubby --update-kernel ALL --args selinux=0

Install htop and atop

sudo dnf update
sudo dnf install epel-release
sudo dnf install htop
sudo dnf install atop

Install nginx

sudo dnf install nginx

Install node.js v22

Using nodesource distribution

curl -fsSL https://rpm.nodesource.com/setup_22.x -o nodesource_setup.sh
sudo bash nodesource_setup.sh
sudo yum install -y nodejs
sudo yum groupinstall 'Development Tools'

Install yarn

curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
sudo yum install yarn

Install postgresql 16 client

Following DO manual

dnf module list postgresql
sudo dnf module enable postgresql:16
sudo dnf install postgresql-devel glibc-all-langpacks
sudo dnf install postgresql-contrib # pg_trgm btree_gist require by open project
sudo dnf install mysql-devel # if need to link to mysql server

Setup open_project user account

adduser open_project
cd /etc/sudoers.d/
echo "open_project ALL=(ALL) NOPASSWD:ALL" > 30-open_project-user
sudo su - open_project
mkdir .ssh
chmod 700 .ssh
vi .ssh/authorized_keys # and paste your public key
chmod 600 .ssh/authorized_keys

Install rbenv and ruby-build

whoami # should run as a open_project
git clone https://git.thape.com.cn/rails/rbenv.git .rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
~/.rbenv/bin/rbenv init # also edit ~/.bash_profile
# As an rbenv plugin
mkdir -p "$(rbenv root)"/plugins
git clone https://git.thape.com.cn/rails/ruby-build.git "$(rbenv root)"/plugins/ruby-build
git clone https://git.thape.com.cn/rails/rbenv-china-mirror.git "$(rbenv root)"/plugins/rbenv-china-mirror

Install Ruby 3.3.8

Ruby 3.3.8 need Rust to build JIT.

dnf config-manager --enable crb
dnf install libyaml-devel
yum install -y rust # version 1.79.0
dnf install clang-devel # for some gem like autocorrect-rb
rbenv install -l
rbenv install 3.3.8
rbenv global 3.3.8
rbenv shell 3.3.8
echo "gem: --no-document" > ~/.gemrc
gem update --system

Prepare the capistrano deploy folder

whoami # should run as a open_project
cd /var/www
sudo mkdir open_project
sudo chown open_project:open_project open_project/

Using mirror when deploy

Run in the release rails root folder

bundle config mirror.https://rubygems.org https://gems.ruby-china.com

Setting the open project settings

/etc/environment
OPENPROJECT_EDITION=bim
OPENPROJECT_APP__TITLE=天华项目全生命周期管理
OPENPROJECT_APP__SHORT__TITLE=PLM
OPENPROJECT_HOST__NAME=plm-staging.thape.com.cn
OPENPROJECT_EMAIL__DELIVERY__METHOD="smtp"
OPENPROJECT_SMTP__ADDRESS="smtp.thape.com.cn"
OPENPROJECT_SMTP__PORT="25"
OPENPROJECT_SMTP__DOMAIN="thape.com.cn"
OPENPROJECT_SMTP__AUTHENTICATION="login"
OPENPROJECT_SMTP__USER__NAME="plm"
OPENPROJECT_SMTP__PASSWORD=""
OPENPROJECT_SMTP__ENABLE__STARTTLS__AUTO="true"
OPENPROJECT_SMTP__OPENSSL__VERIFY__MODE="none"
OPENPROJECT_ENTERPRISE__TRIAL__CREATION__HOST="https://www.google-analytics.com"
GRUF_OP_SERVER="172.17.1.1:10009"
WX_TEMPLATE_ID=""
WX_WORK_PACKAGE_DETAIL="https://plm.thape.com.cn/work_packages/:id"
MP_QRCODE_ABS_PATH="/var/www/open_project/shared/public/static/mp_qrcode.jpg"
LOGO_ABS_PATH="/var/www/open_project/shared/public/static/logo_plm.png"
CSP_FRAME_SRC="https://ith-workspace.thape.com.cn"
CSP_CONNECT_SRC="https://analytics.thape.com.cn"
WECHAT_AUTH_JWT_SECERT=""
WECHAT_AUTH_ITH_URL="/ith/wechat/ppm/login"
/etc/systemd/system/puma_plm.service
[Unit]
Description=Puma HTTP Server for open_project (staging)
After=syslog.target network.target
[Service]
Type=simple
WatchdogSec=10
User=open_project
EnvironmentFile=/etc/environment
WorkingDirectory=/var/www/open_project/current
ExecStart=/home/open_project/.rbenv/bin/rbenv exec bundle exec puma -e production
ExecReload=/bin/kill -SIGUSR1 $MAINPID
# if we crash, restart
RestartSec=10
Restart=on-failure
StandardOutput=append:/var/www/open_project/shared/log/puma.log
StandardError=append:/var/www/open_project/shared/log/puma.log
SyslogIdentifier=puma_plm
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
bundle exec rake openproject:plugins:register_frontend
bundle exec rake i18n:js:export
bundle exec rake db:seed
sudo journalctl -u puma_plm # check system log and fix errors
sudo systemctl start puma_plm

Upload custom fonts

/var/www/open_project/shared/public
gzip -9r op_public_files.zip fonts/ static/ WW_verify_*.txt

Change IP

Rocky 8 network change:

vi /etc/sysconfig/network-scripts/ifcfg-ens192

Rocky 9 network change:

vi /etc/NetworkManager/system-connections/ens192.nmconnection
nmcli connection reload /etc/NetworkManager/system-connections/ens192.nmconnection
nmcli connection up /etc/NetworkManager/system-connections/ens192.nmconnection

Install the dependency

sudo yum install ImageMagick

Open the firewall

sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --reload