name: Build and Release on: workflow_dispatch: inputs: push_latest: description: 'Also push v1-latest tags' required: true default: false type: boolean release: types: [published] permissions: contents: read packages: write env: GHCR_IMAGE: ghcr.io/lfnovo/open-notebook DOCKERHUB_IMAGE: lfnovo/open_notebook jobs: extract-version: runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.version }} has_dockerhub_secrets: ${{ steps.check.outputs.has_dockerhub_secrets }} steps: - name: Checkout uses: actions/checkout@v4 - name: Extract version from pyproject.toml id: version run: | VERSION=$(grep -m1 '^version = ' pyproject.toml | cut -d'"' -f2) echo "version=$VERSION" >> $GITHUB_OUTPUT echo "Extracted version: $VERSION" - name: Check for Docker Hub credentials id: check env: SECRET_DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} SECRET_DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} run: | if [[ -n ""$SECRET_DOCKER_USERNAME"" && -n ""$SECRET_DOCKER_PASSWORD"" ]]; then echo "has_dockerhub_secrets=true" >> $GITHUB_OUTPUT echo "Docker Hub credentials available" else echo "has_dockerhub_secrets=false" >> $GITHUB_OUTPUT echo "Docker Hub credentials not available - will only push to GHCR" fi build-regular: needs: extract-version runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Free up disk space run: | sudo rm -rf /usr/share/dotnet sudo rm -rf /usr/local/lib/android sudo rm -rf /opt/ghc sudo rm -rf /opt/hostedtoolcache/CodeQL sudo docker image prune --all --force df -h - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to Docker Hub if: needs.extract-version.outputs.has_dockerhub_secrets == 'true' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Cache Docker layers uses: actions/cache@v3 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-regular-${{ github.sha }} restore-keys: | ${{ runner.os }}-buildx-regular- - name: Prepare Docker tags for regular build id: tags-regular env: ENV_GHCR_IMAGE: ${{ env.GHCR_IMAGE }} GITHUB_EVENT_INPUTS_PUSH_LATEST: ${{ github.event.inputs.push_latest }} GITHUB_EVENT_NAME: ${{ github.event_name }} GITHUB_EVENT_RELEASE_PRERELEASE: ${{ github.event.release.prerelease }} ENV_DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_IMAGE }} run: | TAGS=""$ENV_GHCR_IMAGE":${{ needs.extract-version.outputs.version }}" # Determine if we should push latest tags PUSH_LATEST=""$GITHUB_EVENT_INPUTS_PUSH_LATEST"" if [[ -z "$PUSH_LATEST" ]]; then PUSH_LATEST="false" fi # Add GHCR latest tag if requested or for non-prerelease releases if [[ "$PUSH_LATEST" == "true" ]] || [[ ""$GITHUB_EVENT_NAME"" == "release" && ""$GITHUB_EVENT_RELEASE_PRERELEASE"" != "true" ]]; then TAGS="${TAGS},"$ENV_GHCR_IMAGE":v1-latest" fi # Add Docker Hub tags if credentials available if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then TAGS="${TAGS},"$ENV_DOCKERHUB_IMAGE":${{ needs.extract-version.outputs.version }}" if [[ "$PUSH_LATEST" == "true" ]] || [[ ""$GITHUB_EVENT_NAME"" == "release" && ""$GITHUB_EVENT_RELEASE_PRERELEASE"" != "true" ]]; then TAGS="${TAGS},"$ENV_DOCKERHUB_IMAGE":v1-latest" fi fi echo "tags=${TAGS}" >> $GITHUB_OUTPUT echo "Generated tags: ${TAGS}" - name: Build and push regular image uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.tags-regular.outputs.tags }} cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - name: Move cache run: | rm -rf /tmp/.buildx-cache mv /tmp/.buildx-cache-new /tmp/.buildx-cache build-single: needs: extract-version runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Free up disk space run: | sudo rm -rf /usr/share/dotnet sudo rm -rf /usr/local/lib/android sudo rm -rf /opt/ghc sudo rm -rf /opt/hostedtoolcache/CodeQL sudo docker image prune --all --force df -h - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Login to Docker Hub if: needs.extract-version.outputs.has_dockerhub_secrets == 'true' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Cache Docker layers uses: actions/cache@v3 with: path: /tmp/.buildx-cache-single key: ${{ runner.os }}-buildx-single-${{ github.sha }} restore-keys: | ${{ runner.os }}-buildx-single- - name: Prepare Docker tags for single build id: tags-single env: ENV_GHCR_IMAGE: ${{ env.GHCR_IMAGE }} GITHUB_EVENT_INPUTS_PUSH_LATEST: ${{ github.event.inputs.push_latest }} GITHUB_EVENT_NAME: ${{ github.event_name }} GITHUB_EVENT_RELEASE_PRERELEASE: ${{ github.event.release.prerelease }} ENV_DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_IMAGE }} run: | TAGS=""$ENV_GHCR_IMAGE":${{ needs.extract-version.outputs.version }}-single" # Determine if we should push latest tags PUSH_LATEST=""$GITHUB_EVENT_INPUTS_PUSH_LATEST"" if [[ -z "$PUSH_LATEST" ]]; then PUSH_LATEST="false" fi # Add GHCR latest tag if requested or for non-prerelease releases if [[ "$PUSH_LATEST" == "true" ]] || [[ ""$GITHUB_EVENT_NAME"" == "release" && ""$GITHUB_EVENT_RELEASE_PRERELEASE"" != "true" ]]; then TAGS="${TAGS},"$ENV_GHCR_IMAGE":v1-latest-single" fi # Add Docker Hub tags if credentials available if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then TAGS="${TAGS},"$ENV_DOCKERHUB_IMAGE":${{ needs.extract-version.outputs.version }}-single" if [[ "$PUSH_LATEST" == "true" ]] || [[ ""$GITHUB_EVENT_NAME"" == "release" && ""$GITHUB_EVENT_RELEASE_PRERELEASE"" != "true" ]]; then TAGS="${TAGS},"$ENV_DOCKERHUB_IMAGE":v1-latest-single" fi fi echo "tags=${TAGS}" >> $GITHUB_OUTPUT echo "Generated tags: ${TAGS}" - name: Build and push single-container image uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile.single platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.tags-single.outputs.tags }} cache-from: type=local,src=/tmp/.buildx-cache-single cache-to: type=local,dest=/tmp/.buildx-cache-single-new,mode=max - name: Move cache run: | rm -rf /tmp/.buildx-cache-single mv /tmp/.buildx-cache-single-new /tmp/.buildx-cache-single summary: needs: [extract-version, build-regular, build-single] runs-on: ubuntu-latest if: always() steps: - name: Build Summary env: GITHUB_EVENT_INPUTS_PUSH_LATEST_____FALSE_: ${{ github.event.inputs.push_latest || 'false' }} ENV_GHCR_IMAGE: ${{ env.GHCR_IMAGE }} ENV_DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_IMAGE }} GITHUB_EVENT_INPUTS_PUSH_LATEST: ${{ github.event.inputs.push_latest }} run: | echo "## Build Summary" >> $GITHUB_STEP_SUMMARY echo "**Version:** ${{ needs.extract-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY echo "**Push v1-Latest:** "$GITHUB_EVENT_INPUTS_PUSH_LATEST_____FALSE_"" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### Registries:" >> $GITHUB_STEP_SUMMARY echo "✅ **GHCR:** \`"$ENV_GHCR_IMAGE"\`" >> $GITHUB_STEP_SUMMARY if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then echo "✅ **Docker Hub:** \`"$ENV_DOCKERHUB_IMAGE"\`" >> $GITHUB_STEP_SUMMARY else echo "⏭️ **Docker Hub:** Skipped (credentials not configured)" >> $GITHUB_STEP_SUMMARY fi echo "" >> $GITHUB_STEP_SUMMARY echo "### Images Built:" >> $GITHUB_STEP_SUMMARY if [[ "${{ needs.build-regular.result }}" == "success" ]]; then echo "✅ **Regular (GHCR):** \`"$ENV_GHCR_IMAGE":${{ needs.extract-version.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY if [[ ""$GITHUB_EVENT_INPUTS_PUSH_LATEST"" == "true" ]]; then echo "✅ **Regular v1-Latest (GHCR):** \`"$ENV_GHCR_IMAGE":v1-latest\`" >> $GITHUB_STEP_SUMMARY fi if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then echo "✅ **Regular (Docker Hub):** \`"$ENV_DOCKERHUB_IMAGE":${{ needs.extract-version.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY if [[ ""$GITHUB_EVENT_INPUTS_PUSH_LATEST"" == "true" ]]; then echo "✅ **Regular v1-Latest (Docker Hub):** \`"$ENV_DOCKERHUB_IMAGE":v1-latest\`" >> $GITHUB_STEP_SUMMARY fi fi elif [[ "${{ needs.build-regular.result }}" == "skipped" ]]; then echo "⏭️ **Regular:** Skipped" >> $GITHUB_STEP_SUMMARY else echo "❌ **Regular:** Failed" >> $GITHUB_STEP_SUMMARY fi if [[ "${{ needs.build-single.result }}" == "success" ]]; then echo "✅ **Single (GHCR):** \`"$ENV_GHCR_IMAGE":${{ needs.extract-version.outputs.version }}-single\`" >> $GITHUB_STEP_SUMMARY if [[ ""$GITHUB_EVENT_INPUTS_PUSH_LATEST"" == "true" ]]; then echo "✅ **Single v1-Latest (GHCR):** \`"$ENV_GHCR_IMAGE":v1-latest-single\`" >> $GITHUB_STEP_SUMMARY fi if [[ "${{ needs.extract-version.outputs.has_dockerhub_secrets }}" == "true" ]]; then echo "✅ **Single (Docker Hub):** \`"$ENV_DOCKERHUB_IMAGE":${{ needs.extract-version.outputs.version }}-single\`" >> $GITHUB_STEP_SUMMARY if [[ ""$GITHUB_EVENT_INPUTS_PUSH_LATEST"" == "true" ]]; then echo "✅ **Single v1-Latest (Docker Hub):** \`"$ENV_DOCKERHUB_IMAGE":v1-latest-single\`" >> $GITHUB_STEP_SUMMARY fi fi elif [[ "${{ needs.build-single.result }}" == "skipped" ]]; then echo "⏭️ **Single:** Skipped" >> $GITHUB_STEP_SUMMARY else echo "❌ **Single:** Failed" >> $GITHUB_STEP_SUMMARY fi echo "" >> $GITHUB_STEP_SUMMARY echo "### Platforms:" >> $GITHUB_STEP_SUMMARY echo "- linux/amd64" >> $GITHUB_STEP_SUMMARY echo "- linux/arm64" >> $GITHUB_STEP_SUMMARY