docs: file a release document (#12)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index d874156..0000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,148 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-name: Release
-
-on:
-  push:
-    tags:
-      - 'v*' # Run workflow on version tags, e.g. v1.0.0.
-
-jobs:
-  release:
-    runs-on: ubuntu-latest
-    env:
-      GRAFANA_API_KEY: ${{ secrets.GRAFANA_API_KEY }} # Requires a Grafana API key from Grafana.com.
-    steps:
-      - uses: actions/checkout@v3
-
-      - name: Setup Node.js environment
-        uses: actions/setup-node@v3
-        with:
-          node-version: '16'
-          cache: 'yarn'
-
-      - name: Setup Go environment
-        uses: actions/setup-go@v3
-        with:
-          go-version: '1.19'
-
-      - name: Install dependencies
-        run: yarn install --immutable --prefer-offline
-
-      - name: Build and test frontend
-        run: yarn build
-
-      - name: Check for backend
-        id: check-for-backend
-        run: |
-          if [ -f "Magefile.go" ]
-          then
-            echo "has-backend=true" >> $GITHUB_OUTPUT
-          fi
-
-      - name: Test backend
-        if: steps.check-for-backend.outputs.has-backend == 'true'
-        uses: magefile/mage-action@v2
-        with:
-          version: latest
-          args: coverage
-
-      - name: Build backend
-        if: steps.check-for-backend.outputs.has-backend == 'true'
-        uses: magefile/mage-action@v2
-        with:
-          version: latest
-          args: buildAll
-
-      - name: Warn missing Grafana API key
-        run: |
-          echo Please generate a Grafana API key: https://grafana.com/docs/grafana/latest/developers/plugins/sign-a-plugin/#generate-an-api-key
-          echo Once done please follow the instructions found here: https://github.com/${{github.repository}}/blob/main/README.md#using-github-actions-release-workflow
-        if: ${{ env.GRAFANA_API_KEY == '' }}
-
-      - name: Sign plugin
-        run: yarn sign
-        if: ${{ env.GRAFANA_API_KEY != '' }}
-
-      - name: Get plugin metadata
-        id: metadata
-        run: |
-          sudo apt-get install jq
-
-          export GRAFANA_PLUGIN_ID=$(cat dist/plugin.json | jq -r .id)
-          export GRAFANA_PLUGIN_VERSION=$(cat dist/plugin.json | jq -r .info.version)
-          export GRAFANA_PLUGIN_TYPE=$(cat dist/plugin.json | jq -r .type)
-          export GRAFANA_PLUGIN_ARTIFACT=${GRAFANA_PLUGIN_ID}-${GRAFANA_PLUGIN_VERSION}.zip
-          export GRAFANA_PLUGIN_ARTIFACT_CHECKSUM=${GRAFANA_PLUGIN_ARTIFACT}.md5
-
-          echo "plugin-id=${GRAFANA_PLUGIN_ID}" >> $GITHUB_OUTPUT
-          echo "plugin-version=${GRAFANA_PLUGIN_VERSION}" >> $GITHUB_OUTPUT
-          echo "plugin-type=${GRAFANA_PLUGIN_TYPE}" >> $GITHUB_OUTPUT
-          echo "archive=${GRAFANA_PLUGIN_ARTIFACT}" >> $GITHUB_OUTPUT
-          echo "archive-checksum=${GRAFANA_PLUGIN_ARTIFACT_CHECKSUM}" >> $GITHUB_OUTPUT
-
-          echo "github-tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT
-
-      - name: Read changelog
-        id: changelog
-        run: |
-          awk '/^## / {s++} s == 1 {print}' CHANGELOG.md > release_notes.md
-          echo "path=release_notes.md" >> $GITHUB_OUTPUT
-
-      - name: Check package version
-        run: if [ "v${{ steps.metadata.outputs.plugin-version }}" != "${{ steps.metadata.outputs.github-tag }}" ]; then printf "\033[0;31mPlugin version doesn't match tag name\033[0m\n"; exit 1; fi
-
-      - name: Package plugin
-        id: package-plugin
-        run: |
-          mv dist ${{ steps.metadata.outputs.plugin-id }}
-          zip ${{ steps.metadata.outputs.archive }} ${{ steps.metadata.outputs.plugin-id }} -r
-          md5sum ${{ steps.metadata.outputs.archive }} > ${{ steps.metadata.outputs.archive-checksum }}
-          echo "checksum=$(cat ./${{ steps.metadata.outputs.archive-checksum }} | cut -d' ' -f1)" >> $GITHUB_OUTPUT
-
-      - name: Validate plugin
-        run: |
-          git clone https://github.com/grafana/plugin-validator
-          pushd ./plugin-validator/pkg/cmd/plugincheck2
-          go install
-          popd
-          plugincheck2 -config ./plugin-validator/config/default.yaml ${{ steps.metadata.outputs.archive }}
-
-      - name: Create Github release
-        uses: softprops/action-gh-release@v1
-        with:
-          draft: true
-          generate_release_notes: true
-          files: |
-            ./${{ steps.metadata.outputs.archive }}
-            ./${{ steps.metadata.outputs.archive-checksum }}
-          body: |
-            **This Github draft release has been created for your plugin.**
-
-            _Note: if this is the first release for your plugin please consult the [distributing-your-plugin section](https://github.com/${{github.repository}}/blob/main/README.md#distributing-your-plugin) of the README_
-
-            If you would like to submit this release to Grafana please consider the following steps:
-
-            - Check the Validate plugin step in the [release workflow](https://github.com/${{github.repository}}/commit/${{github.sha}}/checks/${{github.run_id}}) for any warnings that need attention
-            - Navigate to https://grafana.com/auth/sign-in/ to sign into your account
-            - Once logged in click **My Plugins** in the admin navigation
-            - Click the **Submit Plugin** button
-            - Fill in the Plugin Submission form:
-              - Paste this [.zip asset link](https://github.com/${{ github.repository }}/releases/download/v${{ steps.metadata.outputs.plugin-version }}/${{ steps.metadata.outputs.archive }}) in the Plugin URL field
-              - Paste this [.zip.md5 link](https://github.com/${{ github.repository }}/releases/download/v${{ steps.metadata.outputs.plugin-version }}/${{ steps.metadata.outputs.archive-checksum }}) in the MD5 field
-
-            Once done please remove these instructions and publish this release.
diff --git a/.gitignore b/.gitignore
index 97eb6f6..ae4f940 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,7 @@
 
 # Compiled binary addons (https://nodejs.org/api/addons.html)
 dist/
+release/
 artifacts/
 work/
 ci/
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..c5436cd
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,61 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+SHELL := /bin/bash -o pipefail
+
+VERSION ?= latest
+RELEASE_SRC = skywalking-grafana-plugins-${VERSION}-src
+
+GPG_UID :=
+
+# set gpg user id
+ifdef GPG_UID
+	GPG_UID_FLAG := -u $(GPG_UID)
+endif
+
+.PHONY: release-src
+release-src:
+	tar -zcvf $(RELEASE_SRC).tgz \
+	--exclude .git/ \
+	--exclude .idea/ \
+	--exclude .gitignore \
+	--exclude .DS_Store \
+	--exclude .github \
+	--exclude lib \
+	--exclude node_modules \
+	--exclude release \
+	--exclude $(RELEASE_SRC).tgz \
+	.
+
+	gpg $(GPG_UID_FLAG) --batch --yes --armor --detach-sig $(RELEASE_SRC).tgz
+	shasum -a 512 $(RELEASE_SRC).tgz > $(RELEASE_SRC).tgz.sha512
+
+	mkdir -p release
+	mv $(RELEASE_SRC).tgz release/$(RELEASE_SRC).tgz
+	mv $(RELEASE_SRC).tgz.asc release/$(RELEASE_SRC).tgz.asc
+	mv $(RELEASE_SRC).tgz.sha512 release/$(RELEASE_SRC).tgz.sha512
+
+.PHONY: install
+install:
+	yarn install
+
+.PHONY: clean
+clean:
+	rm -rf ./node_modules && \
+	rm -rf ./lib
+
+.PHONY: build
+build:
+	yarn build
diff --git a/release.md b/release.md
new file mode 100644
index 0000000..c99708b
--- /dev/null
+++ b/release.md
@@ -0,0 +1,174 @@
+# Release Guide
+All committer should follow these steps to do release for this repo.
+
+1. Update the [package version](package.json) and [CHANGES.md](CHANGES.md) to prepare the official release.
+
+2. Package the source release.
+
+```shell
+> export VERSION=x.y.z
+> make release-src
+```
+
+Use SVN to upload the files(tgz, asc and sha512) in the `release` folder to `https://dist.apache.org/repos/dist/dev/skywalking/grafana-plugins/x.y.z`.
+
+3. Make the internal announcements. Send an announcement mail in dev mail list.
+
+```
+[ANNOUNCE] SkyWalking Grafana Plugins x.y.z test build available
+
+The test build of x.y.z is available.
+
+We welcome any comments you may have, and will take all feedback into
+account if a quality vote is called for this build.
+
+Release notes:
+
+ * https://github.com/apache/skywalking-grafana-plugins/blob/vx.y.z/CHANGES.md
+
+Release Candidate:
+
+ * https://dist.apache.org/repos/dist/dev/skywalking/grafana-plugins/x.y.z/
+ * sha512 checksums
+   - xxxxxxx  skywalking-grafana-plugins-x.y.z-src.tgz
+
+Release Tag :
+
+ * vx.y.z
+
+Release CommitID :
+
+ * https://github.com/apache/skywalking-grafana-plugins/tree/xxxxxxxxxx
+
+Keys to verify the Release Candidate :
+
+ * https://dist.apache.org/repos/dist/release/skywalking/KEYS
+
+
+A vote regarding the quality of this test build will be initiated
+within the next couple of days.
+```
+
+4. Wait at least 48 hours for test responses. If there is a critical issue found and confirmed by the PMC, this release should be cancelled.
+
+5. Call for a vote. Call a vote in dev@skywalking.apache.org
+
+```
+[VOTE] Release skywalking Grafana Plugins x.y.z
+
+This is a call for vote to release Apache SkyWalking Grafana Plugins version x.y.z.
+
+Release notes:
+
+ * https://github.com/apache/skywalking-grafana-plugins/blob/vx.y.z/CHANGES.md
+
+Release Candidate:
+
+ * https://dist.apache.org/repos/dist/dev/skywalking/grafana-plugins/x.y.z/
+ * sha512 checksums
+   - xxxxxxx  skywalking-grafana-plugins-x.y.z-src.tgz
+
+Release Tag :
+
+ * vx.y.z
+
+Release CommitID :
+
+ * https://github.com/apache/skywalking-grafana-plugins/tree/xxxxxxxxxx
+
+Keys to verify the Release Candidate :
+
+ * https://dist.apache.org/repos/dist/release/skywalking/KEYS
+
+
+Voting will start now (xxxx date) and will remain open for at least 72 hours, Request all PMC members to give their vote.
+[ ] +1 Release this package.
+[ ] +0 No opinion.
+[ ] -1 Do not release this package because....
+
+```
+
+5. Publish release, if vote passed.
+
+Move the release from RC folder to the dist folder. This will begin the file sync across the global Apache mirrors.
+```
+> export SVN_EDITOR=vim
+> svn mv https://dist.apache.org/repos/dist/dev/skywalking/grafana-plugins/x.y.z https://dist.apache.org/repos/dist/release/skywalking/grafana-plugins
+....
+enter your apache password
+....
+```
+
+Send ANNOUNCE email to `dev@skywalking.apache.org`, `announce@apache.org`, the sender should use Apache email account.
+```
+Mail title: [ANNOUNCE] Release Apache SkyWalking Grafana Plugins version x.y.z
+
+Mail content:
+Hi all,
+
+Apache SkyWalking  Team is glad to announce the first release of Apache SkyWalking Grafana Plugins x.y.z
+
+SkyWalking: APM (application performance monitor) tool for distributed systems,
+especially designed for microservices, cloud native and container-based (Docker, Kubernetes, Mesos) architectures.
+
+SkyWalking Grafana Plugins provide browser metrics and error collection to SkyWalking backend.
+
+This release contains a number of new features, bug fixes and improvements compared to
+version a.b.c(last release). The notable changes since x.y.z include:
+
+(Highlight key changes)
+1. ...
+2. ...
+3. ...
+
+Please refer to the change log for the complete list of changes:
+https://github.com/apache/skywalking-grafana-plugins/blob/x.y.z/CHANGES.md
+
+Apache SkyWalking website:
+http://skywalking.apache.org/
+
+Downloads:
+http://skywalking.apache.org/downloads/
+
+Twitter:
+https://twitter.com/ASFSkyWalking
+
+SkyWalking Resources:
+- GitHub: https://github.com/apache/skywalking
+- Issue: https://github.com/apache/skywalking/issues
+- Mailing list: dev@skywalkiing.apache.org
+
+
+- Apache SkyWalking Team
+```
+
+6. publish package to Grafana Cloud
+
+  1. Build the plugin
+
+  ```bash
+  > yarn install --pure-lockfile
+  > yarn build
+  ```
+
+  2. [Sign in](https://grafana.com/auth/sign-in) to Grafana Cloud account,the username is `wusheng@apache.org` and the password has been sent to `private@skwalking.apache.org`.
+
+    * In the left menu, under Org settings, click My Plugins.
+
+    * Click Submit Update for the plugin you want to update.
+
+    * Enter the information requested by the form.
+
+      OS & Architecture:
+
+        Select Single if your plugin archive contains binaries for multiple architectures.
+
+        Select Multiple if you’d like to submit separate plugin archives for each architecture. This can lead to faster downloads since users can select the specific architecture they want to install the plugin on.
+
+      URL: A URL that points to a ZIP archive of your packaged plugin.
+
+      Source Code URL: A URL that points to a public git repository or ZIP archive of your complete plugin source code.
+
+      MD5: The MD5 hash of the plugin specified by the URL.
+
+    * Click Submit.