# ci/cd for the public nostermd relay. # # - every push/pr: gofmt check, vet, test, build. # - push to main / a v* tag: also build the image and push it to ecr public # (anonymous pulls) so anyone can `docker pull` it. # # this is the public contribution repo — it builds and ships only the relay # image to the public registry. it never touches private ecr or redeploys any # environment; promoting an image to a live relay is handled out of band. # # gitea 1.21 actions on a self-hosted (ec2) runner. aws auth uses the runner's # ambient iam role (no stored creds): `aws ecr-public get-login-password` mints # a short-lived token for `docker login`. the runner role needs ecr public push # perms (ecr-public:GetAuthorizationToken, sts:GetServiceBearerToken, # BatchCheckLayerAvailability, Put*/Upload*/Complete*). name: ci env: # ecr public always authenticates via the us-east-1 endpoint. AWS_REGION: us-east-1 # public mirror for anonymous pulls. k3k1z1x5 is the account's ecr public # registry alias; the repo name (nostermd) is provisioned out of band. ECR_PUBLIC_REGISTRY: public.ecr.aws/k3k1z1x5 ECR_PUBLIC_REPO: nostermd on: push: branches: [main] tags: ['v*'] pull_request: jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Go uses: actions/setup-go@v5 with: go-version: '1.25' - name: Verify formatting (gofmt) run: | unformatted="$(gofmt -l .)" if [ -n "$unformatted" ]; then echo "These files are not gofmt-clean:" echo "$unformatted" exit 1 fi - name: Vet run: go vet ./... # no -race: go-nostr's unsafe json serializer trips the detector during # event signing (upstream lib issue, not a relay race). see README.md#tests. - name: Test run: go test ./... - name: Build run: go build -trimpath -o /dev/null ./cmd/nostermd image: needs: build # publish only from the default branch and version tags, never from prs. if: gitea.event_name == 'push' && (gitea.ref == 'refs/heads/main' || startsWith(gitea.ref, 'refs/tags/v')) runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Install AWS CLI # runner image ships without aws; install v2 if it's missing. run: | if ! command -v aws >/dev/null 2>&1; then apt-get update -qq apt-get install -y -qq curl unzip curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip unzip -q /tmp/awscliv2.zip -d /tmp /tmp/aws/install fi aws --version - name: Log in to Amazon ECR Public # ecr public auth is a separate endpoint (always us-east-1) with its own # login user (AWS). this is push auth; anonymous pulls need no login. run: | aws ecr-public get-login-password --region us-east-1 \ | docker login --username AWS --password-stdin public.ecr.aws - name: Build and push image shell: bash run: | set -eo pipefail IMAGE="$ECR_PUBLIC_REGISTRY/$ECR_PUBLIC_REPO" # tag by commit sha for traceability. docker build -t "$IMAGE:${{ gitea.sha }}" . docker push "$IMAGE:${{ gitea.sha }}" # move :latest only on main. if [ "${{ gitea.ref }}" = "refs/heads/main" ]; then docker tag "$IMAGE:${{ gitea.sha }}" "$IMAGE:latest" docker push "$IMAGE:latest" fi # on a v* tag, also push that version tag. case "${{ gitea.ref }}" in refs/tags/v*) VERSION="${{ gitea.ref_name }}" docker tag "$IMAGE:${{ gitea.sha }}" "$IMAGE:$VERSION" docker push "$IMAGE:$VERSION" ;; esac