1+ name : Build and Release
2+
3+ on :
4+ push :
5+ branches : [ main, master ]
6+ pull_request :
7+ branches : [ main, master ]
8+ release :
9+ types : [ published ]
10+
11+ env :
12+ REGISTRY : ghcr.io
13+ IMAGE_NAME : ${{ github.repository }}
14+
15+ jobs :
16+ test :
17+ name : Run Tests
18+ runs-on : ubuntu-latest
19+ steps :
20+ - name : Checkout code
21+ uses : actions/checkout@v4
22+
23+ - name : Set up Go
24+ uses : actions/setup-go@v4
25+ with :
26+ go-version : ' 1.21'
27+
28+ - name : Set up Node.js
29+ uses : actions/setup-node@v4
30+ with :
31+ node-version : ' 18'
32+
33+ - name : Cache Go modules
34+ uses : actions/cache@v3
35+ with :
36+ path : |
37+ ~/.cache/go-build
38+ ~/go/pkg/mod
39+ key : ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
40+ restore-keys : |
41+ ${{ runner.os }}-go-
42+
43+ - name : Cache Node modules
44+ uses : actions/cache@v3
45+ with :
46+ path : web/node_modules
47+ key : ${{ runner.os }}-node-${{ hashFiles('web/package-lock.json') }}
48+ restore-keys : |
49+ ${{ runner.os }}-node-
50+
51+ - name : Install Node.js dependencies
52+ run : cd web && npm ci
53+
54+ - name : Run tests
55+ run : make test
56+
57+ build-matrix :
58+ name : Build Binaries
59+ runs-on : ubuntu-latest
60+ needs : test
61+ if : github.event_name == 'push' || github.event_name == 'release'
62+ strategy :
63+ matrix :
64+ include :
65+ - os : linux
66+ arch : amd64
67+ - os : linux
68+ arch : arm64
69+ - os : darwin
70+ arch : amd64
71+ - os : darwin
72+ arch : arm64
73+
74+ steps :
75+ - name : Checkout code
76+ uses : actions/checkout@v4
77+
78+ - name : Set up Docker Buildx
79+ uses : docker/setup-buildx-action@v3
80+
81+ - name : Build for ${{ matrix.os }}/${{ matrix.arch }}
82+ run : |
83+ # Create build directory
84+ mkdir -p build
85+
86+ # Create platform-specific Dockerfile
87+ cat > Dockerfile.release << 'EOF'
88+ FROM node:18-alpine AS dashboard-builder
89+ WORKDIR /app
90+ COPY web/package*.json ./web/
91+ WORKDIR /app/web
92+ RUN npm ci --only=production
93+ COPY web/ .
94+ RUN npm run build
95+
96+ FROM golang:1.21-alpine AS go-builder
97+ ARG TARGETOS
98+ ARG TARGETARCH
99+ RUN apk add --no-cache git
100+ WORKDIR /app
101+ COPY . .
102+ COPY --from=dashboard-builder /app/web/dist ./internal/dashboard/web/dist
103+ RUN sed -i 's|replace github.com/dan-v/lambda-nat-punch-proxy => ..|replace github.com/dan-v/lambda-nat-punch-proxy => /app|' lambda/go.mod
104+ RUN go mod download && cd lambda && go mod download
105+ RUN cd lambda && GOOS=linux GOARCH=amd64 go build -o ../cmd/lambda-nat-proxy/assets/bootstrap .
106+ RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -a -installsuffix cgo -o lambda-nat-proxy ./cmd/lambda-nat-proxy
107+
108+ FROM scratch
109+ COPY --from=go-builder /app/lambda-nat-proxy .
110+ COPY --from=go-builder /app/cmd/lambda-nat-proxy/assets/bootstrap ./bootstrap
111+ EOF
112+
113+ # Build for specific platform
114+ docker buildx build \
115+ --platform ${{ matrix.os }}/${{ matrix.arch }} \
116+ --build-arg TARGETOS=${{ matrix.os }} \
117+ --build-arg TARGETARCH=${{ matrix.arch }} \
118+ --file Dockerfile.release \
119+ --output type=local,dest=./build-output \
120+ .
121+
122+ # Set binary name
123+ BINARY_NAME="lambda-nat-proxy"
124+ PLATFORM_DIR="build/${{ matrix.os }}-${{ matrix.arch }}"
125+
126+ # Create platform directory and copy binaries
127+ mkdir -p "$PLATFORM_DIR"
128+ cp build-output/lambda-nat-proxy "$PLATFORM_DIR/$BINARY_NAME"
129+ cp build-output/bootstrap "$PLATFORM_DIR/bootstrap"
130+
131+ # Make executable
132+ chmod +x "$PLATFORM_DIR/$BINARY_NAME"
133+ chmod +x "$PLATFORM_DIR/bootstrap"
134+
135+ # Create archive
136+ cd build
137+ tar -czf "lambda-nat-proxy-${{ matrix.os }}-${{ matrix.arch }}.tar.gz" "${{ matrix.os }}-${{ matrix.arch }}/"
138+
139+ # Cleanup
140+ rm -rf ../build-output ../Dockerfile.release
141+
142+ - name : Upload build artifacts
143+ uses : actions/upload-artifact@v4
144+ with :
145+ name : lambda-nat-proxy-${{ matrix.os }}-${{ matrix.arch }}
146+ path : build/lambda-nat-proxy-${{ matrix.os }}-${{ matrix.arch }}.tar.gz
147+ retention-days : 30
148+
149+ release :
150+ name : Create Release
151+ runs-on : ubuntu-latest
152+ needs : build-matrix
153+ if : github.event_name == 'release'
154+ permissions :
155+ contents : write
156+
157+ steps :
158+ - name : Download all artifacts
159+ uses : actions/download-artifact@v4
160+ with :
161+ path : artifacts
162+
163+ - name : Display structure of downloaded files
164+ run : ls -la artifacts/
165+
166+ - name : Upload release assets
167+ uses : softprops/action-gh-release@v1
168+ with :
169+ files : artifacts/**/*.tar.gz
170+ fail_on_unmatched_files : true
171+ env :
172+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
173+
174+ docker :
175+ name : Build and Push Docker Image
176+ runs-on : ubuntu-latest
177+ needs : test
178+ if : github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
179+ permissions :
180+ contents : read
181+ packages : write
182+
183+ steps :
184+ - name : Checkout code
185+ uses : actions/checkout@v4
186+
187+ - name : Set up Docker Buildx
188+ uses : docker/setup-buildx-action@v3
189+
190+ - name : Log in to Container Registry
191+ uses : docker/login-action@v3
192+ with :
193+ registry : ${{ env.REGISTRY }}
194+ username : ${{ github.actor }}
195+ password : ${{ secrets.GITHUB_TOKEN }}
196+
197+ - name : Extract metadata
198+ id : meta
199+ uses : docker/metadata-action@v5
200+ with :
201+ images : ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
202+ tags : |
203+ type=ref,event=branch
204+ type=sha,prefix={{branch}}-
205+ type=raw,value=latest,enable={{is_default_branch}}
206+
207+ - name : Build and push Docker image
208+ uses : docker/build-push-action@v5
209+ with :
210+ context : .
211+ file : ./Dockerfile.build
212+ platforms : linux/amd64,linux/arm64
213+ push : true
214+ tags : ${{ steps.meta.outputs.tags }}
215+ labels : ${{ steps.meta.outputs.labels }}
216+ cache-from : type=gha
217+ cache-to : type=gha,mode=max
0 commit comments