diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..1d915cb --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,97 @@ +name: Release + +on: + push: + tags: + - 'v*' + workflow_dispatch: + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-24.04 + timeout-minutes: 45 + steps: + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 + with: + fetch-depth: 0 + + - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 + with: + go-version-file: go.mod + + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6 + with: + python-version: '3.13' + + - name: Determine version + id: version + run: | + if [[ "$GITHUB_REF" == refs/tags/v* ]]; then + tag="${GITHUB_REF_NAME}" + else + latest=$(git tag -l 'v*' --sort=-v:refname | head -n1) + if [ -z "$latest" ]; then + version=$(jq -r '.version' manifest.json) + else + base="${latest#v}" + IFS='.' read -r major minor patch <<< "$base" + version="${major}.${minor}.$((patch + 1))" + fi + tag="v${version}" + git tag "$tag" + git push origin "refs/tags/${tag}" + fi + echo "version=${tag#v}" >> "$GITHUB_OUTPUT" + echo "tag=${tag}" >> "$GITHUB_OUTPUT" + + - name: Build release archives + run: make dist VERSION="${{ steps.version.outputs.version }}" + + - name: Prepare release assets + # The Silo plugin catalog and server install raw binaries named + # plugin-- and verify them against checksums.txt. Publish + # those alongside the reproducible ZIP archives from `make dist`. + run: | + set -euo pipefail + version="${{ steps.version.outputs.version }}" + mkdir -p release + cp dist/*.zip release/ + cp dist/checksums.txt release/checksums.txt + for platform in linux-amd64 linux-arm64 darwin-arm64; do + archive="dist/silo-plugin-tailscale-${version}-${platform}.zip" + unzip -p "$archive" plugin > "release/plugin-${platform}" + chmod 0755 "release/plugin-${platform}" + (cd release && sha256sum "plugin-${platform}" >> checksums.txt) + done + cat release/checksums.txt + + - name: Create GitHub Release + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 + with: + tag_name: ${{ steps.version.outputs.tag }} + files: | + release/plugin-linux-amd64 + release/plugin-linux-arm64 + release/plugin-darwin-arm64 + release/*.zip + release/checksums.txt + generate_release_notes: true + + - name: Notify approved community catalog + env: + DISPATCH_TOKEN: ${{ secrets.SILO_PLUGINS_DISPATCH_TOKEN }} + run: | + if [ -z "$DISPATCH_TOKEN" ]; then + echo "::warning::SILO_PLUGINS_DISPATCH_TOKEN is not set; catalog was not notified." + exit 0 + fi + curl --fail --silent --show-error \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${DISPATCH_TOKEN}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/Silo-Community/silo-plugins/dispatches \ + -d "$(printf '{"event_type":"plugin_release_published","client_payload":{"repo":"Silo-Community/silo-plugin-tailscale","tag":"%s"}}' "${{ steps.version.outputs.tag }}")" diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..0105275 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @ironicbadger @Quick104 diff --git a/README.md b/README.md index 18105a4..835ae1e 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ Access Silo over HTTPS through your Tailscale network. No separate Tailscale dae ## Setup -Requires Silo’s [network-access support](https://github.com/Silo-Server/silo-server/pull/1096), with MagicDNS and HTTPS certificates enabled in Tailscale. +Requires a Silo server with network-access plugin support, with MagicDNS and HTTPS certificates enabled in Tailscale. -1. [Build the plugin](docs/DEVELOPMENT.md#build-and-verify), extract the ZIP, and upload its `plugin` executable to Silo. +1. Install **Tailscale** from the plugin catalog in Silo (enable **Include approved community plugins** in plugin settings). To install manually instead, [build the plugin](docs/DEVELOPMENT.md#build-and-verify), extract the ZIP, and upload its `plugin` executable. 2. Enable the plugin, choose a hostname, and optionally enter a Tailscale auth key. 3. Save, then select **Connect** in **Settings > Network Access**. Sign in if prompted. 4. Open the reported HTTPS URL from a device running Tailscale. @@ -20,3 +20,14 @@ Optional public access. Disabled by default. > Funnel is not well suited to streaming video. Proceed at your own risk. [Developer documentation](docs/DEVELOPMENT.md) + +## Community maintenance + +This is an approved community plugin maintained in the +[`Silo-Community`](https://github.com/Silo-Community) organization by +[ironicbadger](https://github.com/ironicbadger). Use +[GitHub Issues](https://github.com/Silo-Community/silo-plugin-tailscale/issues) +for support and bug reports. Security reports should follow +[`SECURITY.md`](SECURITY.md). + +Licensed under the [MIT License](LICENSE). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..88e8dbb --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,7 @@ +# Security Policy + +Please do not report security vulnerabilities in a public issue. + +Use GitHub's private vulnerability reporting for this repository: + +https://github.com/Silo-Community/silo-plugin-tailscale/security/advisories/new diff --git a/go.mod b/go.mod index 79c7469..656eafe 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/ironicbadger/silo-plugin-tailscale +module github.com/Silo-Community/silo-plugin-tailscale go 1.26.7 diff --git a/main.go b/main.go index c506980..1d6a951 100644 --- a/main.go +++ b/main.go @@ -8,11 +8,11 @@ import ( "os" "sync" + "github.com/Silo-Community/silo-plugin-tailscale/internal/tailscale" pluginv1 "github.com/Silo-Server/silo-plugin-sdk/pkg/pluginproto/silo/plugin/v1" "github.com/Silo-Server/silo-plugin-sdk/pkg/pluginsdk/manifest" sdkruntime "github.com/Silo-Server/silo-plugin-sdk/pkg/pluginsdk/runtime" "github.com/Silo-Server/silo-plugin-sdk/pkg/pluginsdk/runtimedefault" - "github.com/ironicbadger/silo-plugin-tailscale/internal/tailscale" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "tailscale.com/envknob" diff --git a/main_lifecycle_test.go b/main_lifecycle_test.go index 807bdaa..14d59fb 100644 --- a/main_lifecycle_test.go +++ b/main_lifecycle_test.go @@ -6,9 +6,9 @@ import ( "testing" "time" + "github.com/Silo-Community/silo-plugin-tailscale/internal/tailscale" pluginv1 "github.com/Silo-Server/silo-plugin-sdk/pkg/pluginproto/silo/plugin/v1" "github.com/Silo-Server/silo-plugin-sdk/pkg/pluginsdk/runtimehost" - "github.com/ironicbadger/silo-plugin-tailscale/internal/tailscale" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/structpb" diff --git a/manifest.json b/manifest.json index f54344a..1fab1e5 100644 --- a/manifest.json +++ b/manifest.json @@ -8,7 +8,12 @@ "summary": "Reach Silo through your tailnet without opening public ports.", "description_markdown": "Runs a separate Tailscale node on the API host and every proxy. Exposes the native, Jellyfin and Audiobookshelf listeners over HTTPS. Silo retains its existing authentication.", "setup_markdown": "Requires Silo's network-access plugin support, one API host, and MagicDNS plus HTTPS certificates enabled in Tailscale. Save an optional reusable auth key for automatic enrollment across proxies, then select Connect in Settings > Network Access. Otherwise use the authorization URL shown for each host.", + "homepage_url": "https://github.com/Silo-Community/silo-plugin-tailscale", + "source_url": "https://github.com/Silo-Community/silo-plugin-tailscale", + "support_url": "https://github.com/Silo-Community/silo-plugin-tailscale/issues", + "changelog_url": "https://github.com/Silo-Community/silo-plugin-tailscale/releases", "publisher_name": "ironicbadger", + "publisher_url": "https://github.com/ironicbadger", "license_spdx": "MIT" }, "supported_platforms": [ diff --git a/scripts/dist.py b/scripts/dist.py index efd40f3..c2488db 100644 --- a/scripts/dist.py +++ b/scripts/dist.py @@ -51,7 +51,7 @@ def notices(root, environment): if not entry: continue name, module_version, directory = entry.split("|", 2) - if name == "github.com/ironicbadger/silo-plugin-tailscale": + if name == "github.com/Silo-Community/silo-plugin-tailscale": continue files = [p for p in Path(directory).iterdir() if p.is_file() and p.name.upper().startswith(("LICENSE", "COPYING", "NOTICE", "COPYRIGHT"))]