Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/otto-commitlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Otto Conventional Commits

on:
pull_request_target:
paths:
- "otto/**"
types: [opened, edited, synchronize, reopened]

jobs:
semantic-pull-request:
name: Validate PR title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
133 changes: 133 additions & 0 deletions .github/workflows/otto-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
name: Otto Release

# PR-based release trigger only
on:
pull_request:
types: [closed]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure if we should change this in this pull request, but this would run on a pr close (which could be a merge, but also could be a "i'm closing this pull request"). I think release should only run on push to main.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re: Releasing

semantic-release and go-semantic-release are pretty standard for doing releases in the industry. They're fairly opinionated, but quite good. they rely of course on the conventional commits standard.

These are usually my default recommendation when doing any type of trunk based development. Of course, you can make the workflow a dispatch.

Neither of those tools support monorepo versioning from the perspective of multiple versions within a single repo based on path. That may be ok. Since otto doesn't publish versions of it's internal modules to be consumed, then there's no need to try to add multiple versions unless you want a prefix.

I'm generally not a fan of pull request based releases (release-please-esq). I will absolutely concede though to the wider decision.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want, I can try to find sometime to push a change here.

branches:
- main
paths:
- 'otto/**'

permissions:
contents: write
packages: write

jobs:
# PR-based tag creation (only runs on merged PRs with release label)
create-release:
if: |
github.event.pull_request.merged == true &&
contains(github.event.pull_request.labels.*.name, 'release')
runs-on: ubuntu-latest
outputs:
tag_name: ${{ steps.create_tag.outputs.tag_name }}
release_created: ${{ steps.create_tag.outputs.release_created }}

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Determine release type
id: release_type
run: |
RELEASE_TYPE="patch"

if contains(github.event.pull_request.labels.*.name, 'release:major'); then
RELEASE_TYPE="major"
elif contains(github.event.pull_request.labels.*.name, 'release:minor'); then
RELEASE_TYPE="minor"
fi

echo "release_type=$RELEASE_TYPE" >> $GITHUB_OUTPUT

- name: Calculate next version with svu
id: svu
uses: charlesthomas/github-action-svu@v1.0.2
with:
type: ${{ steps.release_type.outputs.release_type }}
working-directory: otto
# Ensure prefix is set correctly
prefix: "v"
# Handle case when no previous tags exist
fallback: "0.1.0"
# Use the same configuration as in .svu.yml
metadata: false
pre: false

- name: Create tag
id: create_tag
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NEW_VERSION: v${{ steps.svu.outputs.version }}
run: |
# Extract PR title and body for release notes
PR_TITLE="${{ github.event.pull_request.title }}"
PR_NUMBER="${{ github.event.pull_request.number }}"

git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"

# Create and push tag
echo "Creating tag $NEW_VERSION"
git tag -a "$NEW_VERSION" -m "Release $NEW_VERSION from PR #$PR_NUMBER: $PR_TITLE"
git push origin "$NEW_VERSION"

echo "tag_name=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "release_created=true" >> $GITHUB_OUTPUT

# Main release job - runs after tag creation
goreleaser:
needs: [create-release]
if: needs.create-release.outputs.release_created == 'true'
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./otto
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
# Use the newly created tag
ref: ${{ needs.create-release.outputs.tag_name }}

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: ./otto/go.mod
cache: true

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Install cosign for artifact signing
- name: Install cosign
uses: sigstore/cosign-installer@v3.4.0
with:
cosign-release: 'v2.2.2'

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: latest
args: release --clean
workdir: ./otto
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# These secrets need to be set in the repository settings
COSIGN_KEY: ${{ secrets.COSIGN_KEY }}
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
58 changes: 46 additions & 12 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ on:
push:
branches: [main]
paths:
- "otto/**"
- 'otto/**'
- '.github/workflows/test.yml'
pull_request:
branches: [main]
paths:
- "otto/**"
- 'otto/**'
- '.github/workflows/test.yml'

jobs:
test:
Expand Down Expand Up @@ -42,15 +44,47 @@ jobs:
working-directory: ./otto

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24.x
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24.x

- name: Run linter
uses: golangci/golangci-lint-action@v7
with:
version: latest
working-directory: otto
- name: Run linter
uses: golangci/golangci-lint-action@v7
with:
version: latest
working-directory: otto
build:
name: Build Check
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./otto
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24.x
cache: true
cache-dependency-path: otto/go.sum

- name: Build binary
run: make build

- name: Check GoReleaser config
uses: goreleaser/goreleaser-action@v6
with:
version: latest
args: check
workdir: ./otto

- name: Test Docker build
uses: goreleaser/goreleaser-action@v6
with:
version: latest
args: build --snapshot --clean --single-target
workdir: ./otto
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
otto/config.yaml
otto/secrets.yaml
otto/.env
otto/*.pem
otto/dist
.DS_Store
130 changes: 130 additions & 0 deletions otto/.goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
version: 2

# Force project name to be "otto"
project_name: otto

# Signing configuration for binaries
signs:
- cmd: cosign
args:
- "sign-blob"
- "--key=${env.COSIGN_KEY}"
- "--output-signature=${signature}"
- "${artifact}"
artifacts: checksum
stdin: "{{ .Env.COSIGN_PASSWORD }}"
signature: "${artifact}.sig"

before:
hooks:
- go mod tidy

builds:
- id: otto
binary: otto
main: ./cmd/otto
env:
- CGO_ENABLED=0
goos:
- linux
- darwin
goarch:
- amd64
- arm64
# Ignore combinations that don't exist
ignore:
- goos: darwin
goarch: "386"
flags:
- -trimpath
ldflags:
- -s -w -X github.com/open-telemetry/sig-project-infra/otto/internal.Version={{.Version}}

dockers:
- image_templates:
- "ghcr.io/open-telemetry/sig-project-infra/otto:{{ .Version }}-amd64"
- "ghcr.io/open-telemetry/sig-project-infra/otto:latest-amd64"
dockerfile: Dockerfile.goreleaser
use: docker
build_flag_templates:
- "--pull"
- "--platform=linux/amd64"
- "--label=org.opencontainers.image.created={{.Date}}"
- "--label=org.opencontainers.image.title=Otto"
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
- "--label=org.opencontainers.image.version={{.Version}}"
- "--label=org.opencontainers.image.source=https://github.com/open-telemetry/sig-project-infra"
- "--label=org.opencontainers.image.licenses=Apache-2.0"
ids:
- otto

- image_templates:
- "ghcr.io/open-telemetry/sig-project-infra/otto:{{ .Version }}-arm64"
- "ghcr.io/open-telemetry/sig-project-infra/otto:latest-arm64"
dockerfile: Dockerfile.goreleaser
use: docker
build_flag_templates:
- "--pull"
- "--platform=linux/arm64"
- "--label=org.opencontainers.image.created={{.Date}}"
- "--label=org.opencontainers.image.title=Otto"
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
- "--label=org.opencontainers.image.version={{.Version}}"
- "--label=org.opencontainers.image.source=https://github.com/open-telemetry/sig-project-infra"
- "--label=org.opencontainers.image.licenses=Apache-2.0"
goarch: arm64
ids:
- otto

# Add docker manifests as suggested by adrielp
docker_manifests:
- name_template: ghcr.io/open-telemetry/sig-project-infra/otto:{{ .Version }}
image_templates:
- ghcr.io/open-telemetry/sig-project-infra/otto:{{ .Version }}-amd64
- ghcr.io/open-telemetry/sig-project-infra/otto:{{ .Version }}-arm64
- name_template: ghcr.io/open-telemetry/sig-project-infra/otto:latest
image_templates:
- ghcr.io/open-telemetry/sig-project-infra/otto:latest-amd64
- ghcr.io/open-telemetry/sig-project-infra/otto:latest-arm64

# Docker image signing configuration
docker_signs:
- cmd: cosign
args:
- "sign"
- "--key=${env.COSIGN_KEY}"
- "${artifact}"
artifacts: images
stdin: "{{ .Env.COSIGN_PASSWORD }}"

archives:
- id: default
name_template: >-
otto_
{{- .Version }}_
{{- .Os }}_
{{- .Arch }}
formats: [tar.gz]
format_overrides:
- goos: windows
formats: [zip]
files:
- LICENSE*
- README*
- CHANGELOG*
- config.example.yaml

checksum:
name_template: "checksums.txt"

snapshot:
version_template: "{{ incpatch .Version }}-next"

changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
- "^chore:"
- "^ci:"
7 changes: 7 additions & 0 deletions otto/.svu.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
tag.prefix: "v" # Prefix for version tags
pre.prefix: "" # Prefix for pre-release versions
build.prefix: "+" # Prefix for build metadata
metadata: false # Include metadata in the version
pre: false # Pre-release mode
no-metadata: true # Exclude metadata from the version
no-pre: true # Exclude pre-release info from the version
24 changes: 24 additions & 0 deletions otto/Dockerfile.goreleaser
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FROM scratch

# Copy SSL certificates for HTTPS requests
COPY --from=alpine:latest /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

# Set up the non-root user (needed for scratch image)
# Since scratch has no shell, we need to create user in /etc/passwd directly
COPY --from=alpine:latest /etc/passwd /etc/passwd
COPY --from=alpine:latest /etc/group /etc/group

# Copy the pre-built binary from the build stage
COPY otto /usr/local/bin/

# Expose the service port
EXPOSE 8080

# Set environment variables
ENV OTTO_ADDR=:8080

# Use non-root user
USER nobody

# Set the entry point
ENTRYPOINT ["/usr/local/bin/otto"]
Loading
Loading