diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9867791..e8fc443 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,16 +1,12 @@ -name: Build +name: CI on: - # Disabled automatic builds - run manually only - # push: - # branches: - # - "master" - # pull_request: + push: + pull_request: workflow_dispatch: env: PYTHON_VERSION: '>=3.10' - USE_UPX: false jobs: lint: @@ -70,60 +66,3 @@ jobs: echo -e "\nFailed to validate the following language file(s): ${failed[@]}" exit 1 fi - docker: - name: Docker Build - runs-on: ubuntu-latest - needs: - - lint - - validate - permissions: - contents: read - packages: write - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up variables - id: vars - run: | - echo "sha_short=$(git rev-parse --short HEAD)" >> "${GITHUB_OUTPUT}" - echo "date=$(date +%Y-%m-%d)" >> "${GITHUB_OUTPUT}" - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to GitHub Container Registry - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{github.actor}} - password: ${{secrets.GITHUB_TOKEN}} - - - name: Extract metadata for Docker - id: meta - uses: docker/metadata-action@v5 - with: - images: ghcr.io/${{github.repository}} - tags: | - type=raw,value=dev - type=raw,value=dev-${{steps.vars.outputs.sha_short}} - type=raw,value=latest,enable=${{github.ref == 'refs/heads/master'}} - type=sha,prefix= - - - name: Build and push Docker image - uses: docker/build-push-action@v6 - with: - context: . - platforms: linux/amd64,linux/arm64 - push: ${{github.event_name != 'pull_request'}} - tags: ${{steps.meta.outputs.tags}} - labels: ${{steps.meta.outputs.labels}} - cache-from: type=gha - cache-to: type=gha,mode=max - build-args: | - BUILD_DATE=${{steps.vars.outputs.date}} - VCS_REF=${{github.sha}} - VERSION=dev-${{steps.vars.outputs.sha_short}} - diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..a597a7f --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,62 @@ +name: Docker Dev Build + +on: + push: + branches: + - main + - master + - develop + workflow_dispatch: + +jobs: + docker: + name: Docker Dev Build & Push + runs-on: ubuntu-latest + environment: prod + permissions: + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@v5 + + - name: Set up variables + id: vars + run: | + echo "sha_short=$(git rev-parse --short HEAD)" >> "${GITHUB_OUTPUT}" + echo "date=$(date +%Y-%m-%d)" >> "${GITHUB_OUTPUT}" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Extract metadata for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: rangermix/twitch-drops-miner + tags: | + type=raw,value=dev + type=raw,value=dev-${{steps.vars.outputs.sha_short}} + type=raw,value=latest,enable=${{github.ref == 'refs/heads/master'}} + type=sha,prefix= + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{steps.meta.outputs.tags}} + labels: ${{steps.meta.outputs.labels}} + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: | + BUILD_DATE=${{steps.vars.outputs.date}} + VCS_REF=${{github.sha}} + VERSION=dev-${{steps.vars.outputs.sha_short}} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..da116ad --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,221 @@ +name: Release + +on: + workflow_dispatch: + inputs: + version: + description: 'Release version (SemVer format, e.g., 1.2.3 or 2.0.0-rc.1)' + required: true + type: string + +permissions: + contents: write + packages: write + +jobs: + validate: + name: Validate Version + runs-on: ubuntu-latest + outputs: + version: ${{ steps.validate.outputs.version }} + is_prerelease: ${{ steps.validate.outputs.is_prerelease }} + + steps: + - name: Validate SemVer format + id: validate + run: | + VERSION="${{ github.event.inputs.version }}" + + # SemVer regex: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string + SEMVER_REGEX='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*))?(\+([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*))?$' + + if ! echo "$VERSION" | grep -Pq "$SEMVER_REGEX"; then + echo "Error: Version '$VERSION' is not valid SemVer format" + echo "Examples: 1.2.3, 2.0.0-rc.1, 1.0.0-beta.2+build.123" + exit 1 + fi + + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + # Check if pre-release (contains hyphen) + if echo "$VERSION" | grep -q '-'; then + echo "is_prerelease=true" >> "$GITHUB_OUTPUT" + echo "Detected pre-release version: $VERSION" + else + echo "is_prerelease=false" >> "$GITHUB_OUTPUT" + echo "Detected stable release version: $VERSION" + fi + + create-release-branch: + name: Create Release Branch + runs-on: ubuntu-latest + needs: validate + outputs: + branch_name: ${{ steps.create-branch.outputs.branch_name }} + + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + ref: master + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Check if branch exists + id: check-branch + run: | + BRANCH_NAME="release/${{ needs.validate.outputs.version }}" + + if git ls-remote --heads origin "$BRANCH_NAME" | grep -q "$BRANCH_NAME"; then + echo "Error: Branch '$BRANCH_NAME' already exists" + exit 1 + fi + + echo "Branch '$BRANCH_NAME' does not exist, proceeding..." + + - name: Create release branch + id: create-branch + run: | + BRANCH_NAME="release/${{ needs.validate.outputs.version }}" + VERSION="${{ needs.validate.outputs.version }}" + + # Create and checkout new branch + git checkout -b "$BRANCH_NAME" + + # Update version.py + echo "__version__ = \"$VERSION\"" > src/version.py + + # Commit changes + git add src/version.py + git commit -m "chore: bump version to $VERSION" + + # Push branch + git push origin "$BRANCH_NAME" + + # Create and push tag + git tag "v$VERSION" + git push origin "v$VERSION" + + echo "branch_name=$BRANCH_NAME" >> "$GITHUB_OUTPUT" + echo "Created branch '$BRANCH_NAME' and tag 'v$VERSION'" + + docker-build: + name: Build & Push Docker Images + runs-on: ubuntu-latest + needs: [validate, create-release-branch] + environment: prod + + steps: + - name: Checkout release branch + uses: actions/checkout@v5 + with: + ref: ${{ needs.create-release-branch.outputs.branch_name }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Generate Docker tags + id: docker-tags + run: | + VERSION="${{ needs.validate.outputs.version }}" + IMAGE="rangermix/twitch-drops-miner" + IS_PRERELEASE="${{ needs.validate.outputs.is_prerelease }}" + + # Always include the full version tag + TAGS="$IMAGE:$VERSION" + + # For stable releases, add major.minor, major, and latest tags + if [ "$IS_PRERELEASE" = "false" ]; then + # Extract major.minor.patch + MAJOR=$(echo "$VERSION" | cut -d. -f1) + MINOR=$(echo "$VERSION" | cut -d. -f2) + + TAGS="$TAGS,$IMAGE:$MAJOR.$MINOR" + TAGS="$TAGS,$IMAGE:$MAJOR" + TAGS="$TAGS,$IMAGE:latest" + fi + + echo "tags=$TAGS" >> "$GITHUB_OUTPUT" + echo "Generated tags: $TAGS" + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.docker-tags.outputs.tags }} + labels: | + org.opencontainers.image.title=Twitch Drops Miner + org.opencontainers.image.description=Automatically mine Twitch drops + org.opencontainers.image.version=${{ needs.validate.outputs.version }} + org.opencontainers.image.revision=${{ github.sha }} + org.opencontainers.image.created=${{ github.event.repository.updated_at }} + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: | + BUILD_DATE=${{ github.event.repository.updated_at }} + VCS_REF=${{ github.sha }} + VERSION=${{ needs.validate.outputs.version }} + + github-release: + name: Create GitHub Release + runs-on: ubuntu-latest + needs: [validate, create-release-branch, docker-build] + + steps: + - name: Checkout release branch + uses: actions/checkout@v5 + with: + ref: ${{ needs.create-release-branch.outputs.branch_name }} + fetch-depth: 0 + + - name: Generate release notes + id: release-notes + run: | + VERSION="${{ needs.validate.outputs.version }}" + + # Get the previous tag + PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "") + + if [ -n "$PREV_TAG" ]; then + echo "## Changes since $PREV_TAG" > release_notes.md + echo "" >> release_notes.md + git log $PREV_TAG..HEAD --pretty=format:"- %s (%h)" >> release_notes.md + else + echo "## Initial Release" > release_notes.md + echo "" >> release_notes.md + echo "First release of Twitch Drops Miner $VERSION" >> release_notes.md + fi + + echo "" >> release_notes.md + echo "" >> release_notes.md + echo "## Docker Images" >> release_notes.md + echo "" >> release_notes.md + echo '```bash' >> release_notes.md + echo "docker pull rangermix/twitch-drops-miner:$VERSION" >> release_notes.md + echo '```' >> release_notes.md + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: v${{ needs.validate.outputs.version }} + name: Release ${{ needs.validate.outputs.version }} + body_path: release_notes.md + prerelease: ${{ needs.validate.outputs.is_prerelease }} + draft: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}