fix(daemon): strictly enforce Caddy config dir permissions to 0755 #364
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release Pipeline | |
| on: | |
| push: | |
| branches: ["main", "develop"] | |
| tags: ["v*.*.*"] | |
| pull_request: | |
| branches: ["main"] | |
| paths: ["**.go", "go.mod", "go.sum"] | |
| # Prevent concurrent releases | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| test-and-verify: | |
| name: Test & Verify | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: "1.24.x" | |
| cache: true | |
| cache-dependency-path: go.sum | |
| - name: Verify dependencies | |
| run: | | |
| go mod verify | |
| go mod download | |
| - name: Run tests | |
| run: | | |
| go test -v -race -coverprofile=coverage.txt -covermode=atomic ./... | |
| - name: Upload coverage | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| file: ./coverage.txt | |
| flags: unittests | |
| name: codecov-umbrella | |
| fail_ci_if_error: false | |
| - name: Check version consistency | |
| run: | | |
| # Verify that version variables are properly set | |
| if grep -r "var Version = \"dev\"" --include="*.go" | grep -v "version.go"; then | |
| echo "⚠️ Found hardcoded 'dev' version in unauthorized files" | |
| exit 1 | |
| fi | |
| build-and-release: | |
| name: Build & Release | |
| runs-on: ubuntu-latest | |
| needs: [test-and-verify] | |
| if: github.event_name != 'pull_request' | |
| permissions: | |
| contents: write | |
| packages: write | |
| discussions: write | |
| env: | |
| DOCKER_REGISTRY: ghcr.io | |
| DOCKER_IMAGE: ${{ github.repository }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: "1.24.x" | |
| cache: true | |
| cache-dependency-path: go.sum | |
| - name: Set up GoReleaser | |
| uses: goreleaser/goreleaser-action@v6 | |
| with: | |
| distribution: goreleaser | |
| version: latest | |
| install-only: true | |
| - name: Set VERSION from tag or branch | |
| id: version | |
| run: | | |
| if [[ "$GITHUB_REF" == refs/tags/* ]]; then | |
| VERSION="${GITHUB_REF#refs/tags/}" | |
| IS_TAG="true" | |
| else | |
| SHORT_SHA=$(git rev-parse --short HEAD) | |
| VERSION="dev-${SHORT_SHA}" | |
| IS_TAG="false" | |
| fi | |
| echo "VERSION=$VERSION" >> $GITHUB_ENV | |
| echo "is_tag=$IS_TAG" >> $GITHUB_OUTPUT | |
| # Validate semantic version for tags | |
| if [[ "$IS_TAG" == "true" ]]; then | |
| if ! [[ $VERSION =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then | |
| echo "❌ Invalid semantic version tag: $VERSION" | |
| exit 1 | |
| fi | |
| fi | |
| echo "🔖 Building version: $VERSION" | |
| - name: Verify version stamping | |
| run: | | |
| echo "Testing version embedding..." | |
| # Build a test binary with version | |
| go build -ldflags="\ | |
| -X 'github.com/Golangcodes/nextdeploy/shared.Version=${{ env.VERSION }}' \ | |
| -X 'github.com/Golangcodes/nextdeploy/shared/updater.Version=${{ env.VERSION }}' \ | |
| -X 'main.commit=$(git rev-parse --short HEAD)' \ | |
| -X 'main.date=$(date -u +%Y-%m-%dT%H:%M:%SZ)'" \ | |
| -o nextdeploy-test ./cli | |
| # Verify version | |
| ACTUAL_VERSION=$(./nextdeploy-test version) | |
| if [[ "$ACTUAL_VERSION" == *"${{ env.VERSION }}"* ]]; then | |
| echo "✅ Version correctly embedded: $ACTUAL_VERSION" | |
| else | |
| echo "❌ Version mismatch! Expected: ${{ env.VERSION }}, Got: $ACTUAL_VERSION" | |
| exit 1 | |
| fi | |
| # Clean up test binary to avoid dirty git state | |
| rm nextdeploy-test | |
| - name: Run GoReleaser (Tag Release) | |
| if: steps.version.outputs.is_tag == 'true' | |
| uses: goreleaser/goreleaser-action@v6 | |
| with: | |
| distribution: goreleaser | |
| version: latest | |
| args: release --clean --timeout 60m | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| VERSION: ${{ env.VERSION }} | |
| - name: Run GoReleaser (Snapshot) | |
| if: steps.version.outputs.is_tag != 'true' | |
| uses: goreleaser/goreleaser-action@v6 | |
| with: | |
| distribution: goreleaser | |
| version: latest | |
| args: release --snapshot --clean --timeout 30m | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| VERSION: ${{ env.VERSION }} | |
| - name: Verify Release Assets | |
| if: steps.version.outputs.is_tag == 'true' | |
| run: | | |
| echo "🔍 Verifying release assets..." | |
| # Check if binaries exist and have correct version | |
| for binary in dist/nextdeploy_linux_amd64_v1/nextdeploy dist/nextdeploy_darwin_amd64_v1/nextdeploy; do | |
| if [ -f "$binary" ]; then | |
| VERSION_OUTPUT=$($binary version 2>/dev/null | head -1) | |
| echo "✅ $binary: $VERSION_OUTPUT" | |
| if [[ "$VERSION_OUTPUT" != *"${{ env.VERSION }}"* ]]; then | |
| echo "❌ Version mismatch in $binary" | |
| exit 1 | |
| fi | |
| fi | |
| done | |
| # Verify checksums | |
| if [ -f dist/*_checksums.txt ]; then | |
| echo "✅ Checksums file created" | |
| cat dist/*_checksums.txt | |
| else | |
| echo "❌ Checksums file missing!" | |
| exit 1 | |
| fi | |
| - name: Upload Release Assets (Non-Tag) | |
| if: steps.version.outputs.is_tag != 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: nextdeploy-${{ env.VERSION }} | |
| path: dist/* | |
| retention-days: 7 | |
| if-no-files-found: error | |
| - name: Generate SBOM | |
| if: steps.version.outputs.is_tag == 'true' | |
| uses: anchore/sbom-action@v0 | |
| with: | |
| path: ./ | |
| format: spdx-json | |
| output-file: dist/nextdeploy-${{ env.VERSION }}-sbom.spdx.json | |
| - name: Attach SBOM to Release | |
| if: steps.version.outputs.is_tag == 'true' | |
| run: | | |
| gh release upload ${{ env.VERSION }} dist/nextdeploy-${{ env.VERSION }}-sbom.spdx.json --clobber | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| notify: | |
| name: Notify | |
| runs-on: ubuntu-latest | |
| needs: [build-and-release] | |
| if: success() && startsWith(github.ref, 'refs/tags/') | |
| steps: | |
| - name: Send Slack notification | |
| if: env.SLACK_WEBHOOK_URL != '' | |
| uses: slackapi/slack-github-action@v1 | |
| with: | |
| payload: | | |
| { | |
| "text": "🚀 NextDeploy ${{ github.ref_name }} released!", | |
| "blocks": [ | |
| { | |
| "type": "section", | |
| "text": { | |
| "type": "mrkdwn", | |
| "text": "*NextDeploy ${{ github.ref_name }}* has been released! 🎉\n\n• <${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}|View Release>\n• <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Build>" | |
| } | |
| } | |
| ] | |
| } | |
| env: | |
| SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} | |
| - name: Create GitHub Discussion | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const { data: release } = await github.rest.repos.getReleaseByTag({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| tag: process.env.GITHUB_REF_NAME | |
| }); | |
| await github.rest.repos.createDiscussion({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: `🚀 NextDeploy ${process.env.GITHUB_REF_NAME} Released`, | |
| body: `## What's New in ${process.env.GITHUB_REF_NAME}\n\nCheck out the [release notes](${release.html_url}) for details.\n\n### Installation\n\`\`\`bash\ncurl -fsSL https://nextdeploy.one/install.sh | bash\n\`\`\`\n\n### Docker\n\`\`\`bash\ndocker pull ghcr.io/${{ github.repository }}:${process.env.GITHUB_REF_NAME}\n\`\`\``, | |
| category: 'announcements' | |
| }); |