name: "Docker Image CI: crawlab" on: push: branches: [ develop, main ] #pull_request: # branches: [ main ] release: types: [ published ] workflow_dispatch: repository_dispatch: types: [ docker-crawlab ] env: IMAGE_PATH_CRAWLAB_BACKEND: backend IMAGE_PATH_CRAWLAB_FRONTEND: frontend IMAGE_NAME_CRAWLAB: crawlabteam/crawlab IMAGE_NAME_CRAWLAB_BACKEND: crawlabteam/crawlab-backend IMAGE_NAME_CRAWLAB_FRONTEND: crawlabteam/crawlab-frontend IMAGE_NAME_CRAWLAB_TENCENT: ccr.ccs.tencentyun.com/crawlab/crawlab jobs: setup: runs-on: ubuntu-latest outputs: backend_changed: ${{ steps.check_changed_files.outputs.backend_changed }} frontend_changed: ${{ steps.check_changed_files.outputs.frontend_changed }} dockerfile_changed: ${{ steps.check_changed_files.outputs.dockerfile_changed }} version: ${{ steps.version.outputs.version }} image_hash: ${{ steps.hash.outputs.hash }} steps: - uses: actions/checkout@v4 - name: Get changed files id: changed_files uses: tj-actions/changed-files@v45 with: files_yaml: | backend: - 'backend/**' - 'core/**' - 'db/**' - 'fs/**' - 'grpc/**' - 'vcs/**' - 'trace/**' frontend: - '${{ env.IMAGE_PATH_CRAWLAB_FRONTEND }}/**' dockerfile: - 'Dockerfile' - id: check_changed_files name: Check changed files run: | # set outputs if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then echo "backend_changed=true" >> $GITHUB_OUTPUT echo "frontend_changed=true" >> $GITHUB_OUTPUT echo "dockerfile_changed=true" >> $GITHUB_OUTPUT else echo "backend_changed=${{ steps.changed_files.outputs.backend_any_changed }}" >> $GITHUB_OUTPUT echo "frontend_changed=${{ steps.changed_files.outputs.frontend_any_changed }}" >> $GITHUB_OUTPUT echo "dockerfile_changed=${{ steps.changed_files.outputs.dockerfile_any_changed }}" >> $GITHUB_OUTPUT fi # Display change status for each component echo "Backend changed: ${{ steps.changed_files.outputs.backend_any_changed }}" echo "Frontend changed: ${{ steps.changed_files.outputs.frontend_any_changed }}" echo "Dockerfile changed: ${{ steps.changed_files.outputs.dockerfile_any_changed }}" - id: version name: Get version run: | # Strip git ref prefix from version VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') # Strip "v" prefix from tag name [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') # Use Docker `latest` tag convention [ "$VERSION" == "main" ] && VERSION=latest echo "version=$VERSION" >> $GITHUB_OUTPUT - id: hash name: Generate unique hash run: echo "hash=$(echo ${{ github.sha }} | cut -c1-7)" >> $GITHUB_OUTPUT test_backend: needs: [ setup ] if: needs.setup.outputs.backend_changed == 'true' runs-on: ubuntu-latest services: mongo: image: mongo:5 ports: - 27017:27017 steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: go-version-file: 'core/go.mod' cache-dependency-path: 'core/go.sum' - name: Run tests working-directory: core run: | # Find all directories containing *_test.go files test_dirs=$(find . -name "*_test.go" -exec dirname {} \; | sort -u) # Run go test on each directory for dir in $test_dirs do echo "Running tests in $dir" go test ./$dir done build_backend: needs: [ setup, test_backend ] if: needs.test_backend.result == 'success' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build image run: | cd $IMAGE_PATH_CRAWLAB_BACKEND docker build . --file Dockerfile --tag image - name: Log into registry run: echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin - name: Push image run: | IMAGE_VERSION=${{needs.setup.outputs.version}} IMAGE_NAME=$IMAGE_NAME_CRAWLAB_BACKEND docker tag image $IMAGE_NAME:$IMAGE_VERSION docker push $IMAGE_NAME:$IMAGE_VERSION build_frontend: needs: [ setup ] if: needs.setup.outputs.frontend_changed == 'true' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build image run: | cd $IMAGE_PATH_CRAWLAB_FRONTEND docker build . --file Dockerfile --tag image - name: Log into registry run: echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin - name: Push image run: | IMAGE_VERSION=${{needs.setup.outputs.version}} IMAGE_NAME=$IMAGE_NAME_CRAWLAB_FRONTEND docker tag image $IMAGE_NAME:$IMAGE_VERSION docker push $IMAGE_NAME:$IMAGE_VERSION build_crawlab: needs: [setup, build_backend, build_frontend] if: | always() && ((needs.setup.outputs.backend_changed == 'true' && needs.build_backend.result == 'success') || (needs.setup.outputs.frontend_changed == 'true' && needs.build_frontend.result == 'success') || (needs.setup.outputs.dockerfile_changed == 'true')) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Update Dockerfile run: | IMAGE_VERSION=${{needs.setup.outputs.version}} if [[ $IMAGE_VERSION != "latest" ]]; then for n in crawlab-backend crawlab-frontend; do IMAGE_NAME=$n sed -i "s/${IMAGE_NAME}:latest/${IMAGE_NAME}:${IMAGE_VERSION}/" Dockerfile done fi - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push image uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile push: true tags: | ghcr.io/${{ github.repository }}/crawlab:${{ needs.setup.outputs.image_hash }} test_crawlab: needs: [setup, build_crawlab] if: ${{ always() && needs.build_crawlab.result == 'success' }} runs-on: ubuntu-latest services: mongo: image: mongo:5 ports: - 27017:27017 crawlab: image: ghcr.io/${{ github.repository }}/crawlab:${{ needs.setup.outputs.image_hash }} env: CRAWLAB_NODE_MASTER: "true" CRAWLAB_MONGO_HOST: mongo CRAWLAB_MONGO_PORT: 27017 ports: - 8080:8080 steps: - uses: actions/checkout@v4 with: submodules: 'recursive' - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '20' - name: Install pnpm run: npm install -g pnpm@9 - name: Install dependencies working-directory: tests/e2e run: pnpm install - name: Install Playwright browser id: install_playwright working-directory: tests/e2e run: pnpm playwright install --with-deps - name: Run Playwright tests id: run_playwright working-directory: tests/e2e run: pnpm playwright test - name: Upload Playwright report id: upload_playwright_report uses: actions/upload-artifact@v3 if: ${{ always() && steps.install_playwright.outcome == 'success' }} with: name: playwright-report path: tests/e2e/playwright-report/ retention-days: 1 push_images: if: ${{ always() && needs.test_crawlab.result == 'success' }} needs: [setup, test_crawlab] runs-on: ubuntu-latest strategy: matrix: registry: [dockerhub, tencent] steps: - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Pull Docker image from GitHub Container Registry run: docker pull ghcr.io/${{ github.repository }}/crawlab:${{ needs.setup.outputs.image_hash }} - name: Login to DockerHub or Tencent Registry uses: docker/login-action@v3 with: registry: ${{ (matrix.registry == 'dockerhub' && 'https://index.docker.io/v1/') || (matrix.registry == 'tencent' && 'ccr.ccs.tencentyun.com') }} username: ${{ (matrix.registry == 'dockerhub' && secrets.DOCKER_USERNAME) || (matrix.registry == 'tencent' && secrets.DOCKER_TENCENT_USERNAME) }} password: ${{ (matrix.registry == 'dockerhub' && secrets.DOCKER_PASSWORD) || (matrix.registry == 'tencent' && secrets.DOCKER_TENCENT_PASSWORD) }} - name: Tag and push image run: | docker tag ghcr.io/${{ github.repository }}/crawlab:${{ needs.setup.outputs.image_hash }} ${{ (matrix.registry == 'dockerhub' && env.IMAGE_NAME_CRAWLAB) || (matrix.registry == 'tencent' && env.IMAGE_NAME_CRAWLAB_TENCENT) }}:${{ needs.setup.outputs.version }} docker push ${{ (matrix.registry == 'dockerhub' && env.IMAGE_NAME_CRAWLAB) || (matrix.registry == 'tencent' && env.IMAGE_NAME_CRAWLAB_TENCENT) }}:${{ needs.setup.outputs.version }} cleanup: needs: [setup, push_images] if: always() runs-on: ubuntu-latest steps: - name: Delete temporary image uses: actions/github-script@v6 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const owner = context.repo.owner; const repo = context.repo.repo; const package_name = 'crawlab'; const tag = '${{ needs.setup.outputs.image_hash }}'; try { await github.rest.packages.deletePackageVersionForOrg({ package_type: 'container', package_name: package_name, org: owner, version_id: tag, }); console.log(`Successfully deleted image: ${owner}/${repo}/${package_name}:${tag}`); } catch (error) { console.error('Failed to delete image:', error); }