diff --git a/.github/workflows/ci_scripts/ghcr_utils.py b/.github/workflows/ci_scripts/ghcr_utils.py new file mode 100644 index 0000000..dfe2398 --- /dev/null +++ b/.github/workflows/ci_scripts/ghcr_utils.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2017-2021 ARM Limited. All rights reserved. +SPDX-License-Identifier: Apache-2.0 +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at +http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations +""" +import click +import requests +import logging +import sys +import time +import json +import subprocess + +""" +This file contains ghcr utlity wrapper used for: +- retrieving digest of docker image +- deleting images in ghcr +""" + + +@click.command() +@click.pass_context +@click.option("-r", "--repository", required=True) +@click.option("-t", "--tag", required=True) +@click.option("-p", "--platform", required=False) +def get_digest(ctx, repository, tag, platform=None): + """ + Prints docker digest of specific platform of multi architecture image + :param ctx: click context + :param repository: docker repository + :param tag: docker tag + :param platform: platform for e.g, linux/arm64 + """ + command = f"docker run quay.io/skopeo/stable --creds={ctx.obj['username']}:{ctx.obj['passwd']} inspect docker://ghcr.io/{ctx.obj['username']}/{repository}:{tag} --raw" + output = subprocess.run( + command.split(), stdout=subprocess.PIPE, check=True + ).stdout.decode("utf-8") + output = json.loads(output) + + images = output["manifests"] + digest = "" + if len(images) and platform is None: + logging.error( + "This tag has more than one platform associated to it, please input a platform" + ) + sys.exit(1) + + for image in images: + if platform != None: + if (platform.split("/")[0] == image["platform"]["os"]) and ( + platform.split("/")[1] == image["platform"]["architecture"] + ): + digest = image["digest"] + else: + digest = image["digest"] + + if digest == "": + logging.error("Digest not found. image not in repo for the given platform") + sys.exit(1) + + print(digest) + + +@click.command() +@click.pass_context +@click.option("-r", "--repository", required=True) +@click.option( + "-n", + "--number_of_days", + default="10", + help="number of days since image was created", + required=False, +) +def delete_old_images(ctx, repository, number_of_days): + """ + delete old images from docker repository + + :param ctx: click context + :param repository: docker repository + :param number_of_days: delete older than these number of days + """ + with requests.Session() as s: + github_api_accept = "application/vnd.github.v3+json" + s.headers.update( + {"Authorization": f'token {ctx.obj["passwd"]}', "Accept": github_api_accept} + ) + r = s.get( + f"https://api.github.com/user/packages/container/{repository}/versions" + ) + versions = r.json() + version_id = None + pattern = "%d.%m.%Y %H:%M:%S" + pattern = "%Y-%m-%dT%H:%M:%SZ" + current_time = time.time() + for version in versions: + logging.info(version) + epoch = int(time.mktime(time.strptime(version["updated_at"], pattern))) + + if (current_time - epoch) / (24 * 60 * 60) > int(number_of_days): + version_id = version["id"] + logging.debug(f"deleteing image with version id {version_id}") + + url = f"https://api.github.com/user/packages/container/{repository}/versions/{version_id}" + resp = s.delete(url) + resp.raise_for_status() + + +@click.group() +@click.pass_context +@click.option("-u", "--username", required=False) +@click.option("-p", "--passwd", required=False) +@click.option("-v", "--verbose", is_flag=True, default=False) +def main(ctx, username, passwd, verbose): + ctx.obj = {"username": username, "passwd": passwd} + + if verbose: + logging.basicConfig( + stream=sys.stdout, + format="%(levelname)s %(asctime)s %(message)s", + datefmt="%m/%d/%Y %I:%M:%S %p", + ) + logging.getLogger().setLevel(logging.DEBUG) + else: + logging.basicConfig( + format="%(levelname)s %(asctime)s %(message)s", + datefmt="%m/%d/%Y %I:%M:%S %p", + ) + logging.getLogger().setLevel(logging.INFO) + + +if __name__ == "__main__": + main.add_command(get_digest) + main.add_command(delete_old_images) + main() diff --git a/.github/workflows/docker_management.branch.yml b/.github/workflows/docker_management.branch.yml new file mode 100644 index 0000000..ee47f8e --- /dev/null +++ b/.github/workflows/docker_management.branch.yml @@ -0,0 +1,237 @@ +name: Publish or Update docker image for head of branch +# Design details in https://github.com/ARMmbed/mbed-os/blob/master/docs/design-documents/docker_management + +on: + + # passive update once a week + schedule: + - cron: '15 4 * * 6' + + # build on master branch when there is changes for active update + push: + branches: + - master + + paths: + - requirements.txt + - docker_images/mbed-os-env/** + - .github/workflows/docker_management.branch.yml + + + # manual trigger when needed + workflow_dispatch: + + +jobs: + prepare-tags: + runs-on: ubuntu-latest + + steps: + - + name: Extract branch name + shell: bash + run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" + id: extract_branch + + - + name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - + name: Set UUID + id: generate-uuid + uses: filipstefansson/uuid-action@v1 + +# set docker tags we are building, and intending to publish +# dev-tag is temporary for testing purpose. This should be considered as unstable. +# dated-tag is created for versioning purpose +# prod-tag-latest could be used by customers, CI etc for keeping up to date + - + name: Get build information + shell: bash + run: | + mkdir -p build_info + date=$(date +"%Y.%m.%dT%H.%M.%S") + echo dev-${{ steps.extract_branch.outputs.branch }}-${date}-${{ steps.generate-uuid.outputs.uuid }} > build_info/dev_tag + echo ${{ steps.extract_branch.outputs.branch }}-${date} > build_info/prod_tag_dated + echo ${{ steps.extract_branch.outputs.branch }}-latest > build_info/prod_tag_latest + echo ${{ steps.extract_branch.outputs.branch }} > build_info/mbed_os_version + + - + name: Archive information + uses: actions/upload-artifact@v2 + with: + name: build-info + path: build_info + + + build-container: + runs-on: ubuntu-latest + needs: prepare-tags + outputs: + DEV_DIGEST: ${{ steps.docker_info_dev.outputs.DIGEST }} + PROD_DIGEST: ${{ steps.docker_info_prod.outputs.DIGEST }} + + steps: + - + name: unarchive artefacts + uses: actions/download-artifact@v2 + with: + name: build-info + + - + name: Get build info from archive + shell: bash + id: build_info + run: | + value=`cat dev_tag` + echo "DEV TAG is $value" + echo "::set-output name=DOCKER_DEV_TAG::$value" + value=`cat prod_tag_dated` + echo "PROD TAG DATED is $value" + echo "::set-output name=DOCKER_PROD_TAG_DATED::$value" + value=`cat prod_tag_latest` + echo "::set-output name=DOCKER_PROD_TAG_LATEST::$value" + echo "PROD TAG is $value" + + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - + name: Login to DockerHub + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - + name: Checkout + uses: actions/checkout@v2 + + - + name: Build docker containers + uses: docker/build-push-action@v2 + id: docker_build_dev + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + file: ./docker_images/mbed-os-env/Dockerfile + tags: ghcr.io/${{ github.actor }}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} + + test-container: + runs-on: ubuntu-latest + needs: build-container + strategy: + matrix: + platform: [linux/amd64, linux/arm64] + + steps: + - + name: unarchive artefacts + uses: actions/download-artifact@v2 + with: + name: build-info + + - + name: Get build info from archive + shell: bash + id: build_info + run: | + value=`cat dev_tag` + echo "TAG is $value" + echo "::set-output name=DOCKER_DEV_TAG::$value" + value=`cat prod_tag_dated` + echo "TAG is $value" + echo "::set-output name=DOCKER_PROD_TAG_DATED::$value" + value=`cat prod_tag_latest` + echo "::set-output name=DOCKER_PROD_TAG_LATEST::$value" + value=`cat mbed_os_version` + echo "::set-output name=MBED_OS_VERSION::$value" + + - + name: Checkout + uses: actions/checkout@v2 + + - + name: Find DEV DOCKER DIGEST + id: docker_info_dev + run: | + DIGEST=$(python ./.github/workflows/ci_scripts/ghcr_utils.py -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }} get-digest -r mbed-os-env-tmp -t ${{ steps.build_info.outputs.DOCKER_DEV_TAG }} -p ${{ matrix.platform }} ) + echo "::set-output name=DIGEST::$DIGEST" + echo "Docker DIGEST: $DIGEST" + + # as the dev images are created only for master branch, run test against + # development branch of blinky + - + name: Checkout + uses: actions/checkout@v2 + with: + repository: ARMmbed/mbed-os-example-blinky + path: mbed-os-example-blinky + ref: development + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - + name: test the container + id: test + uses: addnab/docker-run-action@v3 + with: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + registry: ghcr.io + options: -v ${{ github.workspace }}:/work -w=/work + image: ghcr.io/${{ github.actor }}/mbed-os-env-tmp@${{ steps.docker_info_dev.outputs.DIGEST }} + shell: bash + + run: | + uname -m + cd mbed-os-example-blinky + mbed deploy + # build using CLI1 + mbed compile -m K64F -t GCC_ARM + + # build using CLI2 + mbed-tools compile -m K64F -t GCC_ARM + + + deploy-container: + runs-on: ubuntu-latest + needs: test-container + + steps: + - + name: unarchive artefacts + uses: actions/download-artifact@v2 + with: + name: build-info + + - + name: Get build info from archive + shell: bash + id: build_info + run: | + value=`cat dev_tag` + echo "TAG is $value" + echo "::set-output name=DOCKER_DEV_TAG::$value" + value=`cat prod_tag_dated` + echo "TAG is $value" + echo "::set-output name=DOCKER_PROD_TAG_DATED::$value" + value=`cat prod_tag_latest` + echo "::set-output name=DOCKER_PROD_TAG_LATEST::$value" + + - + name: copy dev tag to prod + run: | + docker run quay.io/skopeo/stable --src-creds=${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} --dest-creds=${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} copy --all docker://ghcr.io/${{ github.actor }}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} docker://ghcr.io/${{ github.actor }}/mbed-os-env:${{ steps.build_info.outputs.DOCKER_PROD_TAG_LATEST }} + docker run quay.io/skopeo/stable --src-creds=${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} --dest-creds=${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} copy --all docker://ghcr.io/${{ github.actor }}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} docker://ghcr.io/${{ github.actor }}/mbed-os-env:${{ steps.build_info.outputs.DOCKER_PROD_TAG_DATED }} diff --git a/.github/workflows/docker_management.prune.yml b/.github/workflows/docker_management.prune.yml new file mode 100644 index 0000000..e99cd52 --- /dev/null +++ b/.github/workflows/docker_management.prune.yml @@ -0,0 +1,25 @@ +name: Prune temporary docker images + +on: + schedule: + - cron: '15 4 * * 6' + + workflow_dispatch: + +jobs: + prune-images: + runs-on: ubuntu-latest + + steps: + - + name: Checkout + uses: actions/checkout@v2 + + - + name: Delete old temporary images + run: | + # the following command may fail because github package doesn't allow + # deletion if only one image exists or if DOCKER_MANAGEMENT_TOKEN is not + # setup. This shouldn't create any alarm as temporary image deletion is + # not a critical activity. + python ./.github/workflows/ci_scripts/ghcr_utils.py -u ${{ github.actor }} -p ${{ secrets.DOCKER_MANAGEMENT_TOKEN }} delete-old-images -r mbed-os-env-tmp || true diff --git a/.github/workflows/docker_management.release.yml b/.github/workflows/docker_management.release.yml new file mode 100644 index 0000000..c2d9042 --- /dev/null +++ b/.github/workflows/docker_management.release.yml @@ -0,0 +1,285 @@ +name: Release or update docker image for a released mbed-os version + +# Design doc: https://github.com/ARMmbed/mbed-os/blob/master/docs/design-documents/docker_management + +on: + push: + tags: + - mbed-os-6.[0-9]+.[0-9]+ + + schedule: + - cron: '15 4 * * 6' + + workflow_dispatch: + inputs: + mbed_os_release_version: + description: 'mbed-os release version for which you want to update docker image.' + required: true + +jobs: + # this job finds the necessary tags to be applied to docker image + prepare-tags: + runs-on: ubuntu-latest + + steps: + - + name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - + # if manually triggered makes sure that input tag exists on the branch selected + # this is to avoid silly mistakes, for example: mbed-os-7.0.16-latest docker image + # getting released on mbed-os-6 branch + if: ${{ github.event_name == 'workflow_dispatch' }} + name: Sanity check tag of manual trigger + shell: bash + run: | + if [ -z $(git tag --merged ${GITHUB_REF} ${{ github.event.inputs.mbed_os_release_version }}) ]; then + echo "Check the tag name ${{ github.event.inputs.mbed_os_release_version }} is not found on branch ${GITHUB_REF}" + exit 1 + fi + + - + name: Set UUID + id: generate-uuid + uses: filipstefansson/uuid-action@v1 + + - + # set docker tags we are building, and intending to release + # this workflow can be executed when a tag is pushed, scheduled, or manual trigger + # depending on the trigger cache source and version of mbed-os will change + # + # when trigger is due to tag pushed (ie, a new mbed-os release is made), + # we are targeting to build docker image for the tag + # when trigger is manual + # we are targeting to build docker image for the input tag in workflow + # when trigger is scheduled + # we are targeting to build docker image for the last tag on the branch + name: Get build information + shell: bash + run: | + mkdir -p build_info + date=$(date +"%Y.%m.%dT%H.%M.%S") + if [ "push" == "${{github.event_name}}" ];then + version=${GITHUB_REF#refs/tags/} + elif [ "workflow_dispatch" == "${{github.event_name}}" ];then + version=${{ github.event.inputs.mbed_os_release_version }} + else + version=`git describe --tags --abbrev=0 --match mbed-os-[0-9]*.[0-9]*.[0-9]*` + fi + echo dev-${version}-${date}-${version} > build_info/dev_tag + echo ${version}-${date} > build_info/prod_tag_dated + echo ${version} > build_info/mbed_os_version + + - + name: Archive information + uses: actions/upload-artifact@v2 + with: + name: build-info + path: build_info + + + build-container: + runs-on: ubuntu-latest + needs: prepare-tags + outputs: + DEV_DIGEST: ${{ steps.docker_info_dev.outputs.DIGEST }} + PROD_DIGEST: ${{ steps.docker_info_prod.outputs.DIGEST }} + + steps: + - + name: unarchive artefacts + uses: actions/download-artifact@v2 + with: + name: build-info + + # DOCKER_DEV_TAG is temporary image name. + # DOCKER_PROD_TAG_DATED is fixed tag + # prod-tag-latest could be used by customers, CI etc for keeping up to date + - + name: Get build info from archive + shell: bash + id: build_info + run: | + value=`cat dev_tag` + echo "TAG is $value" + echo "::set-output name=DOCKER_DEV_TAG::$value" + value=`cat prod_tag_dated` + echo "TAG is $value" + echo "::set-output name=DOCKER_PROD_TAG_DATED::$value" + value=`cat mbed_os_version` + echo "::set-output name=MBED_OS_VERSION::$value" + + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - + name: Login to DockerHub + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - + name: Checkout + uses: actions/checkout@v2 + with: + ref: refs/tags/${{ steps.build_info.outputs.MBED_OS_VERSION }} + + - + name: Build docker containers + uses: docker/build-push-action@v2 + id: docker_build_dev + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + file: ./docker_images/mbed-os-env/Dockerfile + tags: ghcr.io/${{ github.actor }}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} + + + test-container: + runs-on: ubuntu-latest + needs: build-container + strategy: + matrix: + platform: [linux/amd64, linux/arm64] + + steps: + - + name: unarchive artefacts + uses: actions/download-artifact@v2 + with: + name: build-info + + - + name: Get build info from archive + shell: bash + id: build_info + run: | + value=`cat dev_tag` + echo "TAG is $value" + echo "::set-output name=DOCKER_DEV_TAG::$value" + value=`cat prod_tag_dated` + echo "TAG is $value" + echo "::set-output name=DOCKER_PROD_TAG_DATED::$value" + value=`cat mbed_os_version` + echo "::set-output name=MBED_OS_VERSION::$value" + + # as the dev images are created only for master branch, run test against + # development branch of blinky + - + name: Checkout example blinky + uses: actions/checkout@v2 + with: + repository: ARMmbed/mbed-os-example-blinky + path: mbed-os-example-blinky + fetch-depth: 0 + + + - + name: update the example application version to test against correct version + # When mbed-os tag is applied, and workflow is triggered to build RELEASE image, example application with same tag will be available yet. + # use release candidate branch to test the image in that case. + # When RELEASE image is passively checked, tag should be available in example application repo, then use it. + shell: bash + id: example_app_info + run: | + cd mbed-os-example-blinky + EXAMPLE_VERSION="release_candidate" + MBED_OS_VERSION=${{ steps.build_info.outputs.MBED_OS_VERSION }} + # if tag is present in example repo, use the tag + if git rev-parse "$MBED_OS_VERSION" >/dev/null 2>&1; then + EXAMPLE_VERSION=$MBED_OS_VERSION + fi + # echo "::set-output VERSION=MBED_OS_VERSION::$EXAMPLE_VERSION" + git checkout ${EXAMPLE_VERSION} + + - + name: Checkout + uses: actions/checkout@v2 + with: + ref: refs/tags/${{ steps.build_info.outputs.MBED_OS_VERSION }} + path: mbed-os-example-blinky/mbed-os + + - + name: Find DEV DOCKER DIGEST + id: docker_info + run: | + cd mbed-os-example-blinky/mbed-os + DIGEST=$(python ./.github/workflows/ci_scripts/ghcr_utils.py -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }} get-digest -r mbed-os-env-tmp -t ${{ steps.build_info.outputs.DOCKER_DEV_TAG }} -p ${{ matrix.platform }} ) + echo "::set-output name=DIGEST::$DIGEST" + echo "Docker DIGEST: $DIGEST" + + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - + name: test the container + id: test + uses: addnab/docker-run-action@v3 + with: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + registry: ghcr.io + options: -v ${{ github.workspace }}:/work -w=/work + image: ghcr.io/${{ github.actor }}/mbed-os-env-tmp@${{ steps.docker_info.outputs.DIGEST }} + shell: bash + run: | + uname -m + cd mbed-os-example-blinky + # build using CLI1 + mbed compile -m K64F -t GCC_ARM + + # build using CLI2 + mbed-tools compile -m K64F -t GCC_ARM + + + deploy-container: + runs-on: ubuntu-latest + needs: test-container + steps: + - + name: unarchive artefacts + uses: actions/download-artifact@v2 + with: + name: build-info + + - + name: Get build info from archive + shell: bash + id: build_info + run: | + value=`cat dev_tag` + echo "DEV TAG is $value" + echo "::set-output name=DOCKER_DEV_TAG::$value" + value=`cat prod_tag_dated` + echo "DATED PROD TAG is $value" + echo "::set-output name=DOCKER_PROD_TAG_DATED::$value" + value=`cat mbed_os_version` + echo "MBED OS VERSION is $value" + echo "::set-output name=MBED_OS_VERSION::$value" + + - + name: copy dev tag to prod tags + run: | + set -x + echo ${{ needs.test-container.result }} + upto_patch_version=${{ steps.build_info.outputs.MBED_OS_VERSION }}-latest + upto_min_version=${upto_patch_version%.[0-9]*}-latest + upto_major_version=${upto_patch_version%.[0-9]*.[0-9]*}-latest + docker run quay.io/skopeo/stable --src-creds=${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} --dest-creds=${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} copy --all docker://ghcr.io/${{ github.actor }}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} docker://ghcr.io/${{ github.actor }}/mbed-os-env:${upto_patch_version} + docker run quay.io/skopeo/stable --src-creds=${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} --dest-creds=${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} copy --all docker://ghcr.io/${{ github.actor }}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} docker://ghcr.io/${{ github.actor }}/mbed-os-env:${upto_min_version} + docker run quay.io/skopeo/stable --src-creds=${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} --dest-creds=${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} copy --all docker://ghcr.io/${{ github.actor }}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} docker://ghcr.io/${{ github.actor }}/mbed-os-env:${upto_major_version} + + # copy to fixed tag + docker run quay.io/skopeo/stable --src-creds=${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} --dest-creds=${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} copy --all docker://ghcr.io/${{ github.actor }}/mbed-os-env-tmp:${{ steps.build_info.outputs.DOCKER_DEV_TAG }} docker://ghcr.io/${{ github.actor }}/mbed-os-env:${{ steps.build_info.outputs.DOCKER_PROD_TAG_DATED }} diff --git a/.github/workflows/docker_management.test-PR.yml b/.github/workflows/docker_management.test-PR.yml new file mode 100644 index 0000000..d41391a --- /dev/null +++ b/.github/workflows/docker_management.test-PR.yml @@ -0,0 +1,82 @@ +name: Build docker image + +# This workflow is triggered when Dockerfile related or github action itself changes are made in a PR +# The workflow is quite simple - builds and test the image. Release of newer version is done only when PR is merged. +# Design doc: https://github.com/ARMmbed/mbed-os/blob/master/docs/design-documents/docker_management + +on: + pull_request: + branches: [ master ] + paths: + - docker_images/mbed-os-env/** + - .github/workflows/docker_management.* + - requirements.txt + +jobs: + + build-container: + runs-on: ubuntu-latest + + strategy: + matrix: + platform: [linux/amd64, linux/arm64] + + steps: + + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + # for PR tests, development branch of blinky is used + - + name: Checkout + uses: actions/checkout@v2 + with: + repository: ARMmbed/mbed-os-example-blinky + path: mbed-os-example-blinky + ref: development + + - + name: Remove mbed-os from example-application + shell: bash + run: | + cd mbed-os-example-blinky + rm -rf mbed-os + + - + name: Checkout + uses: actions/checkout@v2 + with: + path: mbed-os-example-blinky/mbed-os + + - + name: Build container + uses: docker/build-push-action@v2 + id: docker_build_dev + with: + context: ./mbed-os-example-blinky/mbed-os + platforms: ${{ matrix.platform }} + file: ./mbed-os-example-blinky/mbed-os/docker_images/mbed-os-env/Dockerfile + load: true + tags: mbed-os-env:a_pr_test + + - + name: test the container + id: test + uses: addnab/docker-run-action@v2 + with: + options: -v ${{ github.workspace }}:/work -w=/work + image: mbed-os-env:a_pr_test + shell: bash + run: | + uname -m + cd mbed-os-example-blinky + # build using CLI1 + mbed compile -m K64F -t GCC_ARM + + # build using CLI2 + mbed-tools compile -m K64F -t GCC_ARM diff --git a/docker_images/mbed-os-env/Dockerfile b/docker_images/mbed-os-env/Dockerfile new file mode 100644 index 0000000..c337053 --- /dev/null +++ b/docker_images/mbed-os-env/Dockerfile @@ -0,0 +1,93 @@ +# ------------------------------------------------------------------------------ +# Pull base image +FROM ubuntu:20.04 + +# ------------------------------------------------------------------------------ +# Arguments +ARG WORKDIR=/root + +# ------------------------------------------------------------------------------ +# Install tools via apt +ENV DEBIAN_FRONTEND=noninteractive +RUN set -x \ + && apt -y update \ + && apt -y install \ + git \ + wget \ + python3 \ + python3-dev \ + python3-setuptools \ + python3-pip \ + build-essential \ + astyle \ + mercurial \ + ninja-build \ + libssl-dev \ + cargo \ + flex \ + bison \ + doxygen \ + aspell \ + ccache \ + gcovr \ + && apt clean && rm -rf /var/lib/apt/lists \ + && update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1 \ + && : # last line + +RUN set -x \ + && pip3 install -U cmake + +# Set up Mbed environment +WORKDIR /tmp/ +COPY requirements.txt . +RUN set -x \ + && pip3 install -r requirements.txt \ + && : # last line + +COPY tools/cmake/requirements.txt . +RUN set -x \ + && pip3 install -r requirements.txt \ + && : # last line + + +# ------------------------------------------------------------------------------ +# Install Python modules (which are not included in requirements.txt) +RUN set -x \ + && pip3 install -U \ + mbed-cli \ + mbed-tools \ + && : # last line + +# ------------------------------------------------------------------------------ +# Install arm-none-eabi-gcc +WORKDIR /opt/mbed-os-toolchain +RUN set -x \ + && [ "$(uname -m)" = "aarch64" ] && \ + TARBALL="gcc-arm-none-eabi-9-2019-q4-major-aarch64-linux.tar.bz2" || \ + TARBALL="gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2" \ + && wget -q https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2019q4/RC2.1/${TARBALL} \ + && tar -xjf ${TARBALL} \ + && rm ${TARBALL} \ + && : # last line + +# ------------------------------------------------------------------------------ +# Configure environment variables +ENV MBED_GCC_ARM_PATH=/opt/mbed-os-toolchain/gcc-arm-none-eabi-9-2019-q4-major/bin/ +ENV PATH="${PATH}:${MBED_GCC_ARM_PATH}" + +# ------------------------------------------------------------------------------ +# Display, check and save environment settings +# NOTE: using bash instead of Ubuntu default bash due to unsupport for pipefail +# Pipefail is crucial here, if the tools didn't install properly, docker build should not pass because of piping +RUN /bin/bash -c \ + "set -x -o pipefail \ + && arm-none-eabi-gcc --version | grep arm-none-eabi-gcc | tee env_settings \ + && cmake --version | grep version | tee -a env_settings \ + && python --version 2>&1 | tee -a env_settings \ + && (echo -n 'mbed-cli ' && mbed --version) | tee -a env_settings \ + && (echo -n 'mbed-greentea ' && mbedgt --version | grep ^[0-9]) | tee -a env_settings \ + && (echo -n 'mbed-host-tests ' && mbedhtrun --version) | tee -a env_settings \ + && (echo -n 'mbed-tools ' && mbed-tools --version) | tee -a env_settings \ + && : # LAST LINE" + +WORKDIR /root diff --git a/docker_images/mbed-os-env/README.md b/docker_images/mbed-os-env/README.md new file mode 100644 index 0000000..54ced8c --- /dev/null +++ b/docker_images/mbed-os-env/README.md @@ -0,0 +1,50 @@ +# Mbed OS development environment Docker image + +This Docker image is the official Mbed OS development environment. + +* It is based on Ubuntu 20.04 +* Python and CMake are installed +* Arm-none-eabi-gcc toolchain is installed +* Latest released version of mbed-cli and mbed-greentea are installed +* All other Mbed OS dependency tools are installed. + +# How to use the Docker image: + +## Pull the Docker image +```bash +docker pull ghcr.io/armmbed/mbed-os-env: