Publish from Gitea: releases, CI and install docs

Gitea implements no Terraform provider registry, so distribution goes
through release archives plus a filesystem mirror. GoReleaser targets
the Gitea release API; the archive names follow HashiCorp's convention
because that is the only shape a filesystem mirror recognises.

No GPG signing: signatures are a registry-protocol requirement and a
filesystem mirror never checks them.

Cross-repo links point at Gitea; Go module paths deliberately do not.
This commit is contained in:
2026-08-09 12:37:07 +03:00
parent a6d8aa8b52
commit abe4444d2b
4 changed files with 198 additions and 10 deletions

View File

@@ -0,0 +1,40 @@
name: build
on:
push:
branches: [main]
pull_request:
workflow_dispatch: {}
env:
GO_VERSION: "1.25.x"
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache-dependency-path: go.sum
- name: Format
run: test -z "$(gofmt -l .)" || { gofmt -l .; echo "run gofmt -w ."; exit 1; }
- name: Vet
run: go vet ./...
- name: Build
run: go build ./...
- name: Test
run: go test ./... -count=1
# The bridge in pulumi-dokploy reaches the provider through `shim`, and
# `internal/provider` is not importable from outside this module. If that
# entry point ever stops compiling on its own, the Pulumi build breaks
# somewhere far away from the cause.
- name: The shim package still builds standalone
run: go build ./shim/

View File

@@ -0,0 +1,27 @@
name: release
on:
push:
tags: ["v*.*.*"]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# GoReleaser builds the changelog from history, so a shallow clone
# would produce an empty one.
fetch-depth: 0
- uses: actions/setup-go@v5
with:
go-version: "1.25.x"
- uses: goreleaser/goreleaser-action@v6
with:
version: latest
args: release --clean
env:
# Injected by Gitea for every workflow run; no personal token needed.
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}

89
.goreleaser.yml Normal file
View File

@@ -0,0 +1,89 @@
# Publishes provider binaries to a Gitea release.
#
# Gitea has no Terraform provider registry -- that protocol is not one of the
# ~20 package types it implements -- so these archives are consumed through a
# filesystem mirror instead. See "Installing" in the README.
#
# The archive names follow HashiCorp's convention
# (terraform-provider-NAME_VERSION_OS_ARCH.zip) because a filesystem mirror
# recognises exactly that shape, and nothing else.
version: 2
project_name: terraform-provider-dokploy
before:
hooks:
- go mod download
builds:
- id: provider
main: .
binary: "{{ .ProjectName }}_v{{ .Version }}"
env:
- CGO_ENABLED=0
flags:
- -trimpath
ldflags:
- -s -w
- -X main.version={{ .Version }}
goos:
- darwin
- linux
- windows
- freebsd
goarch:
- amd64
- arm64
- "386"
ignore:
- goos: darwin
goarch: "386"
archives:
- id: provider
formats: [zip]
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
files:
- none*
checksum:
name_template: "{{ .ProjectName }}_{{ .Version }}_SHA256SUMS"
algorithm: sha256
# No `signs:` block on purpose. GPG signatures are required by the Terraform
# *registry* protocol; a filesystem mirror never checks them. Adding signing
# here would imply a verification step that nothing performs.
changelog:
use: git
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
- "^chore:"
gitea_urls:
api: https://gitea.coolify.vojtkov.dev/api/v1
download: https://gitea.coolify.vojtkov.dev
release:
gitea:
owner: usr_unknown
name: terraform-provider-dokploy
header: |
## terraform-provider-dokploy {{ .Tag }}
Gitea cannot serve the Terraform registry protocol, so install through a
filesystem mirror:
```bash
VERSION={{ trimprefix .Tag "v" }}
OS_ARCH="$(go env GOOS)_$(go env GOARCH)"
DEST=~/.local/share/terraform/plugins/registry.terraform.io/maxvojtkov/dokploy/$VERSION/$OS_ARCH
mkdir -p "$DEST"
unzip -j terraform-provider-dokploy_${VERSION}_${OS_ARCH}.zip -d "$DEST"
```
Then point Terraform at the mirror -- the exact `~/.terraformrc` block is
printed by `make install`.

View File

@@ -56,8 +56,32 @@ resource "dokploy_domain" "api" {
## Installing
The provider is not published to a registry yet. Build it and install it into a
local filesystem mirror:
This provider is distributed through
[Gitea releases](https://gitea.coolify.vojtkov.dev/usr_unknown/terraform-provider-dokploy/releases),
not a Terraform registry — Gitea implements about twenty package registries,
and the Terraform provider protocol is not one of them. So installation goes
through a **filesystem mirror**, which is Terraform's supported way to use a
provider that no registry serves.
### From a release
```bash
VERSION=0.1.0
OS_ARCH="$(go env GOOS)_$(go env GOARCH)"
BASE=https://gitea.coolify.vojtkov.dev/usr_unknown/terraform-provider-dokploy/releases/download
DEST=~/.local/share/terraform/plugins/registry.terraform.io/maxvojtkov/dokploy/$VERSION/$OS_ARCH
mkdir -p "$DEST"
curl -fsSLO "$BASE/v$VERSION/terraform-provider-dokploy_${VERSION}_${OS_ARCH}.zip"
unzip -j "terraform-provider-dokploy_${VERSION}_${OS_ARCH}.zip" -d "$DEST"
```
Each release also carries a `_SHA256SUMS` file, worth checking before you
unzip. There are no GPG signatures: those are required by the registry
protocol, and a filesystem mirror never verifies them, so publishing one would
imply a check that nothing performs.
### From source
```bash
make install
@@ -202,7 +226,7 @@ auth and redirects — behind one call:
```hcl
module "storefront" {
source = "github.com/maxvojtkov/terraform-provider-dokploy//modules/web-service"
source = "git::https://gitea.coolify.vojtkov.dev/usr_unknown/terraform-provider-dokploy.git//modules/web-service"
name = "storefront"
environment_id = dokploy_project.shop.default_environment_id
@@ -253,13 +277,13 @@ curl -X POST "$DOKPLOY_HOST/api/application.deploy" \
### From CI
[`dokploy-deploy-action`](https://github.com/maxvojtkov/dokploy-deploy-action)
[`dokploy-deploy-action`](https://gitea.coolify.vojtkov.dev/usr_unknown/dokploy-deploy-action)
is the same call with the parts that matter in a pipeline: it waits for the
build, fails the job when the deployment fails, and prints the build log.
It runs on GitHub Actions and Gitea Actions.
```yaml
- uses: maxvojtkov/dokploy-deploy-action@v1
- uses: https://gitea.coolify.vojtkov.dev/usr_unknown/dokploy-deploy-action@v1
with:
host: ${{ secrets.DOKPLOY_HOST }}
api-key: ${{ secrets.DOKPLOY_API_KEY }}
@@ -325,11 +349,13 @@ Because this is a standard Terraform provider, Pulumi consumes it through
[`pulumi-terraform-bridge`](https://github.com/pulumi/pulumi-terraform-bridge)
— no reimplementation needed. Two routes:
**Dynamic bridge (no build step).** Point Pulumi at the provider binary and use
it straight away:
**Dynamic bridge (no build step).** Point Pulumi at a provider binary and use
it straight away. The usual `owner/name` shorthand resolves through the
Terraform registry, which does not serve this provider, so give a path
instead — `make build` produces one:
```bash
pulumi package add terraform-provider maxvojtkov/dokploy
pulumi package add terraform-provider ./terraform-provider-dokploy
```
Pulumi generates an SDK for your language on the spot. This is the fastest path
@@ -337,8 +363,9 @@ and keeps you in lockstep with the Terraform provider.
**Static bridge (a published SDK).** For a first-class, versioned package with
richer types, use
[`pulumi-dokploy`](https://github.com/maxvojtkov/pulumi-dokploy), which wraps
this provider and ships SDKs for TypeScript, Python, Go and .NET:
[`pulumi-dokploy`](https://gitea.coolify.vojtkov.dev/usr_unknown/pulumi-dokploy), which wraps
this provider and ships SDKs for TypeScript, Python, Go and .NET from this
Gitea instance's package registries:
```bash
npm install @maxvojtkov/pulumi-dokploy
@@ -347,6 +374,11 @@ go get github.com/maxvojtkov/pulumi-dokploy/sdk/go/dokploy
dotnet add package Maxvojtkov.Dokploy
```
Each of those needs its registry pointed at Gitea first — the one-time
configuration per language is in that repository's
[Installing](https://gitea.coolify.vojtkov.dev/usr_unknown/pulumi-dokploy#installing)
section.
That repository holds nothing but the mapping — every resource, schema and API
call still comes from here, so the two providers move together.