diff options
-rw-r--r-- | .github/workflows/lint-test-build-push.yaml | 207 | ||||
-rw-r--r-- | Pipfile | 17 | ||||
-rw-r--r-- | README.md | 16 | ||||
-rw-r--r-- | azure-pipelines.yml | 20 | ||||
-rw-r--r-- | ci/build.yml | 51 | ||||
-rw-r--r-- | ci/lint-test.yml | 41 | ||||
-rw-r--r-- | ci/push.yml | 39 | ||||
-rw-r--r-- | ci/setup.yml | 23 | ||||
-rw-r--r-- | docker-compose.yml | 2 | ||||
-rw-r--r-- | docker/Dockerfile | 58 | ||||
-rw-r--r-- | docker/base.Dockerfile | 34 | ||||
-rw-r--r-- | docker/venv.Dockerfile | 20 | ||||
-rwxr-xr-x | scripts/check_dockerfiles.sh | 127 | ||||
-rwxr-xr-x | scripts/dev.sh | 9 |
14 files changed, 289 insertions, 375 deletions
diff --git a/.github/workflows/lint-test-build-push.yaml b/.github/workflows/lint-test-build-push.yaml new file mode 100644 index 0000000..641b4e6 --- /dev/null +++ b/.github/workflows/lint-test-build-push.yaml @@ -0,0 +1,207 @@ +name: Lint, Test, Build, Push + +on: + push: + branches: + - master + pull_request: + + +jobs: + lint-test: + runs-on: ubuntu-latest + env: + # Determine whether or not we should build the + # final production image and push it to GHCR. + production_build: ${{ github.event_name != 'pull_request' && + github.ref == 'refs/heads/sebastiaan/backend/cache-docker-images' }} + + steps: + # Create a short SHA-tag to tag built images + - name: Create SHA Container Tag + id: sha_tag + run: | + tag=$(cut -c 1-7 <<< $GITHUB_SHA) + echo "::set-output name=tag::$tag" + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to Github Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GHCR_TOKEN }} + + # Set up a caching directory for image layers. According to the docker + # documentation, it's recommended to use a SHA-based key to get the + # greatest change of finding the most relevant cached layer. We fall + # down to more generic containers by then matching by GitHub branch, + # to use cache generated earlier in the same branch, and finally to + # the latest cache in general. The `v0` is purely a cache version + # indicator that can be incremented manually if we want to invalidate + # old caches completely. + - name: Cache Image Layers + uses: actions/cache@v2 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-v0-buildx-${{ github.ref }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-v0-buildx-${{ github.ref }}- + ${{ runner.os }}-v0-buildx- + + # Build the image we need for testing/linting the current codebase, + # without pushing the image to the GHCR. Instead, we load it into + # the runner's docker environment so we can run it later. The + # target of this build is the `venv` stage of the Dockerfile, as we + # don't want to include the final production entry point stage. + # + # This build caches to our GitHub Actions cache and uses that cache + # during the build process as well. If no GitHub Actions cache was + # available, it will use the latest intermediate images pushed to + # the GHCR as a cache source. + - name: Build image for linting and testing + uses: docker/build-push-action@v2 + with: + context: . + file: ./docker/Dockerfile + push: false + load: true + target: venv + cache-from: | + type=local,src=/tmp/.buildx-cache + ghcr.io/python-discord/snekbox-base:latest + ghcr.io/python-discord/snekbox-venv:latest + cache-to: type=local,dest=/tmp/.buildx-cache,mode=max + tags: ghcr.io/python-discord/snekbox-venv:${{ steps.sha_tag.outputs.tag }} + + - name: Start Container + run: "docker run \ + --tty \ + --detach \ + --name snekbox_test \ + --privileged \ + --hostname pdsnk-dev \ + -e PYTHONDONTWRITEBYTECODE=1 \ + -e PIPENV_PIPFILE='/snekbox/Pipfile\' \ + -e ENV=\"${PWD}/scripts/.profile\" \ + --volume \"${PWD}\":\"${PWD}\" \ + --workdir \"${PWD}\" \ + --entrypoint /bin/bash \ + ghcr.io/python-discord/snekbox-venv:${{ steps.sha_tag.outputs.tag }}" + + - name: Install dependencies + run: "docker exec snekbox_test /bin/bash -c \ + 'pipenv install --system --deploy --dev'" + + # This runs `flake8` in the container and asks `flake8` to output + # linting errors in the format of the command for registering workflow + # error messages/annotations. This means that Github Actions will pick + # up on this output to generate nice annotations to indicate what went + # wrong where. + - name: Run linter + run: "docker exec snekbox_test /bin/bash -c 'flake8 \ + --format \"::error file=%(path)s,line=%(row)d,col=%(col)d::\ + [flake8] %(code)s: %(text)s\"'" + + # Memory limit tests would fail if this isn't disabled. + - name: Disable swap memory + run: sudo swapoff -a + + # Run unittests and generate coverage report in the container + - name: Run unit tests and generate coverage report + id: run_tests + run: | + echo '::set-output name=started::true' + cmd='coverage run -m unittest; coverage report -m' + docker exec snekbox_test /bin/bash -c "${cmd}" + + # Set-up a Python version to process the coverage reports + # Note: This step runs even if the test step failed to make + # sure we process the coverage reports. + - name: Setup python + if: always() && steps.run_tests.outputs.started == 'true' + id: python + uses: actions/setup-python@v2 + with: + python-version: '3.9' + + # We'll only ever need a single dependency in this python + # environment and we'll only use it in the CI, so let's + # install it directly here and run it. + # + # This step will publish the coverage results to coveralls.io + # print a job link in the output. It will also register a + # step in the check suite visible in the PR with a link to + # the job. + - name: Publish coverage report to coveralls.io + if: always() && steps.run_tests.outputs.started == 'true' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + pip install coveralls~=2.1 + coveralls + + # Final build stage. This is run in the same job with conditions + # to prevent us from having to reload the caching directory. We + # already built a huge chunk of the image before this point in + # the run, so it does not make sense to drop down to a completely + # fresh build environment in a new worker/runner. + + # Build the final production image and push it to GHCR, tagging it + # both with the short commit SHA and 'latest'. This step should use + # the cache that was just generated when we built the test container. + - name: Build final image + if: env.production_build == 'true' + uses: docker/build-push-action@v2 + with: + context: . + file: ./docker/Dockerfile + push: true + cache-from: | + type=local,src=/tmp/.buildx-cache + ghcr.io/python-discord/snekbox-base:latest + ghcr.io/python-discord/snekbox-venv:latest + ghcr.io/python-discord/snekbox:latest + cache-to: type=local,dest=/tmp/.buildx-cache + tags: | + ghcr.io/python-discord/snekbox:latest + ghcr.io/python-discord/snekbox:${{ steps.sha_tag.outputs.tag }} + + # Push the base image to GHCR, *with* an inline cache manifest to + # ensure we can use this image as a cache source if our GitHub Actions + # "local" cache failed to be restored. GHCR does not support pushing a + # separate cache manifest, meaning we have to use an "inline" manifest. + - name: Push base image + if: env.production_build == 'true' + uses: docker/build-push-action@v2 + with: + context: . + file: ./docker/Dockerfile + target: base + push: true + cache-from: | + type=local,src=/tmp/.buildx-cache + ghcr.io/python-discord/snekbox-base:latest + cache-to: type=inline + tags: ghcr.io/python-discord/snekbox-base:latest + + # Push the venv image to GHCR *with* an inline cache manifest. See + # the comment attached to the previous step for more information. + - name: Push venv image + if: env.production_build == 'true' + uses: docker/build-push-action@v2 + with: + context: . + file: ./docker/Dockerfile + target: venv + push: true + cache-from: | + type=local,src=/tmp/.buildx-cache + ghcr.io/python-discord/snekbox-base:latest + ghcr.io/python-discord/snekbox-venv:latest + cache-to: type=inline + tags: ghcr.io/python-discord/snekbox-venv:latest @@ -61,26 +61,29 @@ snekbox = "gunicorn -c config/gunicorn.conf.py snekbox.api.app" devsh = "sh scripts/dev.sh" build = """ docker build \ - -t pythondiscord/snekbox:latest \ + -t ghcr.io/python-discord/snekbox:latest \ -f docker/Dockerfile \ . """ buildbase = """ docker build \ - -t pythondiscord/snekbox-base:latest \ - -f docker/base.Dockerfile \ + -t ghcr.io/python-discord/snekbox-base:latest \ + -f docker/Dockerfile \ + --target base \ . """ buildvenv = """ docker build \ - -t pythondiscord/snekbox-venv:latest \ - -f docker/venv.Dockerfile \ + -t ghcr.io/python-discord/snekbox-venv:latest \ + -f docker/Dockerfile \ + --target venv \ . """ builddev = """ docker build \ - -t pythondiscord/snekbox-venv:dev \ - -f docker/venv.Dockerfile \ + -t ghcr.io/python-discord/snekbox-venv:dev \ + -f docker/Dockerfile \ + --target venv \ --build-arg DEV=1 \ . """ @@ -1,4 +1,4 @@ -[![Build Status][1]][2] +[![Build Status][1]][2] [![Coverage Status][3]][4] # snekbox @@ -33,10 +33,10 @@ See [`snekapi.py`] and [`resources`] for API documentation. ## Running snekbox -A Docker image is available on [Docker Hub]. A container can be started with the following command, which will also pull the image if it doesn't currently exist locally: +A Docker image is available in the [GitHub Container Registry]. A container can be started with the following command, which will also pull the image if it doesn't currently exist locally: ``` -docker run --ipc=none --privileged -p 8060:8060 pythondiscord/snekbox +docker run --ipc=none --privileged -p 8060:8060 ghcr.io/python-discord/snekbox ``` To run it in the background, use the `-d` option. See the documentation on [`docker run`] for more information. @@ -47,7 +47,7 @@ The above command will make the API accessible on the host via `http://localhost ### Initial Setup -A Python 3.8 interpreter and the [pipenv] package are required. Once those requirements are satisfied, install the project's dependencies: +A Python 3.9 interpreter and the [pipenv] package are required. Once those requirements are satisfied, install the project's dependencies: ``` pipenv sync --dev @@ -142,8 +142,10 @@ nsjpy "print('hello world!')" The alias can be found in `./scripts/.profile`, which is automatically added when the shell is launched in the container. -[1]: https://dev.azure.com/python-discord/Python%20Discord/_apis/build/status/Snekbox?branchName=master -[2]: https://dev.azure.com/python-discord/Python%20Discord/_build/latest?definitionId=13&branchName=master +[1]: https://github.com/python-discord/snekbox/workflows/Lint,%20Test,%20Build,%20Push/badge.svg?branch=master +[2]: https://github.com/python-discord/snekbox/actions?query=workflow%3A%22Lint%2C+Test%2C+Build%2C+Push%22+branch%3Amaster +[3]: https://coveralls.io/repos/github/python-discord/snekbox/badge.svg?branch=master +[4]: https://coveralls.io/github/python-discord/snekbox?branch=master [`snekbox.cfg`]: config/snekbox.cfg [`snekapi.py`]: snekbox/api/snekapi.py [`resources`]: snekbox/api/resources @@ -151,5 +153,5 @@ The alias can be found in `./scripts/.profile`, which is automatically added whe [nsjail]: https://github.com/google/nsjail [falcon]: https://falconframework.org/ [gunicorn]: https://gunicorn.org/ -[docker hub]: https://hub.docker.com/r/pythondiscord/snekbox +[GitHub Container Registry]: https://github.com/orgs/python-discord/packages/container/package/snekbox [pipenv]: https://docs.pipenv.org/en/latest/ diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 573e3cc..0000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,20 +0,0 @@ -# https://aka.ms/yaml - -jobs: - - job: build_lint_test_push - displayName: 'Build, Lint, Test, & Push' - - pool: - vmImage: 'ubuntu-18.04' - - variables: - BASE_CHANGED: 'True' - VENV_CHANGED: 'True' - BASE_PULL: 'False' - VENV_PULL: 'False' - - steps: - - template: ci/build.yml - - template: ci/setup.yml - - template: ci/lint-test.yml - - template: ci/push.yml diff --git a/ci/build.yml b/ci/build.yml deleted file mode 100644 index 7d51709..0000000 --- a/ci/build.yml +++ /dev/null @@ -1,51 +0,0 @@ -steps: - - task: ShellScript@2 - displayName: 'Check If Images Need to Be Built' - inputs: - scriptPath: scripts/check_dockerfiles.sh - disableAutoCwd: true - - # Without a login, the following Docker build steps wouldn't add image tags. - - task: Docker@1 - displayName: 'Log into Docker Hub' - inputs: - command: login - containerregistrytype: 'Container Registry' - dockerRegistryEndpoint: 'DockerHub' - - # Building the venv depends on this base image. Build the base if it can't - # pulled from Docker Hub, which will be the case if the base Dockerfile has - # has had changes. - - script: | - docker build \ - -f docker/base.Dockerfile \ - -t pythondiscord/snekbox-base:latest \ - . - displayName: 'Build Base Image' - condition: > - and( - succeeded(), - or( - eq(variables.BASE_CHANGED, 'True'), - and( - eq(variables.VENV_CHANGED, 'True'), - eq(variables.BASE_PULL, 'False') - ) - ) - ) - - # Build the venv image if it's had changes or it can't be pulled. - - script: | - docker build \ - -f docker/venv.Dockerfile \ - -t pythondiscord/snekbox-venv:latest \ - . - displayName: 'Build Virtual Environment Image' - condition: > - and( - succeeded(), - or( - eq(variables.VENV_CHANGED, 'True'), - eq(variables.VENV_PULL, 'False') - ) - ) diff --git a/ci/lint-test.yml b/ci/lint-test.yml deleted file mode 100644 index 2d70f6e..0000000 --- a/ci/lint-test.yml +++ /dev/null @@ -1,41 +0,0 @@ -steps: - - script: | - docker exec snekbox_test /bin/bash -c \ - 'flake8; flake8 --format junit-xml --output-file test-lint.xml' - displayName: 'Run Linter' - - - task: PublishTestResults@2 - displayName: 'Publish Lint Results' - condition: succeededOrFailed() - inputs: - testResultsFiles: '**/test-lint.xml' - testRunTitle: 'Lint Results' - - # Memory limit tests would fail if this isn't disabled. - - script: sudo swapoff -a - displayName: 'Disable Swap Memory' - - - script: | - docker exec snekbox_test /bin/bash -c \ - 'coverage run -m xmlrunner' - displayName: 'Run Unit Tests' - - - task: PublishTestResults@2 - displayName: 'Publish Test Results' - condition: succeededOrFailed() - inputs: - testResultsFiles: '**/TEST-*.xml' - testRunTitle: 'Test Results' - - # Run report too because the XML report doesn't output to stdout. - - script: | - docker exec snekbox_test /bin/bash -c \ - 'coverage report && coverage xml' - displayName: 'Generate Coverage Report' - - - task: PublishCodeCoverageResults@1 - displayName: 'Publish Coverage Results' - condition: succeededOrFailed() - inputs: - codeCoverageTool: Cobertura - summaryFileLocation: '**/coverage.xml' diff --git a/ci/push.yml b/ci/push.yml deleted file mode 100644 index 9449df0..0000000 --- a/ci/push.yml +++ /dev/null @@ -1,39 +0,0 @@ -steps: - # Always build this image unless it's for a pull request. - - script: | - docker build \ - -f docker/Dockerfile \ - -t pythondiscord/snekbox:latest \ - . - displayName: 'Build Final Image' - condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) - - # Push images only after they've all successfully been built. - - script: docker push pythondiscord/snekbox-base:latest - displayName: 'Push Base Image' - condition: > - and( - succeeded(), - ne(variables['Build.Reason'], 'PullRequest'), - ne(variables.BASE_PULL, 'True'), - or( - eq(variables.BASE_CHANGED, 'True'), - eq(variables.VENV_CHANGED, 'True') - ) - ) - - - script: docker push pythondiscord/snekbox-venv:latest - displayName: 'Push Virtual Environment Image' - condition: > - and( - succeeded(), - ne(variables['Build.Reason'], 'PullRequest'), - or( - eq(variables.BASE_CHANGED, 'True'), - eq(variables.VENV_CHANGED, 'True') - ) - ) - - - script: docker push pythondiscord/snekbox:latest - displayName: 'Push Final Image' - condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) diff --git a/ci/setup.yml b/ci/setup.yml deleted file mode 100644 index 1c66aa7..0000000 --- a/ci/setup.yml +++ /dev/null @@ -1,23 +0,0 @@ -steps: - # The linter and all tests run inside this container. - # The venv image will be pulled if it doesn't exist locally. - - script: | - docker run \ - --tty \ - --detach \ - --name snekbox_test \ - --privileged \ - --hostname pdsnk-dev \ - -e PYTHONDONTWRITEBYTECODE=1 \ - -e PIPENV_PIPFILE="/snekbox/Pipfile" \ - -e ENV="${PWD}/scripts/.profile" \ - --volume "${PWD}":"${PWD}" \ - --workdir "${PWD}"\ - --entrypoint /bin/bash \ - pythondiscord/snekbox-venv:latest - displayName: 'Start Container' - - - script: | - docker exec snekbox_test /bin/bash -c \ - 'pipenv install --system --deploy --dev' - displayName: 'Install Development Dependencies' diff --git a/docker-compose.yml b/docker-compose.yml index aec17d3..066f38b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ services: snekbox: container_name: snekbox privileged: true - image: pythondiscord/snekbox:latest + image: ghcr.io/python-discord/snekbox:latest ports: - 8060:8060 init: true diff --git a/docker/Dockerfile b/docker/Dockerfile index b6c2f77..ea05c5c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,60 @@ -FROM pythondiscord/snekbox-venv:latest +FROM python:3.9-slim-buster as builder +RUN apt-get -y update \ + && apt-get install -y \ + bison=2:3.3.* \ + flex=2.6.* \ + g++=4:8.3.* \ + gcc=4:8.3.* \ + git=1:2.20.* \ + libprotobuf-dev=3.6.* \ + libnl-route-3-dev=3.4.* \ + make=4.2.* \ + pkg-config=0.29-6 \ + protobuf-compiler=3.6.* +RUN git clone \ + -b '2.9' \ + --single-branch \ + --depth 1 \ + https://github.com/google/nsjail.git /nsjail +WORKDIR /nsjail +RUN make + +FROM python:3.9-slim-buster as base +ENV PIP_NO_CACHE_DIR=false + +RUN apt-get -y update \ + && apt-get install -y \ + gcc=4:8.3.* \ + libnl-route-3-200=3.4.* \ + libprotobuf17=3.6.* \ + && rm -rf /var/lib/apt/lists/* +RUN pip install pipenv==2020.11.4 + +COPY --from=builder /nsjail/nsjail /usr/sbin/ +RUN chmod +x /usr/sbin/nsjail + +FROM base as venv +ARG DEV + +ENV PIP_NO_CACHE_DIR=false \ + PIPENV_DONT_USE_PYENV=1 \ + PIPENV_HIDE_EMOJIS=1 \ + PIPENV_NOSPIN=1 + +COPY Pipfile Pipfile.lock /snekbox/ +WORKDIR /snekbox + +RUN if [ -n "${DEV}" ]; \ + then \ + pipenv install --deploy --system --dev; \ + else \ + pipenv install --deploy --system; \ + fi + +# At the end to avoid re-installing dependencies when only a config changes. +COPY config/ /snekbox/config + +FROM venv ENTRYPOINT ["gunicorn"] CMD ["-c", "config/gunicorn.conf.py", "snekbox.api.app"] diff --git a/docker/base.Dockerfile b/docker/base.Dockerfile deleted file mode 100644 index a4a5ad1..0000000 --- a/docker/base.Dockerfile +++ /dev/null @@ -1,34 +0,0 @@ -FROM python:3.9-slim-buster as builder -RUN apt-get -y update \ - && apt-get install -y \ - bison=2:3.3.* \ - flex=2.6.* \ - g++=4:8.3.* \ - gcc=4:8.3.* \ - git=1:2.20.* \ - libprotobuf-dev=3.6.* \ - libnl-route-3-dev=3.4.* \ - make=4.2.* \ - pkg-config=0.29-6 \ - protobuf-compiler=3.6.* -RUN git clone \ - -b '2.9' \ - --single-branch \ - --depth 1 \ - https://github.com/google/nsjail.git /nsjail -WORKDIR /nsjail -RUN make - -FROM python:3.9-slim-buster -ENV PIP_NO_CACHE_DIR=false - -RUN apt-get -y update \ - && apt-get install -y \ - gcc=4:8.3.* \ - libnl-route-3-200=3.4.* \ - libprotobuf17=3.6.* \ - && rm -rf /var/lib/apt/lists/* -RUN pip install pipenv==2020.11.4 - -COPY --from=builder /nsjail/nsjail /usr/sbin/ -RUN chmod +x /usr/sbin/nsjail diff --git a/docker/venv.Dockerfile b/docker/venv.Dockerfile deleted file mode 100644 index 5c0fcfc..0000000 --- a/docker/venv.Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM pythondiscord/snekbox-base:latest - -ARG DEV -ENV PIP_NO_CACHE_DIR=false \ - PIPENV_DONT_USE_PYENV=1 \ - PIPENV_HIDE_EMOJIS=1 \ - PIPENV_NOSPIN=1 - -COPY Pipfile Pipfile.lock /snekbox/ -WORKDIR /snekbox - -RUN if [ -n "${DEV}" ]; \ - then \ - pipenv install --deploy --system --dev; \ - else \ - pipenv install --deploy --system; \ - fi - -# At the end to avoid re-installing dependencies when only a config changes. -COPY config/ /snekbox/config diff --git a/scripts/check_dockerfiles.sh b/scripts/check_dockerfiles.sh deleted file mode 100755 index 88cb7cc..0000000 --- a/scripts/check_dockerfiles.sh +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail -shopt -s inherit_errexit -exec 3>&1 # New file descriptor to stdout - -BASE_URL="https://dev.azure.com/\ -python-discord/${SYSTEM_TEAMPROJECTID}/_apis/build/builds?\ -queryOrder=finishTimeDescending&\ -resultFilter=succeeded&\ -\$top=1&\ -repositoryType=${BUILD_REPOSITORY_PROVIDER}&\ -repositoryId=${BUILD_REPOSITORY_NAME}&\ -api-version=5.0" - -declare -A build_cache - -get_build() { - local branch="${1:?"get_build: argument 1 'branch' is unset"}" - - # Attempt to use cached value - if [[ -v build_cache["${branch}"] ]]; then - printf '%s\n' "Retrieving build for ${branch} from cache." >&3 - printf '%s' "${build_cache[$branch]}" - return 0 - fi - - local url="${BASE_URL}&branchName=${branch}" - - printf '%s\n' "Retrieving the latest successful build using ${url}" >&3 - - local response - response="$(curl -sSL "${url}")" - - if [[ -z "${response}" ]] \ - || ! count="$(printf '%s' "${response}" | jq -re '.count')" \ - || (( "${count}" < 1 )) - then - return 1 - else - # Cache the response - build_cache["${branch}"]="${response}" - printf '%s' "${response}" - fi -} - -can_pull() { - local image="${1:?"can_pull: argument 1 'image' is unset"}" - - local master_commit - if master_commit="$( - get_build "refs/heads/master" \ - | jq -re '.value[0].sourceVersion' - )" \ - && git diff --quiet "${master_commit}" -- "${@:2}" - then - printf \ - '%s\n' \ - "Can pull ${image} image from Docker Hub; no changes since master." - - printf '%s\n' "##vso[task.setvariable variable=${image^^}_PULL]True" - else - printf \ - '%s\n' \ - "Cannot pull ${image} image from Docker Hub due to detected " \ - "changes; the ${image} image will be built." - - return 1 - fi -} - -# Get the previous commit -if [[ "${BUILD_REASON}" = "PullRequest" ]]; then - if ! prev_commit="$( - get_build "${BUILD_SOURCEBRANCH}" \ - | jq -re '.value[0].triggerInfo."pr.sourceSha"' - )" - then - echo \ - "Could not retrieve the previous build's commit." \ - "Falling back to the head of the target branch." - - prev_commit="origin/${SYSTEM_PULLREQUEST_TARGETBRANCH}" - fi -elif ! prev_commit="$( - get_build "${BUILD_SOURCEBRANCH}" \ - | jq -re '.value[0].sourceVersion' - )" -then - echo \ - "No previous build was found." \ - "Either the previous build is too old and was deleted" \ - "or the branch was empty before this build." \ - "All images will be built." - exit 0 -fi - -# Compare diffs -head="$(git rev-parse HEAD)" -printf '%s\n' "Comparing HEAD (${head}) against ${prev_commit}." - -if git diff --quiet "${prev_commit}" -- docker/base.Dockerfile; then - echo "No changes detected in docker/base.Dockerfile." - echo "##vso[task.setvariable variable=BASE_CHANGED]False" -else - # Always rebuild the venv if the base changes. - echo "Changes detected in docker/base.Dockerfile; all images will be built." - exit 0 -fi - -if git diff --quiet "${prev_commit}" -- docker/venv.Dockerfile Pipfile*; then - echo "No changes detected in docker/venv.Dockerfile or the Pipfiles." - echo "##vso[task.setvariable variable=VENV_CHANGED]False" - - if ! can_pull venv docker/venv.Dockerfile Pipfile*; then - # Venv image can't be pulled so it needs to be built. - # Therefore, the base image is needed too. - can_pull base docker/base.Dockerfile || true - fi -else - echo \ - "Changes detected in docker/venv.Dockerfile or the Pipfiles;" \ - "the venv image will be built." - - # Though base image hasn't changed, it's still needed to build the venv. - can_pull base docker/base.Dockerfile || true -fi diff --git a/scripts/dev.sh b/scripts/dev.sh index 408ce2e..f9fc016 100755 --- a/scripts/dev.sh +++ b/scripts/dev.sh @@ -5,12 +5,13 @@ if [ "$1" = "--build" ]; then shift - printf "Building pythondiscord/snekbox-venv:dev..." + printf "Building ghcr.io/python-discord/snekbox-venv:dev..." docker build \ - -t pythondiscord/snekbox-venv:dev \ - -f docker/venv.Dockerfile \ + -t ghcr.io/python-discord/snekbox-venv:dev \ + -f docker/Dockerfile \ --build-arg DEV=1 \ + --target venv \ -q \ . \ >/dev/null \ @@ -46,7 +47,7 @@ docker run \ --volume "${PWD}":"${PWD}" \ --workdir "${PWD}"\ --entrypoint /bin/bash \ - pythondiscord/snekbox-venv:dev \ + ghcr.io/python-discord/snekbox-venv:dev \ >/dev/null \ # Execute the given command(s) |