diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9692f7f..8f32d80 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -2,17 +2,23 @@ name: Build & Deploy Bot on: push: - branches: - - master - paths-ignore: - - '**/*.md' + tags: + - 'v*' + +env: + REGISTRY: docker.io + IMAGE_NAME: ${{ secrets.DOCKERHUB_USERNAME }}/next-downloader-bot jobs: build-and-push: name: Build and Push to Docker Hub runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: - - name: Checkout code + - name: Checkout repository uses: actions/checkout@v3 - name: Create fake .env file for build @@ -24,16 +30,35 @@ jobs: echo "REDIS_PASSWORD=fake" >> .env echo "REDIS_HOST=redis" >> .env - - name: Login to Docker Hub - run: echo "${{ secrets.DOCKERHUB_TOKEN }}" | docker login -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + - name: Log in to Docker Hub + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Build bot image - run: | - docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/next-downloader-bot:latest -f ./apps/bot/Dockerfile . + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.IMAGE_NAME }} + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=ref,event=branch + type=ref,event=pr + type=sha,prefix={{branch}}- + type=raw,value=latest,enable={{is_default_branch}} - - name: Push bot image to Docker Hub - run: | - docker push ${{ secrets.DOCKERHUB_USERNAME }}/next-downloader-bot:latest + - name: Build and push Docker image + uses: docker/build-push-action@v4 + with: + context: . + file: ./apps/bot/Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} deploy: name: Deploy to VPS @@ -44,6 +69,10 @@ jobs: - name: Checkout code uses: actions/checkout@v3 + - name: Get version from tag + id: get_version + run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT + - name: Setup SSH key run: | mkdir -p ~/.ssh @@ -63,6 +92,7 @@ jobs: echo "TELEGRAM_API_HASH=${{ secrets.TELEGRAM_API_HASH }}" >> .env echo "REDIS_PASSWORD=${{ secrets.REDIS_PASSWORD }}" >> .env echo "REDIS_HOST=${{ secrets.REDIS_HOST }}" >> .env + echo "BOT_IMAGE_TAG=${{ steps.get_version.outputs.version }}" >> .env - name: Copy .env to VPS via SCP uses: appleboy/scp-action@master diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..f90c406 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,26 @@ +name: release-please + +on: + push: + branches: + - master + paths-ignore: + - '**/*.md' + +permissions: + contents: write + pull-requests: write + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + - name: release-please + id: release + uses: google-github-actions/release-please-action@v3 + with: + release-type: simple + package-name: next-downloader-bot + bump-minor-pre-major: true + bump-patch-for-minor-pre-major: true + token: ${{ secrets.PAT }} \ No newline at end of file diff --git a/.release-please-config.json b/.release-please-config.json new file mode 100644 index 0000000..5f81146 --- /dev/null +++ b/.release-please-config.json @@ -0,0 +1,9 @@ +{ + "packages": { + ".": { + "release-type": "simple", + "package-name": "next-downloader-bot" + } + }, + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json" +} \ No newline at end of file diff --git a/COMMIT_EXAMPLES.md b/COMMIT_EXAMPLES.md new file mode 100644 index 0000000..25b3389 --- /dev/null +++ b/COMMIT_EXAMPLES.md @@ -0,0 +1,146 @@ +# Conventional Commits Examples + +This file contains examples of conventional commits that will trigger automatic releases. + +## Commit Types + +### `feat:` - New Features (Minor Release) + +```bash +# Add new video format support +git commit -m "feat: add support for MP4 video format" + +# Add new command +git commit -m "feat: add /help command for user assistance" + +# Add new language support +git commit -m "feat: add Spanish language support" +``` + +### `fix:` - Bug Fixes (Patch Release) + +```bash +# Fix download issue +git commit -m "fix: resolve video download timeout issue" + +# Fix memory leak +git commit -m "fix: prevent memory leak in video processing" + +# Fix error handling +git commit -m "fix: improve error handling for invalid URLs" +``` + +### `feat!:` or `fix!:` - Breaking Changes (Major Release) + +```bash +# Breaking change in API +git commit -m "feat!: change bot command structure" + +# Breaking change in configuration +git commit -m "fix!: update environment variable names" +``` + +### `docs:` - Documentation (No Release) + +```bash +# Update README +git commit -m "docs: update installation instructions" + +# Add API documentation +git commit -m "docs: add API endpoint documentation" +``` + +### `style:` - Code Style (No Release) + +```bash +# Format code +git commit -m "style: format code according to prettier" + +# Fix linting issues +git commit -m "style: fix ESLint warnings" +``` + +### `refactor:` - Code Refactoring (No Release) + +```bash +# Refactor download logic +git commit -m "refactor: improve video download performance" + +# Restructure code +git commit -m "refactor: reorganize bot handlers" +``` + +### `test:` - Testing (No Release) + +```bash +# Add unit tests +git commit -m "test: add unit tests for download function" + +# Update test configuration +git commit -m "test: update test environment setup" +``` + +### `chore:` - Maintenance (No Release) + +```bash +# Update dependencies +git commit -m "chore: update dependencies to latest versions" + +# Update CI configuration +git commit -m "chore: update GitHub Actions workflow" + +# Manual release +git commit -m "chore: release 1.0.0" -m "Release-As: 1.0.0" +``` + +## Commit Message Format + +``` +[optional scope]: + +[optional body] + +[optional footer(s)] +``` + +### Examples with Scope + +```bash +# With scope +git commit -m "feat(download): add support for batch downloads" + +# With scope and body +git commit -m "feat(api): add rate limiting" -m "Add rate limiting to prevent abuse" + +# With breaking change +git commit -m "feat(api)!: change response format" -m "BREAKING CHANGE: API response structure has changed" +``` + +## Version Bumping Rules + +- **Patch (1.0.0 → 1.0.1)**: `fix:`, `docs:`, `style:`, `refactor:`, `test:`, `chore:` +- **Minor (1.0.0 → 1.1.0)**: `feat:` +- **Major (1.0.0 → 2.0.0)**: `feat!:` or `fix!:` (breaking changes) + +## Best Practices + +1. **Use present tense**: "add" not "added" +2. **Use imperative mood**: "move cursor" not "moves cursor" +3. **Don't capitalize the first letter**: "fix: resolve issue" not "Fix: resolve issue" +4. **Don't end with a period**: "feat: add new feature" not "feat: add new feature." +5. **Be descriptive**: "fix: resolve memory leak in video processing" not "fix: bug" + +## Testing Commits + +To test the release process without affecting production: + +```bash +# Create a test commit +git commit -m "test: add test feature for release testing" + +# Push to trigger release-please +git push origin master + +# Check the created PR in GitHub +# If satisfied, merge the PR to create a release +``` \ No newline at end of file diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..902df7f --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,89 @@ +# Deployment Guide + +## Automated Release Process + +This project uses [release-please](https://github.com/googleapis/release-please) for automated releases based on conventional commits. The process works as follows: + +1. **Conventional Commits**: All commits should follow the [Conventional Commits](https://www.conventionalcommits.org/) specification +2. **Automatic PR Creation**: release-please creates pull requests for new releases +3. **Tag Creation**: When PR is merged, a new tag is created automatically +4. **Docker Build**: The tag triggers the Docker build and deployment workflow + +## Docker Image Tags + +The bot uses semantic versioning for Docker image tags. Each deployment creates multiple tags: + +- `latest` - Always points to the most recent build +- `{version}` - Full semantic version (e.g., `1.0.0`) +- `{major}.{minor}` - Minor version (e.g., `1.0`) +- `{major}` - Major version (e.g., `1`) + +## Environment Variables + +Create a `.env` file with the following variables: + +```bash +# Bot Configuration +BOT_TOKEN=your_bot_token_here +TELEGRAM_API_ROOT=https://api.telegram.org +TELEGRAM_API_ID=your_api_id_here +TELEGRAM_API_HASH=your_api_hash_here + +# Redis Configuration +REDIS_PASSWORD=your_redis_password_here +REDIS_HOST=redis + +# Docker Image Tag (optional, defaults to 'latest') +BOT_IMAGE_TAG=v1.0.0 +``` + +## Deployment + +The GitHub Actions workflows automatically: + +1. **release-please workflow**: Monitors commits and creates release PRs +2. **Build workflow**: Triggers on tag creation, builds and pushes Docker images +3. **Deploy workflow**: Deploys the new version to VPS + +### Commit Message Format + +Use conventional commits to trigger automatic releases: + +```bash +# Patch release (1.0.0 -> 1.0.1) +git commit -m "fix: resolve download issue" + +# Minor release (1.0.0 -> 1.1.0) +git commit -m "feat: add support for new video format" + +# Major release (1.0.0 -> 2.0.0) +git commit -m "feat!: breaking change in API" +``` + +## Manual Deployment + +To deploy manually with a specific tag: + +```bash +# Set the desired tag +export BOT_IMAGE_TAG=v1.0.0 + +# Deploy +docker compose down +docker compose pull +docker compose up -d +``` + +## Rollback + +To rollback to a previous version: + +```bash +# Set the previous tag +export BOT_IMAGE_TAG=v0.9.0 + +# Redeploy +docker compose down +docker compose pull +docker compose up -d +``` \ No newline at end of file diff --git a/README.md b/README.md index c4f4b8c..74b8abe 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,36 @@ This will start: - Telegram Bot API server - Next-Downloader-Bot application +### Automated Releases + +This project uses [release-please](https://github.com/googleapis/release-please) for automated releases based on conventional commits. The process automatically: + +1. Creates release pull requests when conventional commits are pushed +2. Generates semantic version tags when PRs are merged +3. Builds and deploys Docker images with proper versioning + +### Docker Image Tags + +The bot uses semantic versioning for Docker image tags. Each deployment creates multiple tags: + +- `latest` - Always points to the most recent build +- `{version}` - Full semantic version (e.g., `1.0.0`) +- `{major}.{minor}` - Minor version (e.g., `1.0`) +- `{major}` - Major version (e.g., `1`) + +To use a specific tag, set the `BOT_IMAGE_TAG` environment variable: + +```bash +# Use a specific version +export BOT_IMAGE_TAG=1.0.0 +docker-compose up -d + +# Use latest (default) +docker-compose up -d +``` + +For detailed deployment information, see [DEPLOYMENT.md](DEPLOYMENT.md). + ### Development with Docker For development, use the development compose file: @@ -135,6 +165,7 @@ Next-Downloader-Bot/ | `REDIS_PORT` | Redis server port | ❌ | `6379` | | `REDIS_PASSWORD` | Redis server password | ✅ | - | | `RATE_LIMIT` | Rate limit in milliseconds | ❌ | `5000` | +| `BOT_IMAGE_TAG` | Docker image tag for the bot | ❌ | `latest` | ### Redis Configuration diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 0000000..fdac549 --- /dev/null +++ b/SETUP.md @@ -0,0 +1,109 @@ +# Setup Guide for Automated Releases + +This guide explains how to set up automated releases using release-please and GitHub Actions. + +## Prerequisites + +1. **Personal Access Token (PAT)**: Create a GitHub Personal Access Token with the following scopes: + - `repo` (full control of private repositories) + - `write:packages` (upload packages to GitHub Package Registry) + +2. **Repository Permissions**: Ensure GitHub Actions have the necessary permissions. + +## Setup Steps + +### Step 1: Create Personal Access Token + +1. Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic) +2. Click "Generate new token (classic)" +3. Select the following scopes: + - `repo` (full control of private repositories) + - `write:packages` (upload packages to GitHub Package Registry) +4. Copy the generated token + +### Step 2: Add PAT to Repository Secrets + +1. Go to your repository → Settings → Secrets and variables → Actions +2. Click "New repository secret" +3. Name: `PAT` +4. Value: Paste your Personal Access Token +5. Click "Add secret" + +### Step 3: Configure Repository Permissions + +1. Go to your repository → Settings → Actions → General +2. Scroll down to "Workflow permissions" +3. Select "Read and write permissions" +4. Check "Allow GitHub Actions to create and approve pull requests" +5. Click "Save" + +### Step 4: Initial Release Setup + +For the first release, you can create an empty commit with a specific version: + +```bash +git commit --allow-empty -m "chore: release 0.1.0" -m "Release-As: 0.1.0" +git push origin master +``` + +This will create a pull request for version 0.1.0. + +## How It Works + +### Conventional Commits + +The system uses [Conventional Commits](https://www.conventionalcommits.org/) to determine version bumps: + +- `fix:` → Patch release (1.0.0 → 1.0.1) +- `feat:` → Minor release (1.0.0 → 1.1.0) +- `feat!:` or `fix!:` → Major release (1.0.0 → 2.0.0) + +### Workflow Process + +1. **Push to master**: When you push conventional commits to master +2. **Release PR**: release-please creates a pull request for the new release +3. **Merge PR**: When you merge the PR, a new tag is created +4. **Build & Deploy**: The tag triggers the Docker build and deployment workflow + +### Example Workflow + +```bash +# Make changes and commit with conventional commit +git add . +git commit -m "feat: add new video format support" +git push origin master + +# release-please creates a PR for version 1.1.0 +# Review and merge the PR +# Tag v1.1.0 is created automatically +# Docker image is built and deployed +``` + +## Troubleshooting + +### Common Issues + +1. **PAT Permissions**: Ensure your PAT has the correct scopes +2. **Repository Permissions**: Check that GitHub Actions have write permissions +3. **Conventional Commits**: Make sure commits follow the conventional format + +### Manual Release + +If you need to create a release manually: + +```bash +git commit --allow-empty -m "chore: release 1.0.0" -m "Release-As: 1.0.0" +git push origin master +``` + +### Check Workflow Status + +1. Go to your repository → Actions +2. Check the "release-please" workflow for any errors +3. Verify that release PRs are being created + +## References + +- [release-please Documentation](https://github.com/googleapis/release-please) +- [Conventional Commits](https://www.conventionalcommits.org/) +- [GitHub Actions Documentation](https://docs.github.com/en/actions) \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 95dd96f..4be1096 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,7 +23,7 @@ services: start_period: 30s next-downloader-bot: - image: vchikalkin/next-downloader-bot:latest + image: vchikalkin/next-downloader-bot:${BOT_IMAGE_TAG:-latest} env_file: - .env restart: always