Eric Guo's blog.cloud-mes.com

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

Install Gitea 1.21.3 From Source Code Into Rocky Linux 9

Permalink

Install dependency

Install htop and atop

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

Node.js v18

Using nodesource distribution

curl -fsSL https://rpm.nodesource.com/setup_18.x | bash -
dnf install -y nodejs
dnf 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

Go 1.20

Rocky Linux 9 including golang 1.20.

dnf install golang

Compile

Largely following official guide

Disable SELinux

vi /etc/selinux/config

Clone and build

git clone https://git.thape.com.cn/go-gitea/gitea.git
git checkout v1.21.3
npm config set registry https://registry.npmmirror.com/ --global
npm -g install webpack
TAGS="bindata" make build

Install Gitea

Install dependency

yum install redis
yum install memcached

Create git user

groupadd --system git
adduser \
--system \
--shell /bin/bash \
--comment 'Git Version Control' \
--gid git \
--home-dir /home/git \
--create-home \
git

Create required directory structure

Don't forget change back to more strict setting.

mkdir -p /var/lib/gitea/{custom,data,log}
chown -R git:git /var/lib/gitea/
chmod -R 750 /var/lib/gitea/
mkdir /etc/gitea
chown root:git /etc/gitea
chmod 770 /etc/gitea

Create DB and DB user

sudo su - postgres
createuser gitea_t --pwprompt
psql
ALTER ROLE gitea_t LOGIN;
CREATE DATABASE gitea_staging WITH ENCODING='UTF8' OWNER=gitea_t;
logout
vi /var/lib/pgsql/16/data/pg_hba.conf
# TYPE DATABASE USER ADDRESS METHOD
host gitea_staging gitea_t 0.0.0.0/0 scram-sha-256

Reload conf without restart DB

sudo su - postgres
/usr/pgsql-16/bin/pg_ctl reload

Open port to access and configure

sudo firewall-cmd --zone=public --add-port=3000/tcp
sudo firewall-cmd --zone=public --add-port=3000/tcp --permanent
sudo firewall-cmd --reload
sudo su - git
cd /var/lib/gitea/
gitea web -c /etc/gitea/app.ini

And open your server like http://172.16.1.47:3000 to configure

Binding to 443 and using https

Should following document, but if found cmd/web.go:353:listen() [E] Failed to start server: listen tcp 0.0.0.0:443: bind: permission denied error try below:

sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/gitea

Create DB ReadOnly User

createuser gitea_t_read --pwprompt
psql
ALTER ROLE gitea_t_read LOGIN;
GRANT USAGE ON SCHEMA public TO gitea_t_read;
SELECT 'GRANT SELECT ON ' || tablename || ' TO gitea_t_read;'
FROM pg_catalog.pg_tables
WHERE schemaname = 'public' AND tableowner = 'gitea_t';

Upgrade Gitea

cd /usr/local/bin/
wget https://github.com/go-gitea/gitea/releases/download/v1.21.8/gitea-1.21.8-linux-amd64.xz
xz -d gitea-1.21.8-linux-amd64.xz
systemctl stop gitea
systemctl status gitea
mv gitea-1.21.8-linux-amd64 gitea
chmod +x gitea
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/gitea
systemctl start gitea

Deploy Rails 7.1 and AnyCable 1.4 With RPC Services in the Existing CentOS 7

Permalink

I'm using the same server as post mention, to deploy the pgac_demo project.

Setup pgac user account

adduser pgac
gpasswd -a pgac wheel
cd /etc/sudoers.d
echo "pgac ALL=(ALL) NOPASSWD:ALL" > 97-pgac-user
sudo su - pgac
mkdir .ssh
chmod 700 .ssh
vi .ssh/authorized_keys
chmod 600 .ssh/authorized_keys

Install rbenv and ruby-build

cd # as a pgac
git clone https://github.com/rbenv/rbenv .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://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
git clone https://github.com/andorchen/rbenv-china-mirror.git "$(rbenv root)"/plugins/rbenv-china-mirror

Install Ruby 3.2.2

scl enable devtoolset-7 bash
rbenv install -l
rbenv install 3.2.2
rbenv global 3.2.2
rbenv shell 3.2.2
echo "gem: --no-document" > ~/.gemrc

create deploy folder

cd /var/www
sudo mkdir pgac
sudo chown pgac:pgac pgac/

The extra file for capistrano

The puma file which will lauch puma via system service.

/var/www/pgac/shared/puma.rb
#!/usr/bin/env puma
directory '/var/www/pgac/current'
rackup "/var/www/pgac/current/config.ru"
environment 'production'
tag ''
pidfile "/var/www/pgac/shared/tmp/pids/puma.pid"
state_path "/var/www/pgac/shared/tmp/pids/puma.state"
stdout_redirect '/var/www/pgac/shared/log/puma_access.log', '/var/www/pgac/shared/log/puma_error.log', true
threads 0,16
bind 'unix:///var/www/pgac/shared/tmp/sockets/puma.sock'
workers 0
restart_command 'bundle exec puma'
prune_bundler
on_restart do
puts 'Refreshing Gemfile'
ENV["BUNDLE_GEMFILE"] = ""
end

The systemd service file.

/etc/systemd/system/puma_pgac.service
# This file tells systemd how to run Puma as a 24/7 long-running daemon.
#
# Customize this file based on your bundler location, app directory, etc.
# Customize and copy this into /usr/lib/systemd/system (CentOS) or /lib/systemd/system (Ubuntu).
# Then run:
# - systemctl enable puma_pgac
# - systemctl {start,stop,restart} puma_pgac
#
#
# Use `journalctl -u puma_pgac -rn 100` to view the last 100 lines of log output.
#
[Unit]
Description=Puma HTTP Server for pgac (production)
After=syslog.target network.target
[Service]
Type=simple
WatchdogSec=10
User=pgac
Environment=CABLE_URL=wss://pgac.redwoodjs.cn:3334/cable
WorkingDirectory=/var/www/pgac/current
ExecStart=/home/pgac/.rbenv/bin/rbenv exec bundle exec --keep-file-descriptors puma -C /var/www/pgac/shared/puma.rb
ExecReload=/bin/kill -USR1 $MAINPID
# if we crash, restart
RestartSec=10
Restart=on-failure
StandardOutput=append:/var/www/pgac/shared/log/puma.log
StandardError=append:/var/www/pgac/shared/log/puma.log
SyslogIdentifier=puma_pgac
[Install]
WantedBy=multi-user.target

The nginx conf files.

/etc/nginx/conf.d/pgac.conf
upstream puma_pgac_production {
server unix:/var/www/pgac/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
if ($host = pgac.redwoodjs.cn) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name pgac.redwoodjs.cn;
return 301 https://$host$1$request_uri;
}
server {
listen 443 ssl http2; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/pgac.redwoodjs.cn/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/pgac.redwoodjs.cn/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
server_name pgac.redwoodjs.cn;
root /var/www/pgac/current/public;
try_files $uri/index.html $uri @puma_pgac_production;
client_max_body_size 4G;
keepalive_timeout 10;
error_page 500 502 504 /500.html;
error_page 503 @503;
location @puma_pgac_production {
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://puma_pgac_production;
# limit_req zone=one;
access_log /var/www/pgac/shared/log/nginx.access.log;
error_log /var/www/pgac/shared/log/nginx.error.log;
}
location ~ (/manifest.json|/favicon.ico|/*.txt|/*.png) {
access_log off;
expires 3d;
gzip_static on;
add_header Cache-Control public;
}
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
location = /50x.html {
root html;
}
location = /404.html {
root html;
}
location @503 {
error_page 405 = /system/maintenance.html;
if (-f $document_root/system/maintenance.html) {
rewrite ^(.*)$ /system/maintenance.html break;
}
rewrite ^(.*)$ /503.html break;
}
if ($request_method !~ ^(GET|HEAD|PUT|PATCH|POST|DELETE|OPTIONS)$ ){
return 405;
}
if (-f $document_root/system/maintenance.html) {
return 503;
}
}

The systemd files for AnyCable Go/RPC service

Large following the AnyCable deployment document

Using redis as broadcast_adapter

/etc/systemd/system/pgac-anycable-rpc.service
[Unit]
Description=AnyCable gRPC Server for pgac
After=syslog.target network.target
[Service]
Type=simple
Environment=RAILS_ENV=production
Environment=ANYCABLE_REDIS_URL=redis://localhost:6379/5
Environment=ANYCABLE_REDIS_CHANNEL=__anycable__
WorkingDirectory=/var/www/pgac/current
ExecStart=/home/pgac/.rbenv/bin/rbenv exec bundle exec anycable
ExecStop=/bin/kill -TERM $MAINPID
User=pgac
RestartSec=9
Restart=on-failure
[Install]
WantedBy=multi-user.target

The anycable-go can download from release page

/etc/systemd/system/pgac-anycable-go.service
[Unit]
Description=anycable-go for pgac
After=syslog.target network.target
[Service]
Type=simple
Environment=ANYCABLE_HOST=pgac.redwoodjs.cn
Environment=ANYCABLE_PORT=3334
Environment=ANYCABLE_PATH=/cable
Environment=ANYCABLE_REDIS_URL=redis://localhost:6379/5
Environment=ANYCABLE_REDIS_CHANNEL=__anycable__
Environment=ANYCABLE_METRICS_HTTP=/metrics
WorkingDirectory=/var/www/pgac/current
ExecStart=/usr/local/bin/anycable-go --ssl_cert=/etc/letsencrypt/live/pgac.redwoodjs.cn/cert.pem --ssl_key=/etc/letsencrypt/live/pgac.redwoodjs.cn/privkey.pem
ExecStop=/bin/kill -TERM $MAINPID
User=pgac
LimitNOFILE=16384 # increase open files limit (see OS Tuning guide)
Restart=on-failure
[Install]
WantedBy=multi-user.target

Using http as broadcast_adapter

/etc/systemd/system/pgac-anycable-rpc.service
[Unit]
Description=AnyCable gRPC Server for pgac
After=syslog.target network.target
[Service]
Type=simple
Environment=RAILS_ENV=production
WorkingDirectory=/var/www/pgac/current
ExecStart=/home/pgac/.rbenv/bin/rbenv exec bundle exec anycable
ExecStop=/bin/kill -TERM $MAINPID
User=pgac
RestartSec=9
Restart=on-failure
[Install]
WantedBy=multi-user.target
/etc/systemd/system/pgac-anycable-go.service
[Unit]
Description=anycable-go for pgac
After=syslog.target network.target
[Service]
Type=simple
Environment=ANYCABLE_HOST=pgac.redwoodjs.cn
Environment=ANYCABLE_PORT=3334
Environment=ANYCABLE_PATH=/cable
Environment=ANYCABLE_METRICS_HTTP=/metrics
WorkingDirectory=/var/www/pgac/current
ExecStart=/usr/local/bin/anycable-go --ssl_cert=/etc/letsencrypt/live/pgac.redwoodjs.cn/cert.pem --ssl_key=/etc/letsencrypt/live/pgac.redwoodjs.cn/privkey.pem --broadcast_adapter=http --rpc_impl=grpc
ExecStop=/bin/kill -TERM $MAINPID
User=pgac
LimitNOFILE=16384 # increase open files limit (see OS Tuning guide)
Restart=on-failure
[Install]
WantedBy=multi-user.target

Install Unleash Feature Flag Management OSS Software on Rocky Linux

Permalink

Unleash only depend on postgresql and recommand installation method including Docker/Docker-compose and pure Node.js. I using pm2 to do the daemon job and using a postgresql server seperatedly.

Install htop and atop

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

Setup unleash user account

adduser unleash
sudo su - unleash
mkdir .ssh
chmod 700 .ssh
vi .ssh/authorized_keys # and paste your public key
chmod 600 .ssh/authorized_keys

Install nginx

sudo dnf install nginx

Install node.js v18

Using nodesource distribution

curl -fsSL https://rpm.nodesource.com/setup_18.x | bash -
yum install -y nodejs
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

Disable firewall

firewall-cmd --zone=public --add-port=4242/tcp
firewall-cmd --permanent --zone=public --add-port=4242/tcp
firewall-cmd --reload
systemctl restart firewalld

Install Unleash

sudo su - unleash
git clone https://git.thape.com.cn/Eric-Guo/unleash.git
yarn
yarn run build

Run Unleash

node eric_server.js
eric_server
const unleash = require('./unleash/dist/lib/server-impl');
unleash
.start({
db: {
ssl: false,
host: '172.17.1.66',
port: 5432,
database: 'unleash_prod',
user: 'unleash',
password: 'password',
},
server: {
port: 4242,
unleashUrl: 'https://unleash.thape.com.cn',
baseUriPath: '/'
},
ui: { flags: { P: true } },
versionCheck: {
enable: false,
},
})
.then((unleash) => {
console.log(
`Unleash started on http://localhost:${unleash.app.get('port')}`,
);
});

Nginx conf

upstream unleash_proxy {
server 127.0.0.1:4242;
}
server {
listen 80;
server_name unleash.thape.com.cn;
return 301 https://unleash.thape.com.cn$request_uri;
}
server {
listen 443 ssl;
server_name unleash.thape.com.cn;
ssl_certificate /etc/ssl/cert/STAR_thape_com_cn_integrated.crt;
ssl_certificate_key /etc/ssl/private/STAR_thape_com_cn.key;
client_max_body_size 10M;
location / {
proxy_pass http://unleash_proxy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
access_log /var/www/unleash/shared/log/nginx.access.log;
error_log /var/www/unleash/shared/log/nginx.error.log;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

unleash DB backup

pg_dump unleash_production -O -x | gzip > unleash_prod_db.sql.gz

unleash import

psql -d postgres
DROP DATABASE unleash_dev;
CREATE DATABASE unleash_dev WITH ENCODING='UTF8';
ALTER DATABASE unleash_dev SET TIMEZONE='Asia/Shanghai';
\q
gunzip < unleash_prod_db.sql.gz | psql -d unleash_dev

Install PostgreSQL 16.1 on Rocky Linux 9.2 With Pgxn Client and Pgvector

Permalink

Install htop and atop

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

Install postgresql 17 (original 16.1)

yum install https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm
yum update
yum install postgresql17-server
yum install -y glibc-langpack-en
localectl set-locale LANG=en_US.UTF-8
/usr/pgsql-17/bin/postgresql-17-setup initdb
systemctl start postgresql-17.service
systemctl status postgresql-17.service
systemctl enable postgresql-17.service

Install build tools

sudo yum install gcc-c++ make
sudo dnf --enablerepo=crb install perl-IPC-Run
sudo yum install postgresql17-devel
sudo yum install postgresql17-contrib # pg_trgm btree_gist require by gitlab

Install pip

Run as root

dnf install python3-pip
pip install pgxnclient --no-warn-script-location
export PATH=$PATH:/usr/pgsql-17/bin

Install pgvector extension

Run as root

yum install redhat-rpm-config
pgxnclient install vector

If in MacOS

brew install pgxnclient
pgxnclient install --pg_config $(brew --prefix postgresql@17)/bin/pg_config vector

Install pg gem correctly

bundle config build.pg --with-pg-config=/usr/pgsql-17/bin/pg_config
bundle install

Disable SELinux

vi /etc/selinux/config

Disable firewall

firewall-cmd --zone=public --add-port=5432/tcp
firewall-cmd --permanent --zone=public --add-port=5432/tcp
firewall-cmd --reload
systemctl restart firewalld

Allow Remote Addresses

vi /var/lib/pgsql/17/data/postgresql.conf
listen_addresses = '*'

Create user and DB

sudo su - postgres
createuser kq_ai --pwprompt
psql
ALTER ROLE kq_ai LOGIN;
CREATE DATABASE kq_ai_db WITH ENCODING='UTF8' OWNER=kq_ai;
logout
vi /var/lib/pgsql/17/data/pg_hba.conf
# TYPE DATABASE USER ADDRESS METHOD
host kq_ai_db kq_ai 0.0.0.0/0 scram-sha-256

Reload conf without restart DB

sudo su - postgres
/usr/pgsql-17/bin/pg_ctl reload

Enable vector

psql -d kq_ai_db
CREATE EXTENSION vector;
ALTER EXTENSION vector UPDATE;

check with normal user kq_ai sql

SELECT extversion FROM pg_extension WHERE extname = 'vector';

Export DB

pg_dump thape_forum_prod -O -x > thape_forum_prod_db.sql
zip thape_forum_prod_db.zip thape_forum_prod_db.sql
`

Import DB

psql --username=thape_forum --password --host=localhost -d thape_forum_prod -f thape_forum_prod_db.sql

2023 年的部门小结与 2024 年的计划

Permalink

2023 年马上要结束了,一眨眼 8 个月又过去了,参照2023 年的工作小结与计划的内容,先复盘一下 8 个月前的判断:

世界线

之前不看好阿里,现在回过头看没想到阿里会那么差,连市值也被只有其人数 1/10 的拼多多超过。之前判断鸿蒙失败了,这两天看到了急召鸿蒙开发工程师年薪 160 万的新闻,咋一看好像是鸿蒙非常红火,但其实我觉得只是在炒作,首先一个新兴客户端的年薪不可能那么高,其次如果真的鸿蒙生态起来了,必然开发者数量非常多,也开不了那么高,只能说明大家的眼睛是雪亮的,几乎没啥开发者在搞鸿蒙开发。当然这个肯定是主观判断,客观的也有,跨平台的 Taro 有一个 RFC,只有标题,没有内容,和其他类似的 RFC 提案相比较,我只能说我会持续关注。

经济方面,国内的房地产业大规模熄火已经导致了行业不景气,降本增效天天念就对了,就是得注意一下发言,别像阿里一样,搞成降本增笑。

今年最最火的还是 AI,也是唯一增长的领域。

IT 技术发展预测

语言

计算机语言的隔阂几乎被 GPT 4 完全打破了,一般的算法之类的,只要贴一种语言的表达,让 GPT 4 转化成另外一种语言,几乎都是可用的。甚至直接用人类语言编程也已经不是梦想,我在工作中也已经经常使用,但是这里有个问题,就是人类语言本身还是充满歧义,所以在需要精确表达的时候,还是发现应该用计算机语言。

数据库

本来以为 MySQL 和 PostgreSQL 是平分秋色的,现在看来 PG 已经远远的超过 MySQL,因为人工智能需要向量数据库等新的数据库形式,而这个现在只有 pgvector 是相对成熟和免费的,总的来看 PG 的插件体系太强了,甚至产生了PGXN这样的扩展插件管理工具,为了人工智能,现在只选 PG 就对了。

跨平台

Java 高版本 Oracle 开始收版权费了,dotNET 6 开始就完全跨平台了,WASM 也成为了 Web 的第二运行时(第一还是 JS),跨平台已经不是一个话题了,以后也不会再提。

Web 平台

作为平台之上的平台,Web 目前还是普通应用分发的第一选择。现在普通应用和生产力应用的区分更加模糊,比如现在的轻量看图已经是一种普通应用了。

Serverless、DevOps,运维自动化

随着国内阿里和滴滴的两次史诗级故障,Serverless 被证明只是找不到 Server 去修,而不是不会出错,而且每次故障都是人为的,所以运维自动化是必须的,DevOps 现在也扩展为 DevSecOps,以强调安全。

数据平台/中台

数据集中是对的,数据库是重要的,但是数据平台或者中台可能只是个 PPT 概念而已。

人工智能

GPT 4 出道半年了,基本可以确定现在的软件架构,最上面完全可以新加一层人工智能层,这一层将包含以下功能:

  • 无法写出程序的判断任务
  • 理解用户输入的自然语言意图和心情
  • 模拟人类的思考判断并执行

如何将这些任务所需要的数据送入这层,如何判断这层运算的结果,如果提取这些结果到执行层,这些都将是未来的核心任务。

但无论如何,人工智能需求是真的大,大到了连大的数据中心也一卡难求,所以大多数人都接受了 API 调用方式,而不是通常企业软件的 self-hosting,自部署。但从长期看,随着各种人工智能加速运算卡的普及已经用了公开的所有数据,所以当以后算力或者模型都不是瓶颈以后,数据将成为唯一的区分人工智能强弱的变量。

部门完成的工作小结

部门目前维护了22 个系统,今年新做的比较大的项目是 PLM 项目管理平台,PP 人员考核,PPT 协作,还有 SD 生图。合作商平台材料文本库和 Cybros 商务智能平台也在今年改动了很多。今年还做了不少临时性的需求,比如爬取侵犯我们官网的利用我们官网数据的网站,数据留痕便于起诉等。

比对之前的计划,在 API 互通上也做了好几个案例,特别是 PLM 这边和 DDS 还有会议预定系统的互联互通,迪峰和嘉鹏的合作值得肯定。用户体验方面,今年应该是最难的一年,因为人工智能的浪潮还没有卷到用户层,所以用户现在对 UI 的界面和交互停留在了历史最高点,等明年随着大规模的人工智能能力部署,人类用户应该没那么多闲情逸致吹毛求疵 UI 了,毕竟人工智能可不会嫌软件 UI 差而不用,相反,我们开发还可以将更多的经历投入到让人工智能代替人类用户的事物上。

2024 年的计划

完成开发至少两个人工智能应用

目前肯定能完成的是智能问答,数据现成,代码可控,只要接人工智能模型即可,这个跑通以后,后续天问搜索,材料库搜索都可以用类似的技术重做。

保证系统平稳运行

随着人员和硬件投入的进一步降低,要尽量避免出现类似阿里和滴滴这样的系统崩溃案例,平时的备份和维护还是要做好

引入安全审查和漏洞检测机制

随着人员和硬件投入的进一步降低,越来越多的项目将处于长期停止开发状态,要避免泛微或者 IE 11 造成的大规模安全事件,还是要从源头抓起,找出软件内使用组件的漏洞并修补是一个很好的切入点。

强调团队合作

随着人员和硬件投入的进一步降低,越来越少的人将维护越来越多的系统,原则上要鼓励扩展已有的系统满足需求或者系统相互调用满足需求,尽量避免再开发新的系统。

Resolving macOS Ventura Failed to Install Npm Package Sharp After Brew Upgrade Vips to 8.15.0_1

Permalink

sharp is a dependency module for Next.js. However, I encountered an installation error on my MacOS Ventura, as shown below:

error /Users/guochunzhong/git/sso/changelog/node_modules/sharp: Command failed.
Exit code: 1
Command: (node install/libvips && node install/dll-copy && prebuild-install) || (node install/can-compile && node-gyp rebuild && node install/dll-copy)
Arguments:
Directory: /Users/guochunzhong/git/sso/changelog/node_modules/sharp
Output:
sharp: Detected globally-installed libvips v8.15.0
sharp: Building from source via node-gyp
gyp info it worked if it ends with ok
gyp info using node-gyp@10.0.1
gyp info using node@18.18.2 | darwin | arm64
gyp info find Python using Python version 3.11.6 found at "/opt/homebrew/opt/python@3.11/bin/python3.11"
gyp info spawn /opt/homebrew/opt/python@3.11/bin/python3.11
gyp info spawn args [
gyp info spawn args '/opt/homebrew/lib/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args 'binding.gyp',
gyp info spawn args '-f',
gyp info spawn args 'make',
gyp info spawn args '-I',
gyp info spawn args '/Users/guochunzhong/git/sso/changelog/node_modules/sharp/build/config.gypi',
gyp info spawn args '-I',
gyp info spawn args '/opt/homebrew/lib/node_modules/node-gyp/addon.gypi',
gyp info spawn args '-I',
gyp info spawn args '/Users/guochunzhong/Library/Caches/node-gyp/18.18.2/include/node/common.gypi',
gyp info spawn args '-Dlibrary=shared_library',
gyp info spawn args '-Dvisibility=default',
gyp info spawn args '-Dnode_root_dir=/Users/guochunzhong/Library/Caches/node-gyp/18.18.2',
gyp info spawn args '-Dnode_gyp_dir=/opt/homebrew/lib/node_modules/node-gyp',
gyp info spawn args '-Dnode_lib_file=/Users/guochunzhong/Library/Caches/node-gyp/18.18.2/<(target_arch)/node.lib',
gyp info spawn args '-Dmodule_root_dir=/Users/guochunzhong/git/sso/changelog/node_modules/sharp',
gyp info spawn args '-Dnode_engine=v8',
gyp info spawn args '--depth=.',
gyp info spawn args '--no-parallel',
gyp info spawn args '--generator-output',
gyp info spawn args 'build',
gyp info spawn args '-Goutput_dir=.'
gyp info spawn args ]
Package libarchive was not found in the pkg-config search path.
Perhaps you should add the directory containing `libarchive.pc'
to the PKG_CONFIG_PATH environment variable
Package 'libarchive', required by 'vips', not found
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
CC(target) Release/obj.target/nothing/../node-addon-api/nothing.o
LIBTOOL-STATIC Release/nothing.a
warning: /Library/Developer/CommandLineTools/usr/bin/libtool: archive library: Release/nothing.a the table of contents is empty (no object file members in the library define global symbols)
TOUCH Release/obj.target/libvips-cpp.stamp
CXX(target) Release/obj.target/sharp-darwin-arm64v8/src/common.o
../src/common.cc:13:10: fatal error: 'vips/vips8' file not found
#include <vips/vips8>
^~~~~~~~~~~~
1 error generated.
make: *** [Release/obj.target/sharp-darwin-arm64v8/src/common.o] Error 1
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack at ChildProcess.<anonymous> (/opt/homebrew/lib/node_modules/node-gyp/lib/build.js:209:23)
gyp ERR! System Darwin 22.6.0
gyp ERR! command "/opt/homebrew/Cellar/node@18/18.18.2/bin/node" "/opt/homebrew/bin/node-gyp" "rebuild"
gyp ERR! cwd /Users/guochunzhong/git/sso/changelog/node_modules/sharp
gyp ERR! node -v v18.18.2
gyp ERR! node-gyp -v v10.0.1
gyp ERR! not ok
info Visit https://yarnpkg.com/en/docs/cli/upgrade for documentation about this command.

This issue can be resolved by executing the following command: export PKG_CONFIG_PATH=/opt/homebrew/Cellar/libarchive/3.7.2/lib/pkgconfig:/opt/homebrew/Cellar/vips/8.15.0_1/lib/pkgconfig

This solution was suggested by GPT-4!

A Open Letter Written by Parent at Students and Farmers Party

Permalink

女儿你好,

转眼你都学农了,爸爸记得小时候爸爸要到高中才学的农,可能现在的学农教育提前了吧?爸爸记得小时候,学农的时候,抬头望星空,满天的星星,周围全是蛙声,而现在爸爸也是老眼昏花看不清星空了,而现在你周边蛙声也肯定少了吧?不要误会!爸爸并不是说现在不好,只是世界真的在发生变化,我们一代代中国人也要适应变化。另外爸爸其实很羡慕你现在的时代,科学昌明,生产力发达。

爷爷在爸爸五年级的时候,肯定想不到爸爸最终会以电脑编程为职业,因为电脑进入百姓家是在1995年以后,以此类推,爸爸多半也想不到你最终会以何种技能为职业,也许是人工智能?但是人工智能以目前的观点看并不需要人类参与具体过程,只需要人类最终决定是否采纳它的建议或者结果啊,所以你们现在学习的东西未来到底有没有用,真的很令人担心啊!不要误会!爸爸并不是说你现在应该停止学习,而是想告诉你,世界变化的很快,知识更新的也很快。

无论如何,你现在可以抬头,仰望一下星空。(此处暂停5秒) 我们现在可以肯定仰望星空这个动作肯定是贯穿了整个人类历史的,一代代的人,从打猎烤火吃了这顿没下顿,到学会耕种喂饱自己,到工业革命解放自己体力,到现在信息革命释放自己的脑力。历史已经证明,仰望星空进而引发的好奇探索才有未来,过去大清那样的闭关锁国,闷头耕田,固步自封是没有出路的。不要误会!爸爸并不是建议你现在就退出学农,立刻回家,而是想告诉你,农业搞好了才能搞工业,工业搞好了才有信息产业,其实是无法跳过前面一个步骤直接进入下一个阶段的,我们中国面临的人工智能芯片断供就是中国过去20年自作聪明跳过了芯片研发生产的后果。

不要误会!信的结尾爸爸并不想和你们刚刚学过的少年中国说里那样,给只有5年纪的你提出不切实际的要求,爸爸此刻只是激励自己,好好写好这封信,这信是你妈妈手写的,爸爸电脑上手打的,没有任何人工智能的参与,爸爸猜测这在今后的人工智能时代将是一种奢侈,人工智能时代已经到来,网上你看到的垃圾将越来越多,珍惜现在学校的课程、同学和老师吧。团结起来,爸爸猜测你们共同的敌人应该是已经被开发出,而且越来越不受控制的人工智能。

祝你学农愉快,晚上尽量早点睡。

爸爸 - 过纯中

A Programmer Productivity Measure Method - Code Commit (Chinese)

Permalink

对代码递交数量进行度量的思考

评价程序员工作的度量有哪些?

程序员的工作量评估天然就困难,虽然现在程序员的工作随着各种框架的越来越成熟,越来越接近于搬砖,但是无可否认的是程序员还是一个重度思考的行业,一个优秀的程序员,肯定能够又快又好,代码又少,速度又快的完成工作,但是现实没有那么理想,作为管理者其实是很难对程序员的工作进行检查的,很多公司因此采用了粗暴的方式,只考虑程序员的上班时长,拼命加班,这显然是不好的,所以本文提出了一种对程序员工作的代码递交数量进行考核的方法,它肯定不完美,但至少也是一个方式,所以写了本文进行探讨。

基于上班时长的度量

程序员每天耕地码字,一天12个小时,996,最后不到40岁就身体不行了,提前退休。这就是近10年互联网黄金年代(2012~2022)的常态。从程序员角度看,第一批这样做的人已经财务自由了,所以这个方式显然是不错的,但是由于互联网进入了白银时代,甚至AI自动时代,所以这个方式不可持续。天天996的结果往往是开发效率的降低,一群年轻程序员上班摸鱼,看上去公司灯火通明,但是效率并没有提高。

随着程序员的总体平均年龄增大,越来越多的程序员也难以996,所以提倡上班时长作为唯一度量,会导致损失一部分优秀大龄程序员,所以急需一种补充的度量方式。

基于代码行数的度量

Bill Gates 曾经说过,按照代码行数评价软件就像按照重量评价飞机,它固然是一个指标,但是绝对不是一个好的指标。一系列的实践也表明,片面追求代码行数反而会导致开发的软件质量的下降。

基于递交数量的度量

递交数量的问题会比代码行数好一点,毕竟当你一个个递交点进去的时候,一些明显毫无意义的递交就暴露了,递交需要写递交目的,一个盲目的递交绝对是无法通过同行评审的,所以更加客观一点。开源软件的实践也表明,基于Pull Request和Merge Request的同行审议评审递交制度有利于软件的质量提高。

基于用户评价的度量

用户满意,用户是上帝是对的。但用户作为一个群体,是内在不同的,有的人腼腆,有的人没耐心,有的人还喜欢动不动就以苹果原生软件的标准要求其他没有那么多开发预算的软件。而且由于程序员开发系统的不同,实际上无法用同一批用户对各个系统分别打分,或者说如果这样的打分存在,就是变成业务价值的度量了。

基于业务价值的度量

这是我能想到的最客观评价,也是黄金时代互联网对程序员的最好回馈,很多程序员通过拿互联网公司的股票期权,几年后抛售股票期权达到了财务自由。但业务价值是需要市场评价的,而且评价的速度较为缓慢,难以作为一种短期的评价指标使用。公司内部开发软件等一系列软件并没有简单方式评估业务价值。

针对递交数量的度量的应对

所以综上,基于递交数量的评价再加上上班时长度量,笔者认为可以较为合理的评价程序员的工作量,所以接下来就针对这个评价政策,谈谈程序员如何应对。

如何拆出尽量多的度量

既然数量重要,当然要尽量拆一点出来,所幸的是,这也是也是好的开发习惯。

重构递交

在软件开发中,程序员看起来改的是代码,但是我们都知道,代码其实是一棵抽象语法树,通过函数调用让程序的执行流再一棵棵树中穿梭。所以软件开发中,调整代码的结构实际上是一种重要工作,在新加一个功能的时候,往往代码中是没有地方放这个新功能的,这时候就需要调整代码的结构,所以显然代码结构的调整,也就是重构,完全可以作为一次递交。

数据库的schema架构更改递交

应用开发本质上再操作数据库,所以任何开发工作开始前,肯定要对数据库做一定的更改,这也完全可以作为独立的递交。

实际功能的递交

实际新功能的UI,功能推荐在一起递交,但是UI的结构调整其实也可以作为独立递交,这样拆出来以后,新功能就有两次递交了。

实际功能的异常处理

新功能显然还要考虑各种边界条件,各种约束,发生各种异常的处理,这部分也能作为单独的递交。

Bug修正的递交

这部分递交要慎重,如果Bug修正的递交过多,只能说明程序员的水平较差,但是显然我们没有任何理由将这些递交放弃,修bug显然可以作为一次递交。

一些Typo和Style修正

这部分递交最好还是一次性的,reviewer的智商都是在线的,先打错几个字,几个空格,然后再修正,这种行为太low了,还是要尊重程序员彼此的智商,这类递交要完全避免。

如何避免长时间的单行递交的度量

除了刷递交,长时间的单行递交是很亏的,尤其是你工作了一周,只有一行修正递交的情况下,所以我们可以尽量讲修正这行的思路写在一个PR的message中,通过记录自己的思考过程,检查系统的数据细节罗列来体现工作量,要相信code reviewer的智商。

如何避免无法用代码递交体现的工作

一些运维工作的确无法体现在代码中,所以我们尽量要写出免运维,也就是用户不需要培训或者咨询相关人士,就能使用的软件。

常见问题

下班前需要递交吗?

尽量按照上面的原子单元方式递交,不过如果你一天都在查bug,那就写点message,如果你在探索新的API用法,就写点message,在gitlab的activity 中,这些动作一样会被记录的。

一行行的递交这个主意如何?

我个人的感觉,这个主意很差。我建议不要做傻事,也不要假定别人是傻瓜。当然如果你很擅长当傻瓜,那也许可以尝试,并将对方拖入自己的擅长领域打败他。