1+ name : Create Release
2+
3+ on :
4+ workflow_dispatch :
5+ inputs :
6+ release_type :
7+ description : ' Release type'
8+ required : true
9+ default : ' patch'
10+ type : choice
11+ options :
12+ - patch
13+ - minor
14+ - major
15+ push :
16+ branches :
17+ - main
18+ paths-ignore :
19+ - ' README*.md'
20+ - ' LICENSE'
21+ - ' .gitignore'
22+ - ' IMPLEMENTATION_PLAN.md'
23+
24+ jobs :
25+ check-changes :
26+ runs-on : ubuntu-latest
27+ outputs :
28+ should_release : ${{ steps.changes.outputs.should_release }}
29+ version : ${{ steps.version.outputs.version }}
30+ steps :
31+ - name : Checkout repository
32+ uses : actions/checkout@v4
33+ with :
34+ fetch-depth : 0
35+
36+ - name : Check for significant changes
37+ id : changes
38+ run : |
39+ # Get the last release tag
40+ LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
41+ echo "Last tag: ${LAST_TAG:-'(none)'}"
42+
43+ # Check if there are changes in source code since last release
44+ if [[ -z "$LAST_TAG" ]]; then
45+ # No previous tags, this is the first release
46+ echo "No previous tags found - first release"
47+ echo "should_release=true" >> $GITHUB_OUTPUT
48+ elif git diff --quiet $LAST_TAG HEAD -- '*.go' 'go.mod' 'go.sum' 'Dockerfile' '.github/workflows/' 'internal/' 'cmd/' 'pkg/'; then
49+ echo "No significant changes detected"
50+ echo "should_release=false" >> $GITHUB_OUTPUT
51+ else
52+ echo "Significant changes detected"
53+ echo "should_release=true" >> $GITHUB_OUTPUT
54+ fi
55+
56+ - name : Calculate next version
57+ id : version
58+ if : steps.changes.outputs.should_release == 'true' || github.event_name == 'workflow_dispatch'
59+ run : |
60+ # Get the last release tag
61+ LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
62+ echo "Last tag: ${LAST_TAG:-'(none)'}"
63+
64+ # Handle first release vs. subsequent releases
65+ if [[ -z "$LAST_TAG" ]]; then
66+ # First release - start from v0.0.0
67+ MAJOR=0
68+ MINOR=1
69+ PATCH=0
70+ echo "First release - starting from v0.1.0"
71+ else
72+ # Remove 'v' prefix and split version
73+ VERSION_NUMBER=${LAST_TAG#v}
74+ IFS='.' read -r -a VERSION_PARTS <<< "$VERSION_NUMBER"
75+
76+ MAJOR=${VERSION_PARTS[0]:-0}
77+ MINOR=${VERSION_PARTS[1]:-0}
78+ PATCH=${VERSION_PARTS[2]:-0}
79+ fi
80+
81+ # Determine release type
82+ if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
83+ RELEASE_TYPE="${{ github.event.inputs.release_type }}"
84+ else
85+ # Auto-determine based on commit messages since last release
86+ if [[ -z "$LAST_TAG" ]]; then
87+ # First release - check all commits
88+ COMMITS=$(git log --oneline)
89+ else
90+ # Subsequent release - check commits since last tag
91+ COMMITS=$(git log $LAST_TAG..HEAD --oneline)
92+ fi
93+
94+ if echo "$COMMITS" | grep -qE "(BREAKING CHANGE|!:)"; then
95+ RELEASE_TYPE="major"
96+ elif echo "$COMMITS" | grep -qE "(feat:|feature:)"; then
97+ RELEASE_TYPE="minor"
98+ else
99+ RELEASE_TYPE="patch"
100+ fi
101+ fi
102+
103+ echo "Release type: $RELEASE_TYPE"
104+
105+ # Increment version based on release type
106+ case $RELEASE_TYPE in
107+ major)
108+ MAJOR=$((MAJOR + 1))
109+ MINOR=0
110+ PATCH=0
111+ ;;
112+ minor)
113+ MINOR=$((MINOR + 1))
114+ PATCH=0
115+ ;;
116+ patch)
117+ PATCH=$((PATCH + 1))
118+ ;;
119+ esac
120+
121+ NEW_VERSION="v${MAJOR}.${MINOR}.${PATCH}"
122+ echo "New version: $NEW_VERSION"
123+ echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
124+
125+ test :
126+ runs-on : ubuntu-latest
127+ steps :
128+ - name : Checkout repository
129+ uses : actions/checkout@v4
130+
131+ - name : Set up Go
132+ uses : actions/setup-go@v4
133+ with :
134+ go-version : ' 1.23'
135+
136+ - name : Cache Go modules
137+ uses : actions/cache@v3
138+ with :
139+ path : ~/go/pkg/mod
140+ key : ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
141+ restore-keys : |
142+ ${{ runner.os }}-go-
143+
144+ - name : Download dependencies
145+ run : go mod download
146+
147+ - name : Run tests
148+ run : go test -v ./...
149+
150+ - name : Run go vet
151+ run : go vet ./...
152+
153+ - name : Run go fmt check
154+ run : |
155+ if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then
156+ echo "The following files need to be formatted:"
157+ gofmt -s -l .
158+ exit 1
159+ fi
160+
161+ build :
162+ needs : test
163+ runs-on : ubuntu-latest
164+ steps :
165+ - name : Checkout repository
166+ uses : actions/checkout@v4
167+
168+ - name : Set up Go
169+ uses : actions/setup-go@v4
170+ with :
171+ go-version : ' 1.23'
172+
173+ - name : Build application
174+ run : |
175+ # Build for multiple architectures
176+ GOOS=linux GOARCH=amd64 go build -o syncarr-linux-amd64 ./cmd/syncarr
177+ GOOS=linux GOARCH=arm64 go build -o syncarr-linux-arm64 ./cmd/syncarr
178+ GOOS=windows GOARCH=amd64 go build -o syncarr-windows-amd64.exe ./cmd/syncarr
179+ GOOS=darwin GOARCH=amd64 go build -o syncarr-darwin-amd64 ./cmd/syncarr
180+ GOOS=darwin GOARCH=arm64 go build -o syncarr-darwin-arm64 ./cmd/syncarr
181+
182+ - name : Upload build artifacts
183+ uses : actions/upload-artifact@v4
184+ with :
185+ name : syncarr-binaries
186+ path : syncarr-*
187+
188+ create-release :
189+ needs : [check-changes, test, build]
190+ if : needs.check-changes.outputs.should_release == 'true' || github.event_name == 'workflow_dispatch'
191+ runs-on : ubuntu-latest
192+ permissions :
193+ contents : write
194+ steps :
195+ - name : Checkout repository
196+ uses : actions/checkout@v4
197+ with :
198+ fetch-depth : 0
199+
200+ - name : Download build artifacts
201+ uses : actions/download-artifact@v4
202+ with :
203+ name : syncarr-binaries
204+
205+ - name : Generate changelog
206+ id : changelog
207+ run : |
208+ # Get the last release tag
209+ LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
210+
211+ if [[ -n "$LAST_TAG" ]]; then
212+ echo "## What's Changed" > changelog.md
213+ echo "" >> changelog.md
214+
215+ # Get commits since last release
216+ git log $LAST_TAG..HEAD --pretty=format:"- %s (%h)" --reverse >> changelog.md
217+ else
218+ echo "## 🎉 Initial Release of SyncArr" > changelog.md
219+ echo "" >> changelog.md
220+ echo "SyncArr synchronizes labeled movies and TV shows between source and destination Plex Media Servers." >> changelog.md
221+ echo "" >> changelog.md
222+ echo "### ✨ Features" >> changelog.md
223+ echo "- 🏷️ Label-based synchronization between Plex servers" >> changelog.md
224+ echo "- 🔄 Bidirectional watched state synchronization" >> changelog.md
225+ echo "- 📁 Secure SSH/SFTP file transfers with key-based authentication" >> changelog.md
226+ echo "- 🔄 Incremental sync with change detection" >> changelog.md
227+ echo "- 🎯 Content filtering by patterns, size, and library rules" >> changelog.md
228+ echo "- 🐳 Docker container with complete configuration via environment variables" >> changelog.md
229+ echo "- 📊 Comprehensive structured logging" >> changelog.md
230+ echo "- ⚡ Force full sync option for resolving inconsistencies" >> changelog.md
231+ echo "- 🔧 Flexible deployment (one-shot or continuous modes)" >> changelog.md
232+ echo "" >> changelog.md
233+ echo "### 🚀 Getting Started" >> changelog.md
234+ echo "1. Set up SSH key-based authentication between servers" >> changelog.md
235+ echo "2. Configure environment variables for source/destination Plex servers" >> changelog.md
236+ echo "3. Add labels to media items you want to sync" >> changelog.md
237+ echo "4. Deploy using Docker Compose" >> changelog.md
238+ fi
239+
240+ echo "" >> changelog.md
241+ echo "### 🐳 Docker Images" >> changelog.md
242+ echo "" >> changelog.md
243+ echo "**Multi-architecture support:** \`linux/amd64\`, \`linux/arm64\`" >> changelog.md
244+ echo "" >> changelog.md
245+ echo '```bash' >> changelog.md
246+ echo "# Latest release" >> changelog.md
247+ echo "docker pull ghcr.io/${{ github.repository_owner }}/syncarr:${{ needs.check-changes.outputs.version }}" >> changelog.md
248+ echo "" >> changelog.md
249+ echo "# Always latest" >> changelog.md
250+ echo "docker pull ghcr.io/${{ github.repository_owner }}/syncarr:latest" >> changelog.md
251+ echo '```' >> changelog.md
252+ echo "" >> changelog.md
253+ echo "### 📥 Binary Downloads" >> changelog.md
254+ echo "" >> changelog.md
255+ echo "Pre-compiled binaries are available for multiple platforms in the release assets below." >> changelog.md
256+
257+ - name : Create Release
258+ uses : softprops/action-gh-release@v1
259+ with :
260+ tag_name : ${{ needs.check-changes.outputs.version }}
261+ name : Release ${{ needs.check-changes.outputs.version }}
262+ body_path : changelog.md
263+ files : |
264+ syncarr-linux-amd64
265+ syncarr-linux-arm64
266+ syncarr-windows-amd64.exe
267+ syncarr-darwin-amd64
268+ syncarr-darwin-arm64
269+ draft : false
270+ prerelease : false
271+ generate_release_notes : true
272+
273+ publish-docker :
274+ needs : [check-changes, create-release]
275+ if : needs.check-changes.outputs.should_release == 'true' || github.event_name == 'workflow_dispatch'
276+ runs-on : ubuntu-latest
277+ permissions :
278+ contents : read
279+ packages : write
280+
281+ steps :
282+ - name : Checkout repository
283+ uses : actions/checkout@v4
284+
285+ - name : Set up Docker Buildx
286+ uses : docker/setup-buildx-action@v3
287+
288+ - name : Log in to Container Registry
289+ uses : docker/login-action@v3
290+ with :
291+ registry : ghcr.io
292+ username : ${{ github.actor }}
293+ password : ${{ secrets.GITHUB_TOKEN }}
294+
295+ - name : Extract metadata
296+ id : meta
297+ uses : docker/metadata-action@v5
298+ with :
299+ images : ghcr.io/${{ github.repository }}
300+ tags : |
301+ type=raw,value=${{ needs.check-changes.outputs.version }}
302+ type=raw,value=latest
303+
304+ - name : Build and push Docker image
305+ uses : docker/build-push-action@v5
306+ with :
307+ context : .
308+ file : ./Dockerfile
309+ platforms : linux/amd64,linux/arm64
310+ push : true
311+ tags : ${{ steps.meta.outputs.tags }}
312+ labels : ${{ steps.meta.outputs.labels }}
313+ cache-from : type=gha
314+ cache-to : type=gha,mode=max
315+
316+ - name : Generate Docker summary
317+ run : |
318+ echo "## 🐳 Docker Image Published" >> $GITHUB_STEP_SUMMARY
319+ echo "" >> $GITHUB_STEP_SUMMARY
320+ echo "**Version:** ${{ needs.check-changes.outputs.version }}" >> $GITHUB_STEP_SUMMARY
321+ echo "**Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
322+ echo "" >> $GITHUB_STEP_SUMMARY
323+ echo "**Registry:** ghcr.io" >> $GITHUB_STEP_SUMMARY
324+ echo "**Platforms:** linux/amd64, linux/arm64" >> $GITHUB_STEP_SUMMARY
325+ echo "" >> $GITHUB_STEP_SUMMARY
326+ echo "**Tags:**" >> $GITHUB_STEP_SUMMARY
327+ echo '```' >> $GITHUB_STEP_SUMMARY
328+ echo "ghcr.io/${{ github.repository }}:${{ needs.check-changes.outputs.version }}" >> $GITHUB_STEP_SUMMARY
329+ echo "ghcr.io/${{ github.repository }}:latest" >> $GITHUB_STEP_SUMMARY
330+ echo '```' >> $GITHUB_STEP_SUMMARY
331+ echo "" >> $GITHUB_STEP_SUMMARY
332+ echo "**Pull command:**" >> $GITHUB_STEP_SUMMARY
333+ echo '```bash' >> $GITHUB_STEP_SUMMARY
334+ echo "docker pull ghcr.io/${{ github.repository }}:${{ needs.check-changes.outputs.version }}" >> $GITHUB_STEP_SUMMARY
335+ echo '```' >> $GITHUB_STEP_SUMMARY
0 commit comments