Add release package #76
Workflow file for this run
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: Docker | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| env: | |
| PACKAGE_NAME: python_template_server | |
| INSTALLER_NAME: install_template_server.sh | |
| SERVICE_NAME: python-template-server.service | |
| UNINSTALLER_NAME: uninstall_template_server.sh | |
| CONTAINER_NAME: python-template-server | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Build and start services with docker compose | |
| run: | | |
| docker compose up --build -d | |
| sleep 5 # Wait for services to start | |
| - name: Show server logs | |
| run: docker compose logs ${{ env.CONTAINER_NAME }} | |
| - uses: ./.github/actions/docker-check-containers | |
| with: | |
| port: 443 | |
| - name: Stop services | |
| run: docker compose down --volumes --remove-orphans | |
| prepare-release: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: ./.github/actions/setup-python-dev | |
| - name: Get package name and version from pyproject.toml | |
| id: get_package_info | |
| run: | | |
| VERSION=$(uv run python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])") | |
| echo "package_dir=${{ env.PACKAGE_NAME }}_${VERSION}" >> $GITHUB_OUTPUT | |
| - name: Prepare release directory | |
| run: | | |
| PACKAGE_DIR="${{ steps.get_package_info.outputs.package_dir }}" | |
| cp docker-compose.yml release/ | |
| cp README.md release/ | |
| chmod +x release/${{ env.INSTALLER_NAME }} | |
| mv release $PACKAGE_DIR | |
| tree $PACKAGE_DIR --dirsfirst -F | |
| - name: Create release tarball | |
| run: | | |
| PACKAGE_DIR="${{ steps.get_package_info.outputs.package_dir }}" | |
| tar -czf ${PACKAGE_DIR}.tar.gz $PACKAGE_DIR | |
| - name: Upload release tarball | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.PACKAGE_NAME }}_release | |
| path: ${{ steps.get_package_info.outputs.package_dir }}.tar.gz | |
| check-installer: | |
| runs-on: ubuntu-latest | |
| needs: prepare-release | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: ./.github/actions/setup-python-core | |
| - name: Download artifact from prepare-release job | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ${{ env.PACKAGE_NAME }}_release | |
| - name: Extract release tarball | |
| run: | | |
| TAR_FILE=$(find . -name '${{ env.PACKAGE_NAME }}_*.tar.gz') | |
| tar -xzf $TAR_FILE | |
| - name: Verify pre-installation directory contents | |
| run: | | |
| TAR_FILE=$(find . -name '${{ env.PACKAGE_NAME }}_*.tar.gz') | |
| DIR_NAME=$(basename "$TAR_FILE" .tar.gz) | |
| PACKAGE_NAME="${{ env.PACKAGE_NAME }}" | |
| cd "$DIR_NAME" | |
| echo "$DIR_NAME/" | |
| tree --dirsfirst -F | |
| files=("docker-compose.yml" "README.md") | |
| scripts=("${{ env.INSTALLER_NAME }}") | |
| for file in "${files[@]}"; do | |
| if [ ! -f "$file" ]; then | |
| echo "File $file not found" | |
| exit 1 | |
| fi | |
| done | |
| for script in "${scripts[@]}"; do | |
| if [ ! -f "$script" ]; then | |
| echo "Script $script not found" | |
| exit 1 | |
| fi | |
| if [ ! -x "$script" ]; then | |
| echo "Script $script is not executable" | |
| exit 1 | |
| fi | |
| done | |
| - name: Run installer script | |
| run: | | |
| TAR_FILE=$(find . -name '${{ env.PACKAGE_NAME }}_*.tar.gz') | |
| DIR_NAME=$(basename "$TAR_FILE" .tar.gz) | |
| cd "$DIR_NAME" | |
| ./${{ env.INSTALLER_NAME }} | |
| - name: Verify post-installation directory contents | |
| run: | | |
| TAR_FILE=$(find . -name '${{ env.PACKAGE_NAME }}_*.tar.gz') | |
| DIR_NAME=$(basename "$TAR_FILE" .tar.gz) | |
| cd "$DIR_NAME" | |
| echo "$DIR_NAME/" | |
| tree --dirsfirst -F | |
| if [ -f "${{ env.INSTALLER_NAME }}" ]; then | |
| echo "Installer script not removed" | |
| exit 1 | |
| fi | |
| files=("docker-compose.yml" "README.md" "${{ env.SERVICE_NAME }}" "start_service.sh" "stop_service.sh" "${{ env.UNINSTALLER_NAME }}") | |
| scripts=("start_service.sh" "stop_service.sh" "${{ env.UNINSTALLER_NAME }}") | |
| for file in "${files[@]}"; do | |
| if [ ! -f "$file" ]; then | |
| echo "File $file not found" | |
| exit 1 | |
| fi | |
| done | |
| for script in "${scripts[@]}"; do | |
| if [ ! -x "$script" ]; then | |
| echo "Script $script is not executable" | |
| exit 1 | |
| fi | |
| done | |
| publish-release: | |
| runs-on: ubuntu-latest | |
| needs: [build] | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| permissions: | |
| contents: write | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: ./.github/actions/setup-python-dev | |
| - name: Get version from pyproject.toml | |
| id: get_version | |
| run: | | |
| VERSION=$(uv run python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])") | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "tag=v$VERSION" >> $GITHUB_OUTPUT | |
| - name: Check if tag exists | |
| id: check_tag | |
| run: | | |
| if git rev-parse "v${{ steps.get_version.outputs.version }}" >/dev/null 2>&1; then | |
| echo "Tag v${{ steps.get_version.outputs.version }} already exists, skipping release creation" | |
| echo "tag_exists=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "tag_exists=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Set up Docker Buildx | |
| if: steps.check_tag.outputs.tag_exists == 'false' | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GitHub Container Registry | |
| if: steps.check_tag.outputs.tag_exists == 'false' | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata for Docker | |
| if: steps.check_tag.outputs.tag_exists == 'false' | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ghcr.io/${{ github.repository }} | |
| tags: | | |
| type=semver,pattern={{version}},value=v${{ steps.get_version.outputs.version }} | |
| type=semver,pattern={{major}}.{{minor}},value=v${{ steps.get_version.outputs.version }} | |
| type=semver,pattern={{major}},value=v${{ steps.get_version.outputs.version }} | |
| type=raw,value=latest | |
| - name: Build and push Docker image | |
| if: steps.check_tag.outputs.tag_exists == 'false' | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| platforms: linux/amd64,linux/arm64 | |
| - name: Generate release notes | |
| if: steps.check_tag.outputs.tag_exists == 'false' | |
| id: release_notes | |
| run: | | |
| cat > release_notes.md << 'EOF' | |
| ## Python Template Server v${{ steps.get_version.outputs.version }} | |
| **A template FastAPI server with production-ready configuration.** | |
| ### Quick Start | |
| Download the latest release tarball from the [Releases](https://github.com/${{ github.repository }}/releases) page. | |
| ```bash | |
| # Extract the tarball | |
| tar -xzf ${{ env.PACKAGE_NAME }}_*.tar.gz | |
| cd ${{ env.PACKAGE_NAME }}_*/ | |
| # Run the installer | |
| ./${{ env.INSTALLER_NAME }} | |
| ``` | |
| This will install the server as a systemd service and start it automatically. | |
| Access the application at `https://localhost:443` | |
| - [README](https://github.com/${{ github.repository }}/blob/main/README.md) | |
| - [API Documentation](https://github.com/${{ github.repository }}/blob/main/docs/API.md) | |
| - [Docker Deployment](https://github.com/${{ github.repository }}/blob/main/docs/DOCKER_DEPLOYMENT.md) | |
| EOF | |
| echo "release_notes_file=release_notes.md" >> $GITHUB_OUTPUT | |
| - name: Create GitHub Release | |
| if: steps.check_tag.outputs.tag_exists == 'false' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.get_version.outputs.tag }} | |
| name: "Python Template Server ${{ steps.get_version.outputs.version }}" | |
| body_path: ${{ steps.release_notes.outputs.release_notes_file }} | |
| draft: false | |
| prerelease: false | |
| generate_release_notes: false |