name: Containers env: zephyr-version: 2.4.0 zephyr-sdk-version: 0.11.4 cache-repository-name: zmk-docker-cache on: push: pull_request: workflow_dispatch: concurrency: ${{ github.workflow }} jobs: namespaces: runs-on: ubuntu-latest outputs: docker-hub: ${{ secrets.DOCKER_HUB_NAMESPACE || github.repository_owner }} ghcr: ${{ github.repository_owner }} steps: - run: true credentials: runs-on: ubuntu-latest outputs: ghcr: ${{ steps.ghcr.outcome == 'success' }} docker-hub: ${{ steps.docker-hub.outcome == 'success' }} steps: - name: Docker Hub id: docker-hub run: if [ ${{ secrets.DOCKER_HUB_USERNAME == null || secrets.DOCKER_HUB_TOKEN == null }} = true ]; then exit 1; fi continue-on-error: true - name: GitHub Container Registry id: ghcr run: if [ ${{ secrets.GHCR_USERNAME == null || secrets.GHCR_TOKEN == null }} = true ]; then exit 1; fi continue-on-error: true architectures: runs-on: ubuntu-latest outputs: json: ${{ steps.import.outputs.json }} steps: - name: Checkout uses: actions/checkout@v2 - name: Import from architectures.yml id: import shell: python run: | import yaml, json with open('architectures.yml', 'r') as file: architectures = yaml.safe_load(file) print('::set-output name=json::' + json.dumps(architectures)) tags: runs-on: ubuntu-latest outputs: candidate: ${{ steps.definitions.outputs.candidate }} versions: ${{ steps.definitions.outputs.versions }} major-minor: ${{ steps.definitions.outputs.major-minor }} latest: ${{ steps.definitions.outputs.latest }} release-trigger: ${{ steps.definitions.outputs.release-trigger }} steps: - name: Definitions id: definitions env: SHA: ${{ github.sha }} ZEPHYR_VERSION: ${{ env.zephyr-version }} ZEPHYR_SDK_VERSION: ${{ env.zephyr-sdk-version }} run: | CANDIDATE=${SHA} VERSIONS=${ZEPHYR_VERSION}-${ZEPHYR_SDK_VERSION} MAJOR=$(echo ${ZEPHYR_VERSION} | cut -d'.' -f 1) MINOR=$(echo ${ZEPHYR_VERSION} | cut -d'.' -f 2) MAJOR_MINOR=${MAJOR}.${MINOR} LATEST=${MAJOR_MINOR} RELEASE_TRIGGER=${ZEPHYR_VERSION}-${ZEPHYR_SDK_VERSION} echo ::set-output name=candidate::${CANDIDATE} echo ::set-output name=versions::${VERSIONS} echo ::set-output name=major-minor::${MAJOR_MINOR} echo ::set-output name=latest::${LATEST} echo ::set-output name=release-trigger::${RELEASE_TRIGGER} docker: needs: - namespaces - credentials - architectures - tags runs-on: ubuntu-latest strategy: max-parallel: 1 # takes advantage of caching between jobs matrix: architecture: ${{ fromJSON(needs.architectures.outputs.json) }} target: # ordered from biggest to smallest to take advantage of the registry cache - dev - build steps: - name: Login to Docker Hub id: docker-hub-login if: ${{ needs.credentials.outputs.docker-hub == 'true' }} uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - name: Login to GitHub Container Registry id: ghcr-login if: ${{ needs.credentials.outputs.ghcr == 'true' }} uses: docker/login-action@v1 with: registry: ghcr.io username: ${{ secrets.GHCR_USERNAME }} password: ${{ secrets.GHCR_TOKEN }} - name: Prepare variables id: vars run: | REPOSITORY_NAME=zmk-${{ matrix.target }}-${{ matrix.architecture }} echo ::set-output name=repository-name::${REPOSITORY_NAME} - name: Set up QEMU if: ${{ !startsWith(github.ref, 'refs/tags') }} uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx if: ${{ !startsWith(github.ref, 'refs/tags') }} uses: docker/setup-buildx-action@v1 - name: Build and push (candidate) id: build-push if: ${{ !startsWith(github.ref, 'refs/tags') }} uses: docker/build-push-action@v2 with: target: ${{ matrix.target }} build-args: | ZEPHYR_VERSION=${{ env.zephyr-version }} ARCHITECTURE=${{ matrix.architecture }} ZEPHYR_SDK_VERSION=${{ env.zephyr-sdk-version }} labels: | org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.revision=${{ github.sha }} tags: | docker.io/${{ needs.namespaces.outputs.docker-hub }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.candidate }} cache-from: type=registry,ref=docker.io/${{ needs.namespaces.outputs.docker-hub }}/${{ env.cache-repository-name }}:dev cache-to: ${{ (steps.docker-hub-login.outcome == 'success') && (matrix.target == 'dev') && format('type=registry,ref=docker.io/{0}/{1}:{2},mode=max', needs.namespaces.outputs.docker-hub, env.cache-repository-name, 'dev') || null }} push: ${{ steps.docker-hub-login.outcome == 'success' }} - name: Release (pull candidate, tag, push) if: ${{ github.ref == format('refs/tags/{0}', needs.tags.outputs.release-trigger) }} run: | if [ "${{ steps.docker-hub-login.outcome }}" != "success" ]; then echo "Docker Hub must be authenticated to perform a release!" exit 1 fi if [ "${{ steps.ghcr-login.outcome }}" != "success" ]; then echo "GitHub Container Registry must be authenticated to perform a release!" exit 1 fi docker pull docker.io/${{ needs.namespaces.outputs.docker-hub }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.candidate }} docker tag docker.io/${{ needs.namespaces.outputs.docker-hub }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.candidate }} docker.io/${{ needs.namespaces.outputs.docker-hub }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.versions }} docker tag docker.io/${{ needs.namespaces.outputs.docker-hub }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.candidate }} docker.io/${{ needs.namespaces.outputs.docker-hub }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.latest }} docker tag docker.io/${{ needs.namespaces.outputs.docker-hub }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.candidate }} ghcr.io/${{ needs.namespaces.outputs.ghcr }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.candidate }} docker tag docker.io/${{ needs.namespaces.outputs.docker-hub }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.candidate }} ghcr.io/${{ needs.namespaces.outputs.ghcr }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.versions }} docker tag docker.io/${{ needs.namespaces.outputs.docker-hub }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.candidate }} ghcr.io/${{ needs.namespaces.outputs.ghcr }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.latest }} docker push docker.io/${{ needs.namespaces.outputs.docker-hub }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.candidate }} docker push docker.io/${{ needs.namespaces.outputs.docker-hub }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.versions }} docker push docker.io/${{ needs.namespaces.outputs.docker-hub }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.latest }} docker push ghcr.io/${{ needs.namespaces.outputs.ghcr }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.candidate }} docker push ghcr.io/${{ needs.namespaces.outputs.ghcr }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.versions }} docker push ghcr.io/${{ needs.namespaces.outputs.ghcr }}/${{ steps.vars.outputs.repository-name }}:${{ needs.tags.outputs.latest }} git-tag: needs: - tags - docker if: ${{ startsWith(github.ref, 'refs/tags') }} runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 if: ${{ github.ref == format('refs/tags/{0}', needs.tags.outputs.release-trigger) }} - name: Tag if: ${{ github.ref == format('refs/tags/{0}', needs.tags.outputs.release-trigger) }} env: TAG: ${{ needs.tags.outputs.major-minor }} run: | git tag ${TAG} git push -f origin ${TAG}