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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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
+ })
+ }
+};