ghcr_app.yml 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. # Workflow that builds, tests and then pushes the app docker images to the ghcr.io repository
  2. name: Build and Publish App Image
  3. # Always run on "main"
  4. # Always run on tags
  5. # Always run on PRs
  6. # Can also be triggered manually
  7. on:
  8. push:
  9. branches:
  10. - main
  11. tags:
  12. - '*'
  13. pull_request:
  14. workflow_dispatch:
  15. inputs:
  16. reason:
  17. description: 'Reason for manual trigger'
  18. required: true
  19. default: ''
  20. jobs:
  21. # Builds the OpenHands Docker images
  22. ghcr_build:
  23. name: Build App Image
  24. runs-on: ubuntu-latest
  25. outputs:
  26. tags: ${{ steps.capture-tags.outputs.tags }}
  27. last_tag: ${{ steps.capture-last-tag.outputs.last_tag }}
  28. permissions:
  29. contents: read
  30. packages: write
  31. strategy:
  32. matrix:
  33. image: ['openhands']
  34. platform: ['amd64', 'arm64']
  35. steps:
  36. - name: Checkout
  37. uses: actions/checkout@v4
  38. - name: Free Disk Space (Ubuntu)
  39. uses: jlumbroso/free-disk-space@main
  40. with:
  41. # this might remove tools that are actually needed,
  42. # if set to "true" but frees about 6 GB
  43. tool-cache: true
  44. # all of these default to true, but feel free to set to
  45. # "false" if necessary for your workflow
  46. android: true
  47. dotnet: true
  48. haskell: true
  49. large-packages: true
  50. docker-images: false
  51. swap-storage: true
  52. - name: Set up QEMU
  53. uses: docker/setup-qemu-action@v3
  54. - name: Set up Docker Buildx
  55. id: buildx
  56. uses: docker/setup-buildx-action@v3
  57. - name: Build and export image
  58. id: build
  59. run: ./containers/build.sh ${{ matrix.image }} ${{ github.repository_owner }} ${{ matrix.platform }}
  60. - name: Capture tags
  61. id: capture-tags
  62. run: |
  63. tags=$(cat tags.txt)
  64. echo "tags=$tags"
  65. echo "tags=$tags" >> $GITHUB_OUTPUT
  66. - name: Capture last tag
  67. id: capture-last-tag
  68. run: |
  69. last_tag=$(cat tags.txt | awk '{print $NF}')
  70. echo "last_tag=$last_tag"
  71. echo "last_tag=$last_tag" >> $GITHUB_OUTPUT
  72. - name: Upload Docker image as artifact
  73. uses: actions/upload-artifact@v4
  74. with:
  75. name: ${{ matrix.image }}_${{ steps.capture-last-tag.outputs.last_tag }}_${{ matrix.platform }}
  76. path: /tmp/${{ matrix.image }}_${{ steps.capture-last-tag.outputs.last_tag }}_${{ matrix.platform }}.tar
  77. retention-days: 14
  78. # Push the OpenHands and sandbox Docker images to the ghcr.io repository
  79. ghcr_push:
  80. name: Push App Image
  81. runs-on: ubuntu-latest
  82. needs: [ghcr_build]
  83. if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') || (github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main')
  84. env:
  85. tags: ${{ needs.ghcr_build.outputs.tags }}
  86. permissions:
  87. contents: read
  88. packages: write
  89. strategy:
  90. matrix:
  91. image: ['openhands']
  92. last_tag: ${{ needs.ghcr_build.outputs.last_tag }}
  93. platform: ['amd64', 'arm64']
  94. steps:
  95. - name: Checkout code
  96. uses: actions/checkout@v4
  97. - name: Login to GHCR
  98. uses: docker/login-action@v3
  99. with:
  100. registry: ghcr.io
  101. username: ${{ github.repository_owner }}
  102. password: ${{ secrets.GITHUB_TOKEN }}
  103. - name: Download Docker images
  104. uses: actions/download-artifact@v4
  105. with:
  106. name: ${{ matrix.image }}_${{ matrix.last_tag }}_${{ matrix.platform }}
  107. path: /tmp
  108. - name: Load images and push to registry
  109. run: |
  110. mv /tmp/${{ matrix.image }}_${{ matrix.last_tag }}_${{ matrix.platform }}.tar .
  111. loaded_image=$(docker load -i ${{ matrix.image }}_${{ matrix.last_tag }}_${{ matrix.platform }}.tar | grep "Loaded image:" | head -n 1 | awk '{print $3}')
  112. echo "loaded image = $loaded_image"
  113. tags=$(echo ${tags} | tr ' ' '\n')
  114. image_name=$(echo "ghcr.io/${{ github.repository_owner }}/${{ matrix.image }}" | tr '[:upper:]' '[:lower:]')
  115. echo "image name = $image_name"
  116. for tag in $tags; do
  117. echo "tag = $tag"
  118. docker tag $loaded_image $image_name:${tag}_${{ matrix.platform }}
  119. docker push $image_name:${tag}_${{ matrix.platform }}
  120. done
  121. # Creates and pushes the OpenHands Docker image manifests
  122. create_manifest:
  123. name: Create Manifest
  124. runs-on: ubuntu-latest
  125. needs: [ghcr_build, ghcr_push]
  126. if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') || (github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main')
  127. env:
  128. tags: ${{ needs.ghcr_build.outputs.tags }}
  129. strategy:
  130. matrix:
  131. image: ['openhands']
  132. permissions:
  133. contents: read
  134. packages: write
  135. steps:
  136. - name: Checkout code
  137. uses: actions/checkout@v4
  138. - name: Login to GHCR
  139. uses: docker/login-action@v3
  140. with:
  141. registry: ghcr.io
  142. username: ${{ github.repository_owner }}
  143. password: ${{ secrets.GITHUB_TOKEN }}
  144. - name: Create and push multi-platform manifest
  145. run: |
  146. image_name=$(echo "ghcr.io/${{ github.repository_owner }}/${{ matrix.image }}" | tr '[:upper:]' '[:lower:]')
  147. echo "image name = $image_name"
  148. tags=$(echo ${tags} | tr ' ' '\n')
  149. for tag in $tags; do
  150. echo 'tag = $tag'
  151. docker buildx imagetools create --tag $image_name:$tag \
  152. $image_name:${tag}_amd64 \
  153. $image_name:${tag}_arm64
  154. done