diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..40585e3 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,21 @@ +name-template: 'release-v$NEXT_PATCH_VERSION' +tag-template: 'release-v$NEXT_PATCH_VERSION' +categories: + - title: 'Features' + labels: + - 'feature' + - 'enhancement' + - title: 'Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - title: 'Maintenance' + labels: + - 'chore' + - 'documentation' +change-template: '- $TITLE (#$NUMBER) @$AUTHOR' +template: | + # Changes + + $CHANGES \ No newline at end of file diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000..c72f8d3 --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,17 @@ +name: Release Drafter + +on: + push: + branches: + - master + +jobs: + draft_release: + if: github.repository == 'PasteUs/PasteMeLite' + name: Draft release + runs-on: ubuntu-latest + steps: + - uses: toolmantim/release-drafter@v5.2.0 + name: Draft + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/update-submodule-cron.yml b/.github/workflows/update-submodule-cron.yml new file mode 100644 index 0000000..da4072f --- /dev/null +++ b/.github/workflows/update-submodule-cron.yml @@ -0,0 +1,23 @@ +name: Update submodule + +on: + schedule: + - cron: "*/5 * * * *" + +jobs: + update: + if: github.repository == 'PasteUs/PasteMeLite' + name: Update submodule + runs-on: ubuntu-latest + + steps: + - name: Clone and update submodule + run: | + git clone https://github.com/${{ github.repository }}.git -b dev PasteMeDev --recursive + cd PasteMeDev + git submodule foreach git pull origin master + git config user.name "Lucien Shui" + git config user.email "lucien@lucien.ink" + git add --all + if ! git commit -m "Sync submodule at `TZ=UTC-8 date +'%Y-%m-%d %H:%M:%S'`"; then exit 0; fi + git push https://"${{ secrets.GITHUB_PASSWORD }}"@"github.com/${{ github.repository }}.git" dev diff --git a/.github/workflows/upload-to-release.yml b/.github/workflows/upload-to-release.yml new file mode 100644 index 0000000..a92305d --- /dev/null +++ b/.github/workflows/upload-to-release.yml @@ -0,0 +1,73 @@ +name: PasteMe Lite Release + +on: + release: + types: [published] + +jobs: + + release: + if: github.repository == 'PasteUs/PasteMeLite' + name: Release on ${{ matrix.os }} and upload + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest] + node_version: [12.x] + go_version: [1.13] + + steps: + - uses: actions/checkout@v1 + + - name: Set up Node.js ${{ matrix.node_version }} + uses: actions/setup-node@v1 + with: + node_version: ${{ matrix.node_version }} + + - name: Set up Go ${{ matrix.go_version }} + uses: actions/setup-go@v1 + with: + go-version: ${{ matrix.go_version }} + id: go + + - name: Update submodule + run: | + git submodule update --init --recursive + + - name: Build Frontend + run: | + cp vue.config.js PasteMeFrontend + cd PasteMeFrontend + npm install + npm run build + mv pasteme_frontend/usr/config.example.json pasteme_frontend/usr/config.json + rm -rf pasteme_frontend/conf.d pasteme_frontend/report.html + cd .. + + - name: Build Backend + run: | + cp server.go PasteMeGoBackend + cd PasteMeGoBackend + go mod download + go build main.go + cd .. + env: + GO111MODULE: on + GOPROXY: https://goproxy.io + GOOS: linux + + - name: Gzip + run: | + mkdir pasteme_lite + cp doc/DEPLOY.md pasteme_lite/README.md + cp -r PasteMeFrontend/pasteme_frontend pasteme_lite + cp PasteMeGoBackend/main pasteme_lite/pastemed + tar -czvf pasteme_lite.tar.gz pasteme_lite + + - name: Upload to release + uses: JasonEtco/upload-to-release@master + with: + args: pasteme_lite.tar.gz application/octet-stream + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..b901c66 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "PasteMeFrontend"] + path = PasteMeFrontend + url = https://github.com/PasteUs/PasteMeFrontend.git +[submodule "PasteMeGoBackend"] + path = PasteMeGoBackend + url = https://github.com/PasteUs/PasteMeGoBackend.git diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b2b370e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +FROM node:12 as frontend_builder +COPY ./PasteMeFrontend /source +COPY ./vue.config.js /source/vue.config.js +WORKDIR /source +RUN npm install --registry=https://registry.npm.taobao.org +RUN npm run build +RUN mv pasteme_frontend/usr/config.example.json pasteme_frontend/usr/config.json +RUN rm -rf pasteme_frontend/conf.d pasteme_frontend/report.html + +FROM golang:1.13-alpine as backend_builder +COPY ./PasteMeGoBackend /go/src/github.com/PasteUs/PasteMeGoBackend +COPY ./server.go /go/src/github.com/PasteUs/PasteMeGoBackend/server/server.go +ENV GO111MODULE=on \ + GOPROXY=https://goproxy.io \ + GOOS=linux +WORKDIR /go/src/github.com/PasteUs/PasteMeGoBackend +RUN apk --no-cache add g++ +RUN go mod download +RUN go build main.go + +FROM alpine:3 +LABEL maintainer="Lucien Shui" \ + email="lucien@lucien.ink" +COPY --from=backend_builder /go/src/github.com/PasteUs/PasteMeGoBackend/main /usr/bin/pastemed +COPY --from=frontend_builder /source/pasteme_frontend /pasteme_frontend +RUN chmod +x /usr/bin/pastemed && \ + mkdir /data && \ + mkdir /config && \ + echo '{"address":"0.0.0.0","port":8000,"database":{"type":"sqlite","username":"username","password":"password","server":"pasteme-mysql","port":3306,"database":"pasteme"}}' > /config/config.json +CMD ["pastemed", "-c", "/config/config.json", "-d", "/data"] diff --git a/PasteMeFrontend b/PasteMeFrontend new file mode 160000 index 0000000..1e505b1 --- /dev/null +++ b/PasteMeFrontend @@ -0,0 +1 @@ +Subproject commit 1e505b1f47e8b0dedaca83e35b1160aa87e80924 diff --git a/PasteMeGoBackend b/PasteMeGoBackend new file mode 160000 index 0000000..78cb828 --- /dev/null +++ b/PasteMeGoBackend @@ -0,0 +1 @@ +Subproject commit 78cb828474e0a50334027f30fd5b01a5c573803d diff --git a/README.md b/README.md index 842fe79..44676cc 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,34 @@ -# PasteMeLite -PasteMe lite version, executing is all you need to do. +

+ +

+

+ + version + + + version + +

+

+ + + + + version + + + version + + + donate + +

+
+

PasteMe Lite

+
+ +[PasteMe](https://github.com/LucienShui/PasteMe) 的轻量版本,将前端集成至 Golang 服务中,不依赖于数据库服务。唯一一件需要做的事情,就是运行。 + +## Deploy + +[PasteMe Lite Deploy Documentation](./doc/DEPLOY.md) diff --git a/doc/DEPLOY.md b/doc/DEPLOY.md new file mode 100644 index 0000000..a1efc08 --- /dev/null +++ b/doc/DEPLOY.md @@ -0,0 +1,21 @@ +# PasteMe Lite 部署文档 + +## 直接运行 + +> 由于 sqlite 使用了 cgo,故目前只支持 linux-amd64 + +前往此项目的 [latest release](https://github.com/PasteUs/PasteMeLite/releases/latest) 页面下载 `pasteme_lite.tar.gz` ,解压后执行 `./pastemed` 即可。 + +## Docker + +```bash +docker run \ + -d \ + -p 80:8000 \ + -v ${PWD}/backend/data/:/data/ \ + registry.cn-hangzhou.aliyuncs.com/pasteus/pasteme-lite:0.0.1 +``` + +## docker-compose + +[docker-compose.yml](../docker-compose.yml) diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml new file mode 100644 index 0000000..60865da --- /dev/null +++ b/docker-compose-dev.yml @@ -0,0 +1,17 @@ +version: "3" + +services: + pasteme-lite: + build: . + container_name: pasteme-lite + healthcheck: + test: ["CMD", "wget", "localhost:8000/?method=beat", "--output=/dev/null"] + interval: 45s + timeout: 3s + retries: 3 + restart: always + volumes: + - ./backend/data/:/data/ + #- ./frontend/usr/:/pasteme_frontend/usr/ + ports: + - 80:8000 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1fe456c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,17 @@ +version: "3" + +services: + pasteme-lite: + image: registry.cn-hangzhou.aliyuncs.com/pasteus/pasteme-lite:0.0.1 + container_name: pasteme-lite + healthcheck: + test: ["CMD", "wget", "localhost:8000/?method=beat", "--output=/dev/null"] + interval: 45s + timeout: 3s + retries: 3 + restart: always + volumes: + - ./backend/data/:/data/ + #- ./frontend/usr/:/pasteme_frontend/usr/ + ports: + - 80:8000 diff --git a/server.go b/server.go new file mode 100644 index 0000000..39181b5 --- /dev/null +++ b/server.go @@ -0,0 +1,49 @@ +/* +@File: server.go +@Contact: lucien@lucien.ink +@Licence: (C)Copyright 2019 Lucien Shui + +@Modify Time @Author @Version @Description +------------ ------- -------- ----------- +2019-06-21 08:37 Lucien 1.0 Init +*/ +package server + +import ( + "fmt" + "github.com/PasteUs/PasteMeGoBackend/flag" + "github.com/gin-gonic/gin" + "github.com/wonderivan/logger" +) + +var router *gin.Engine + +func init() { + if !flag.Debug { + gin.SetMode(gin.ReleaseMode) + } + router = gin.Default() + + api := router.Group("/api") + { + api.GET("/", beat) + api.GET("/:token", query) + api.POST("/", permanentCreator) + api.POST("/once", readOnceCreator) + api.PUT("/:key", temporaryCreator) + // router.NoRoute(notFoundHandler) + } + + router.Static("/pasteme_frontend/", "pasteme_frontend/") + router.Static("/usr/", "pasteme_frontend/usr/") + + router.NoRoute(func(requests *gin.Context) { + requests.File("pasteme_frontend/index.html") + }) +} + +func Run(address string, port uint16) { + if err := router.Run(fmt.Sprintf("%s:%d", address, port)); err != nil { + logger.Painc("Run server failed: " + err.Error()) + } +} diff --git a/vue.config.js b/vue.config.js new file mode 100644 index 0000000..ee70c46 --- /dev/null +++ b/vue.config.js @@ -0,0 +1,101 @@ +const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; + +let webPath = '/pasteme_frontend/'; + +const cdn = { + // 开发环境 + dev: { + css: [ + "https://shadow.elemecdn.com/npm/katex@0.11.0/dist/katex.min.css", + "https://cdn.staticfile.org/github-markdown-css/3.0.1/github-markdown.min.css", + "https://shadow.elemecdn.com/npm/bootstrap@4.3.1/dist/css/bootstrap.min.css", + "https://shadow.elemecdn.com/npm/bootstrap-vue@2.0.0-rc.28/dist/bootstrap-vue.min.css" + ], + js: [ + "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.15.9/build/highlight.min.js" + ] + }, + // 生产环境 + build: { + css: [ + "https://shadow.elemecdn.com/npm/katex@0.11.0/dist/katex.min.css", + "https://cdn.staticfile.org/github-markdown-css/3.0.1/github-markdown.min.css", + "https://shadow.elemecdn.com/npm/bootstrap@4.3.1/dist/css/bootstrap.min.css", + "https://shadow.elemecdn.com/npm/bootstrap-vue@2.0.0-rc.28/dist/bootstrap-vue.min.css" + ], + js: [ + 'https://shadow.elemecdn.com/npm/vue@2.6.10/dist/vue.runtime.min.js', + 'https://shadow.elemecdn.com/npm/vue-router@3.1.2/dist/vue-router.min.js', + 'https://shadow.elemecdn.com/npm/vuex@3.1.1/dist/vuex.min.js', + 'https://shadow.elemecdn.com/npm/axios@0.19.0/dist/axios.min.js', + 'https://shadow.elemecdn.com/npm/katex@0.11.0/dist/katex.min.js', + "https://shadow.elemecdn.com/npm/mermaid@8.2.3/dist/mermaid.min.js", + "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.15.9/build/highlight.min.js", + "https://cdn.jsdelivr.net/npm/d3@5.9.7/dist/d3.min.js", + "https://shadow.elemecdn.com/npm/bootstrap-vue@2.0.0-rc.28/dist/bootstrap-vue.min.js", + "https://cdn.jsdelivr.net/npm/markdown-it@9.1.0/dist/markdown-it.min.js", + "https://cdn.jsdelivr.net/npm/unorm@1.6.0/lib/unorm.min.js", + "https://cdn.jsdelivr.net/npm/@chenfengyuan/vue-qrcode@1.0.1/dist/vue-qrcode.min.js", + "https://cdn.jsdelivr.net/npm/vue-i18n@8.14.0/dist/vue-i18n.min.js" + ] + } +}; + +module.exports = { + devServer: { + proxy: { + "/usr": { + secure: false, + target: "http://dev.pasteme.lucien.ink", + changeOrigin: true + }, + "/api": { + secure: false, + target: "http://dev.pasteme.lucien.ink", + changeOrigin: true + } + } + }, + publicPath: process.env.NODE_ENV === 'production' ? webPath : '/', + outputDir: 'pasteme_frontend', + productionSourceMap: false, + configureWebpack: config => { // eslint-disable-line + if (process.env.NODE_ENV === 'production') { + config.plugins.push(new BundleAnalyzerPlugin({ + analyzerMode: "static" + })); + config.externals = { + "vue": "Vue", + "vuex": "Vuex", + "vue-router": "VueRouter", + "katex": "katex", + "axios": "axios", + "mermaid": "mermaid", + "highlight.js": "hljs", + "d3": "d3", + "bootstrap-vue": "BootstrapVue", + "markdown-it": "markdownit", + "unorm": "unorm", + "@chenfengyuan/vue-qrcode": "VueQrcode", + "vue-i18n": "VueI18n" + }; + } + return { + output: { + libraryExport: 'default', + jsonpFunction: 'jsonpFunction' + } + } + }, + chainWebpack: config => { + config.plugin('html').tap(args => { + if (process.env.NODE_ENV === 'production') { + args[0].cdn = cdn.build + } + if (process.env.NODE_ENV === 'development') { + args[0].cdn = cdn.dev + } + return args + }) + } +};