Browse Source

:octocat: Improve development experience

ssfdust 3 years ago
parent
commit
97e5a3c617
8 changed files with 341 additions and 20 deletions
  1. 50 0
      .github/CONTRIBUTING.md
  2. 52 0
      .github/CONTRIBUTING_zh_CN.md
  3. 6 0
      .gitignore
  4. 1 0
      kernel/go.mod
  5. 2 0
      kernel/go.sum
  6. 31 20
      kernel/util/working.go
  7. 8 0
      scripts/kernel-live-reload.sh
  8. 191 0
      scripts/start-dev.sh

+ 50 - 0
.github/CONTRIBUTING.md

@@ -49,3 +49,53 @@ On the desktop, go to the app folder to compile and run:
 * https://github.com/siyuan-note/siyuan-android
 
 For the mobile-end, please refer to the corresponding project repository.
+
+## Container (Optional)
+
+* It's expected to run in linux only. (May work in `Windows WSL 2` as well.)
+* The container is based on `podman`, `buildah` and `catatonit`, you need to install them with your system package manager.
+* The container operation is combined into `start-dev.sh` script.
+
+### User Interface
+
+```bash
+sudo scripts/start-dev.sh -u $(id -u) -f     # Start frontend development
+sudo scripts/start-dev.sh -u $(id -u) -f     # Run the command again to attach container shell
+```
+
+### Kernel
+
+```bash
+sudo scripts/start-dev.sh -u $(id -u) -b                    # Start backend development
+sudo scripts/start-dev.sh -u $(id -u) -b -ws /tmp/siyuan    # Start backend development with workspace mapping with /tmp/siyuan
+```
+
+### Force rebuild image
+
+```bash
+sudo scripts/start-dev.sh -u $(id -u) -f -r  # Force rebuild frontend image
+sudo scripts/start-dev.sh -u $(id -u) -b -r  # Force rebuild backend image
+```
+
+### Attach a running container as root
+
+```bash
+sudo scripts/start-dev.sh -u 0 -f            # Attach frontend as root
+sudo scripts/start-dev.sh -u 0 -b            # Attach backend as root
+```
+
+### Script Arguments
+
+```
+Usage:
+    start-dev.sh [-ws|--workspace <WORKSPACE>] [-u|--uid <UID>]  [-r|--rebuild] [-f|--frontend] [-b|--backend]
+
+Arguments:
+
+    -h, --help                                   Print help information
+    -u=<UID>, --uid=<UID>                        Set the user id (default: 0)
+    -ws=<WORKSPACE>, --workspace=<WORKSPACE>     Set workspace directory for SiYuan kernel (default: Documents/SiYuan)
+    -r, --rebuild                                Force rebuild image (default: false)
+    -f, --frontend                               Start frontend devlop (default: false)
+    -b, --backend                                Start backend devlop (default: true)
+```

+ 52 - 0
.github/CONTRIBUTING_zh_CN.md

@@ -7,6 +7,8 @@
 
 ## NPM 依赖
 
+### 桌面
+
 安装 pnpm:`npm install -g pnpm`
 
 <details>
@@ -47,3 +49,53 @@ NPM 镜像:
 * https://github.com/siyuan-note/siyuan-android
 
 移动端请参考对应项目仓库。
+
+## 容器 (可选)
+
+* 只适用于`Linux` (理论上也能在`Windows WSL 2`中运行。)
+* 容器基于`podman`,`buildah`,`catatonit`开发,需要使用系统自带的包管理器安装它们。
+* 容器自动构建与运行集成在`scripts/start-dev.sh`脚本中。
+
+### 桌面
+
+```bash
+sudo scripts/start-dev.sh -u $(id -u) -f     # 进行前端开发
+sudo scripts/start-dev.sh -u $(id -u) -f     # 再一次运行此命令,进入到前端容器shell
+```
+
+### 内核 
+
+```bash
+sudo scripts/start-dev.sh -u $(id -u) -b                    # 开始后端开发
+sudo scripts/start-dev.sh -u $(id -u) -b -ws /tmp/siyuan    # 开始后端开发,映射本地/tmp/siyuan为工作区
+```
+
+### 强制重建镜像
+
+```bash
+sudo scripts/start-dev.sh -u $(id -u) -f -r  # 强制重建前端镜像
+sudo scripts/start-dev.sh -u $(id -u) -b -r  # 强制重建后端镜像
+```
+
+### 以root角色执行容器Shell
+
+```bash
+sudo scripts/start-dev.sh -u 0 -f            # 以root角色执行前端容器Shell
+sudo scripts/start-dev.sh -u 0 -b            # 以root角色执行后端容器Shell
+```
+
+### 脚本参数
+
+```
+Usage:
+    start-dev.sh [-ws|--workspace <WORKSPACE>] [-u|--uid <UID>]  [-r|--rebuild] [-f|--frontend] [-b|--backend]
+
+Arguments:
+
+    -h, --help                                   Print help information
+    -u=<UID>, --uid=<UID>                        Set the user id (default: 0)
+    -ws=<WORKSPACE>, --workspace=<WORKSPACE>     Set workspace directory for SiYuan kernel (default: Documents/SiYuan)
+    -r, --rebuild                                Force rebuild image (default: false)
+    -f, --frontend                               Start frontend devlop (default: false)
+    -b, --backend                                Start backend devlop (default: true)
+```

+ 6 - 0
.gitignore

@@ -37,3 +37,9 @@ lerna-debug.log*
 # package
 package-lock.json
 yarn.lock
+
+# container
+Documents/
+.bash_history
+.config/
+.pnpm-store/

+ 1 - 0
kernel/go.mod

@@ -78,6 +78,7 @@ require (
 	github.com/hhrutter/tiff v0.0.0-20190829141212-736cae8d0bc7 // indirect
 	github.com/huandu/xstrings v1.3.2 // indirect
 	github.com/imdario/mergo v0.3.13 // indirect
+	github.com/jnovack/flag v1.16.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/juju/errors v0.0.0-20220331221717-b38fca44723b // indirect
 	github.com/klauspost/compress v1.15.6 // indirect

+ 2 - 0
kernel/go.sum

@@ -302,6 +302,8 @@ github.com/imroc/req/v3 v3.13.1/go.mod h1:G6fkq27P+JcTcgRVxecxY+amHN1xFl8W81eLCf
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
 github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
+github.com/jnovack/flag v1.16.0 h1:gJC3JVofq/hNGlNfki4NlIWLOiDkaeLNUOCzznCablU=
+github.com/jnovack/flag v1.16.0/go.mod h1:8g1MmrEr03yquMjIe6CYeXUiIsZ46ssYt+o3X7uEjcg=
 github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=

+ 31 - 20
kernel/util/working.go

@@ -17,7 +17,6 @@
 package util
 
 import (
-	"flag"
 	"log"
 	"math/rand"
 	"mime"
@@ -29,6 +28,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/jnovack/flag"
 	"github.com/88250/gulu"
 	figure "github.com/common-nighthawk/go-figure"
 	goPS "github.com/mitchellh/go-ps"
@@ -50,40 +50,51 @@ var (
 )
 
 func Boot() {
+    var (
+        workspacePath string
+        wdPath string
+        servePath string
+        resident bool
+        readOnly bool
+        accessAuthCode string
+        ssl bool
+        lang string
+        mode string
+    )
 	IncBootProgress(3, "Booting...")
 	rand.Seed(time.Now().UTC().UnixNano())
 	initMime()
 
-	workspacePath := flag.String("workspace", "", "dir path of the workspace, default to ~/Documents/SiYuan/")
-	wdPath := flag.String("wd", WorkingDir, "working directory of SiYuan")
-	servePath := flag.String("servePath", "", "obsoleted https://github.com/siyuan-note/siyuan/issues/4647")
+	flag.StringVar(&workspacePath, "workspace", "", "dir path of the workspace, default to ~/Documents/SiYuan/")
+	flag.StringVar(&wdPath, "wd", WorkingDir, "working directory of SiYuan")
+	flag.StringVar(&servePath, "servePath", "", "obsoleted https://github.com/siyuan-note/siyuan/issues/4647")
 	_ = servePath
-	resident := flag.Bool("resident", true, "resident memory even if no active session")
-	readOnly := flag.Bool("readonly", false, "read-only mode")
-	accessAuthCode := flag.String("accessAuthCode", "", "access auth code")
-	ssl := flag.Bool("ssl", false, "for https and wss")
-	lang := flag.String("lang", "en_US", "zh_CN/zh_CHT/en_US/fr_FR")
-	mode := flag.String("mode", "prod", "dev/prod")
+	flag.BoolVar(&resident, "resident", true, "resident memory even if no active session")
+	flag.BoolVar(&readOnly, "readonly", false, "read-only mode")
+	flag.StringVar(&accessAuthCode, "accessAuthCode", "", "access auth code")
+	flag.BoolVar(&ssl, "ssl", false, "for https and wss")
+	flag.StringVar(&lang, "lang", "en_US", "zh_CN/zh_CHT/en_US/fr_FR")
+	flag.StringVar(&mode, "mode", "prod", "dev/prod")
 	flag.Parse()
 
-	if "" != *wdPath {
-		WorkingDir = *wdPath
+	if "" != wdPath {
+		WorkingDir = wdPath
 	}
-	if "" != *lang {
-		Lang = *lang
+	if "" != lang {
+		Lang = lang
 	}
-	Mode = *mode
-	Resident = *resident
-	ReadOnly = *readOnly
-	AccessAuthCode = *accessAuthCode
+	Mode = mode
+	Resident = resident
+	ReadOnly = readOnly
+	AccessAuthCode = accessAuthCode
 	Container = "std"
 	if isRunningInDockerContainer() {
 		Container = "docker"
 	}
 
-	initWorkspaceDir(*workspacePath)
+	initWorkspaceDir(workspacePath)
 
-	SSL = *ssl
+	SSL = ssl
 	LogPath = filepath.Join(TempDir, "siyuan.log")
 	AppearancePath = filepath.Join(ConfDir, "appearance")
 	if "dev" == Mode {

+ 8 - 0
scripts/kernel-live-reload.sh

@@ -0,0 +1,8 @@
+#!/bin/sh
+
+cd kernel
+gin --port 6807 \
+    --appPort 6806 \
+    --buildArgs '--tags fts5 -ldflags "-s -w"' \
+    -b ../app/kernel/kernel \
+    run 

+ 191 - 0
scripts/start-dev.sh

@@ -0,0 +1,191 @@
+#!/bin/bash
+# 
+# Description:
+#   Start running siyuan background development environment...   
+#   If there is an environment running already, it will take you into
+#   the shell of the container.
+#
+# Preparation:
+#   Archlinux:
+#       sudo pacman -S podman catatonit buildah
+#   Fedora & RHEL:
+#       sudo dnf install podman catatonit buildah
+#   Ubuntu & Debian:
+#       sudo apt install podman catatonit buildah
+
+set -eo pipefail
+
+BASEDIR=$(cd `dirname $BASH_SOURCE`;pwd)
+NAME="siyuan-go-dev"
+PODNAME="siyuan"
+USERID=0
+REBUILD=0
+FRONTEND=0
+BACKEND=0
+WORKSPACE=$(cd `dirname $BASEDIR`;echo `pwd`/"Documents/SiYuan")
+
+function InitlizePod () {
+    echo "Start to initilize pod..."
+    found=$(podman pod ps | grep ${PODNAME} || :)
+    if [[ -n "${found}" ]];then
+        echo "Found pod ${PODNAME}, starting..."
+        podman pod start ${PODNAME} > /dev/null || (podman pod rm -f ${PODNAME} && podman pod start ${PODNAME})
+    else
+        echo "Create pod..."
+        podman pod create --name ${PODNAME} -p 6806:6807
+    fi
+}
+
+function BuildFrontImage () {
+    if [[ "$(podman images ${NAME} 2>&1 >/dev/null;echo $?)" != "0" || "${REBUILD}" == "1" ]];then
+        echo "Start build ${NAME} image..."
+        buildah ps -a | grep -q ${NAME} && buildah rm ${NAME} || :
+        container=$(buildah from --name ${NAME} docker.io/library/node:16-bullseye)
+        buildah run ${container} -- sh -c "sed -i 's|deb.debian.org|mirrors.ustc.edu.cn|' /etc/apt/sources.list &&
+            sed -i 's|security.debian.org/debian-security|mirrors.ustc.edu.cn/debian-security|g' /etc/apt/sources.list &&
+            apt-get update -y &&
+            apt-get upgrade -y &&
+            apt install -y build-essential make"
+        buildah run ${container} -- npm --registry=https://registry.npm.taobao.org install --location=global pnpm
+        buildah config \
+            --workingdir /go/src/github.com/siyuan-note/siyuan/app \
+            --env ELECTRON_MIRROR=https://cnpmjs.org/mirrors/electron/ \
+            --user ${USERID} ${NAME}
+        buildah run \
+            -v "$(pwd):/go/src/github.com/siyuan-note/siyuan" \
+            ${container} -- sh -c "pnpm config set registry https://registry.npm.taobao.org/ &&
+                pnpm install"
+        buildah config --cmd "pnpm run dev:desktop" ${container}
+        buildah commit ${container} ${NAME}
+        buildah rm ${container}
+    fi
+}
+
+function BuildGoImage () {
+    if [[ "$(podman images ${NAME} 2>&1 >/dev/null;echo $?)" != "0" || "${REBUILD}" == "1" ]];then
+        echo "Start build ${NAME} image..."
+        buildah ps -a | grep -q ${NAME} && buildah rm ${NAME} || :
+        container=$(buildah from --name ${NAME} docker.io/library/golang:1-bullseye)
+        buildah run ${container} -- sh -c "sed -i 's|deb.debian.org|mirrors.ustc.edu.cn|' /etc/apt/sources.list &&
+            sed -i 's|security.debian.org/debian-security|mirrors.ustc.edu.cn/debian-security|g' /etc/apt/sources.list &&
+            apt-get update -y &&
+            apt-get upgrade -y &&
+            apt install -y build-essential make"
+        buildah run ${container} -- sh -c "mkdir -p /home/siyuan/Documents/SiYuan;chmod 777 -R /home/siyuan"
+        buildah config \
+            --workingdir /go/src/github.com/siyuan-note/siyuan \
+            --env GO111MODULE=on \
+            --env GOPROXY=https://goproxy.io \
+            --env CGO_ENABLED=1 \
+            --env GOCACHE=/go/cache/go-build \
+            --env GOOS=linux \
+            --env GOARCH=amd64 \
+            --env WD=/go/src/github.com/siyuan-note/siyuan/app \
+            --env MODE=dev \
+            --env PORT=6807 \
+            --env TZ=Asia/Shanghai \
+            --env WORKSPACE=/home/siyuan/Documents/SiYuan \
+            --user ${USERID} ${container}
+        buildah run \
+            -v "$(pwd):/go/src/github.com/siyuan-note/siyuan" "${container}" \
+            -- go install github.com/codegangsta/gin@latest
+        buildah config --cmd scripts/kernel-live-reload.sh ${container}
+        buildah commit ${container} ${NAME}
+        buildah rm ${container}
+    fi
+}
+
+function BuildImage () {
+    if [[ ${FRONTEND} == 1 ]];then
+        NAME="siyuan-front-dev"
+        BuildFrontImage
+    else
+        NAME="siyuan-go-dev"
+        BuildGoImage
+    fi
+}
+
+function StartDev () {
+    if [[ -n "$(podman ps | grep ${NAME} || :)" ]];then
+        podman exec -u ${USERID} -ti ${NAME} bash
+    else
+        podman ps -a | grep -q ${NAME} && podman rm ${NAME} || :
+        [ ! -d ${WORKSPACE} ] && mkdir -p ${WORKSPACE} && chown -R ${USERID} ${WORKSPACE}
+        podman run --rm --pod ${PODNAME} --name ${NAME} -u ${USERID} -ti -v "$(pwd):/go/src/github.com/siyuan-note/siyuan" -v "${WORKSPACE}:/home/siyuan/Documents/SiYuan" ${NAME}
+    fi
+}
+
+for i in "$@"; do
+    case $i in
+        -r|--rebuild)
+            REBUILD=1
+            shift
+            ;;
+        -u=*|--uid=*)
+            USERID="${i#*=}"
+            shift
+            ;;
+        -u|--uid)
+            shift
+            USERID=$1
+            shift
+            ;;
+        -ws=*|--workspace=*)
+            WORKSPACE="${i#*=}"
+            shift
+            ;;
+        -ws|--workspace)
+            shift
+            WORKSPACE=$1
+            shift
+            ;;
+        -f|--frontend)
+            FRONTEND=1
+            shift
+            ;;
+        -b|--backend)
+            BACKEND=1
+            shift
+            ;;
+        -h|--help)
+            echo ""
+            echo "Usage:"
+            echo "    $(basename $BASH_SOURCE) [-ws|--workspace <WORKSPACE>] [-u|--uid <UID>]  [-r|--rebuild] [-f|--frontend] [-b|--backend]"
+            echo ""
+            echo "Arguments:"
+            echo ""
+            echo "    -h, --help                                   Print help information"
+            echo "    -u=<UID>, --uid=<UID>                        Set the user id (default: 0)"
+            echo "    -ws=<WORKSPACE>, --workspace=<WORKSPACE>     Set workspace directory for SiYuan kernel (default: Documents/SiYuan)"
+            echo "    -r, --rebuild                                Force rebuild image (default: false)"
+            echo "    -f, --frontend                               Start frontend devlop (default: false)"
+            echo "    -b, --backend                                Start backend devlop (default: true)"
+            echo ""
+            echo "Examples:"
+            echo ""
+            echo '    sudo scripts/start-dev.sh -u $(id -u) -f                    # Start frontend development'
+            echo '    sudo scripts/start-dev.sh -u $(id -u) -f                    # Run the command again to attach container shell'
+            echo '    sudo scripts/start-dev.sh -u $(id -u) -b                    # Start backend development with workspace mapping with default'
+            echo '    sudo scripts/start-dev.sh -u $(id -u) -b -ws /tmp/siyuan    # Start backend development with workspace mapping with /tmp/siyuan'
+            echo '    sudo scripts/start-dev.sh -u $(id -u) -f -r                 # Force rebuild frontend image'
+            echo '    sudo scripts/start-dev.sh -u $(id -u) -b -r                 # Force rebuild backend image'
+            echo '    sudo scripts/start-dev.sh -u $(id -u) -b -r                 # Force rebuild backend image'
+            echo "    sudo scripts/start-dev.sh -u 0 -f                           # Attach frontend container as root"
+            echo "    sudo scripts/start-dev.sh -u 0 -b                           # Attach backend container as root"
+            exit 2
+            ;;
+        -*|--*)
+            echo "Unknown option $i"
+            exit 1
+            ;;
+    esac
+done
+
+if [[ "${UID}" != "0" ]];then
+    echo "Must run as root."
+    exit 1
+fi
+
+BuildImage && \
+    InitlizePod && \
+    StartDev