Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce Docker image rebuilds #2269

Merged
merged 16 commits into from
Feb 1, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/actions/docker-build/action.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

# Use this action to execute the action scripts in tools/ci-build/scripts within the Docker build image.
# Use this action to execute the action scripts in tools/ci-scripts.
name: smithy-rs Docker Build
description: Run Docker build command for smithy-rs
inputs:
# The name of the script in tools/ci-build/scripts to run
# The name of the script in tools/ci-scripts to run
action:
description: What action to run in the Docker build
required: true
Expand Down Expand Up @@ -43,7 +43,7 @@ runs:
# from attempting to download an image from ECR since it will already exist,
# which enables testing build image modifications as part of the pull request.
if [[ -d smithy-rs-base-image ]]; then
IMAGE_TAG="$(./smithy-rs/tools/ci-build/tools-hash)"
IMAGE_TAG="$(./smithy-rs/.github/scripts/docker-image-hash)"
docker load -i smithy-rs-base-image/smithy-rs-base-image
docker tag "smithy-rs-base-image:${IMAGE_TAG}" "smithy-rs-base-image:local"
fi
Expand All @@ -52,7 +52,7 @@ runs:
# or from ECR. We disable building the image from scratch so that any mistakes in the CI
# configuration won't cause each individual action to build its own image, which would
# drastically increase the total CI time. Fail fast!
ALLOW_LOCAL_BUILD=false ./smithy-rs/tools/ci-build/acquire-build-image
ALLOW_LOCAL_BUILD=false ./smithy-rs/.github/scripts/acquire-build-image
# This runs the commands from the matrix strategy
- name: Run ${{ inputs.action }}
shell: bash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class Context:
self.start_path = start_path
self.script_path = script_path
self.tools_path = tools_path
self.docker_image_path = tools_path + "/ci-build"
self.user_id = user_id
self.image_tag = image_tag
self.allow_local_build = allow_local_build
Expand All @@ -56,7 +57,7 @@ class Context:
script_path = os.path.dirname(os.path.realpath(__file__))
tools_path = get_cmd_output("git rev-parse --show-toplevel", cwd=script_path)[1] + "/tools"
user_id = get_cmd_output("id -u")[1]
image_tag = get_cmd_output("./ci-build/tools-hash", cwd=tools_path)[1]
image_tag = get_cmd_output("./docker-image-hash", cwd=script_path)[1]
allow_local_build = os.getenv("ALLOW_LOCAL_BUILD") != "false"
github_actions = os.getenv("GITHUB_ACTIONS") == "true"
print(f"Start path: {start_path}")
Expand Down Expand Up @@ -118,10 +119,10 @@ class Shell:
run(f"docker build -t \"smithy-rs-base-image:{image_tag}\" .", cwd=path)

# Builds the local build image
def docker_build_build_image(self, user_id, script_path):
def docker_build_build_image(self, user_id, docker_image_path):
run(
f"docker build -t smithy-rs-build-image --file add-local-user.dockerfile --build-arg=USER_ID={user_id} .",
cwd=script_path
cwd=docker_image_path
)

# Saves the Docker image named `image_name` with `image_tag` to `output_path`
Expand Down Expand Up @@ -188,7 +189,7 @@ def acquire_build_image(context=Context.default(), shell=Shell()):
return 1

announce("Building a new image locally.")
shell.docker_build_base_image(context.image_tag, context.tools_path)
shell.docker_build_base_image(context.image_tag, context.docker_image_path)

if context.github_actions:
announce("Saving base image for use in later jobs...")
Expand All @@ -205,7 +206,7 @@ def acquire_build_image(context=Context.default(), shell=Shell()):

announce("Creating local build image...")
shell.docker_tag(LOCAL_BASE_IMAGE_NAME, context.image_tag, LOCAL_BASE_IMAGE_NAME, LOCAL_TAG)
shell.docker_build_build_image(context.user_id, context.script_path)
shell.docker_build_build_image(context.user_id, context.docker_image_path)
return 0


Expand Down Expand Up @@ -373,7 +374,7 @@ class SelfTest(unittest.TestCase):

shell.docker_image_exists_locally.assert_called_once()
shell.docker_tag.assert_called_with(LOCAL_BASE_IMAGE_NAME, "someimagetag", LOCAL_BASE_IMAGE_NAME, LOCAL_TAG)
shell.docker_build_build_image.assert_called_with("123", "/tmp/test/script-path")
shell.docker_build_build_image.assert_called_with("123", "/tmp/test/tools-path")

# When:
# - the base image doesn't exist locally
Expand All @@ -393,7 +394,7 @@ class SelfTest(unittest.TestCase):
shell.docker_build_base_image.assert_called_with("someimagetag", "/tmp/test/tools-path")
shell.docker_save.assert_not_called()
shell.docker_tag.assert_called_with(LOCAL_BASE_IMAGE_NAME, "someimagetag", LOCAL_BASE_IMAGE_NAME, LOCAL_TAG)
shell.docker_build_build_image.assert_called_with("123", "/tmp/test/script-path")
shell.docker_build_build_image.assert_called_with("123", "/tmp/test/tools-path")

# When:
# - the base image doesn't exist locally
Expand All @@ -413,7 +414,7 @@ class SelfTest(unittest.TestCase):
shell.docker_build_base_image.assert_called_with("someimagetag", "/tmp/test/tools-path")
shell.docker_save.assert_not_called()
shell.docker_tag.assert_called_with(LOCAL_BASE_IMAGE_NAME, "someimagetag", LOCAL_BASE_IMAGE_NAME, LOCAL_TAG)
shell.docker_build_build_image.assert_called_with("123", "/tmp/test/script-path")
shell.docker_build_build_image.assert_called_with("123", "/tmp/test/tools-path")

# When:
# - the base image doesn't exist locally
Expand All @@ -437,7 +438,7 @@ class SelfTest(unittest.TestCase):
"/tmp/test/start-path/smithy-rs-base-image"
)
shell.docker_tag.assert_called_with(LOCAL_BASE_IMAGE_NAME, "someimagetag", LOCAL_BASE_IMAGE_NAME, LOCAL_TAG)
shell.docker_build_build_image.assert_called_with("123", "/tmp/test/script-path")
shell.docker_build_build_image.assert_called_with("123", "/tmp/test/tools-path")

# When:
# - the base image doesn't exist locally
Expand Down Expand Up @@ -477,7 +478,7 @@ class SelfTest(unittest.TestCase):
call(REMOTE_BASE_IMAGE_NAME, "someimagetag", LOCAL_BASE_IMAGE_NAME, "someimagetag"),
call(LOCAL_BASE_IMAGE_NAME, "someimagetag", LOCAL_BASE_IMAGE_NAME, LOCAL_TAG)
])
shell.docker_build_build_image.assert_called_with("123", "/tmp/test/script-path")
shell.docker_build_build_image.assert_called_with("123", "/tmp/test/tools-path")


def main():
Expand Down
File renamed without changes.
6 changes: 3 additions & 3 deletions .github/workflows/ci-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ jobs:
uses: actions/checkout@v3
- name: Build image
run: |
IMAGE_TAG="$(./tools/ci-build/tools-hash)"
cd tools
IMAGE_TAG="$(./.github/scripts/docker-image-hash)"
cd tools/ci-build
docker build \
-t "${{ env.ecr_repository }}:${IMAGE_TAG}" \
-t "${{ env.ecr_repository }}:main" \
Expand All @@ -45,7 +45,7 @@ jobs:
aws-region: us-west-2
- name: Upload image
run: |
IMAGE_TAG="$(./tools/ci-build/tools-hash)"
IMAGE_TAG="$(./.github/scripts/docker-image-hash)"
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws
docker push "${{ env.ecr_repository }}:${IMAGE_TAG}"
docker push "${{ env.ecr_repository }}:main"
Expand Down
46 changes: 46 additions & 0 deletions .github/workflows/ci-pr-forks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

# This workflow runs CI for pull requests from forks, which can't make use of secrets.

name: CI (from fork)
on:
pull_request:

# Allow one instance of this workflow per pull request, and cancel older runs when new changes are pushed
concurrency:
group: ci-forks-yaml-${{ github.ref }}
cancel-in-progress: true

jobs:
# This job detects if the PR made changes to build tools. If it did, then it builds a new
# build Docker image. Otherwise, it downloads a build image from Public ECR. In both cases,
# it uploads the image as a build artifact for other jobs to download and use.
acquire-base-image:
name: Acquire Base Image
if: ${{ github.event.pull_request.head.repo.full_name != 'awslabs/smithy-rs' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
path: smithy-rs
fetch-depth: 0
- name: Acquire base image
id: acquire
env:
DOCKER_BUILDKIT: 1
run: ./smithy-rs/.github/scripts/acquire-build-image
- name: Upload base image
uses: actions/upload-artifact@v3
with:
name: smithy-rs-base-image
path: smithy-rs-base-image
retention-days: 1

# Run shared CI after the Docker build image has either been rebuilt or found in ECR
ci:
needs: acquire-base-image
if: ${{ github.event.pull_request.head.repo.full_name != 'awslabs/smithy-rs' }}
uses: ./.github/workflows/ci.yml
with:
run_sdk_examples: true
31 changes: 22 additions & 9 deletions .github/workflows/ci-pr.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

# This workflow runs CI and the PR Bot on pull requests.
# This workflow runs CI and the PR Bot on pull requests that are not from forked repositories.

name: CI
on:
Expand All @@ -12,13 +12,20 @@ concurrency:
group: ci-yaml-${{ github.ref }}
cancel-in-progress: true

env:
ecr_repository: public.ecr.aws/w0m4q9l7/github-awslabs-smithy-rs-ci

jobs:
# This job detects if the PR made changes to build tools. If it did, then it builds a new
# build Docker image. Otherwise, it downloads a build image from Public ECR. In both cases,
# it uploads the image as a build artifact for other jobs to download and use.
acquire-base-image:
name: Acquire Base Image
if: ${{ github.event.pull_request.head.repo.full_name == 'awslabs/smithy-rs' }}
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v3
with:
Expand All @@ -28,27 +35,33 @@ jobs:
id: acquire
env:
DOCKER_BUILDKIT: 1
run: ./smithy-rs/tools/ci-build/acquire-build-image
- name: Upload base image
uses: actions/upload-artifact@v3
run: ./smithy-rs/.github/scripts/acquire-build-image
- name: Acquire credentials
uses: aws-actions/configure-aws-credentials@v1-node16
with:
name: smithy-rs-base-image
path: smithy-rs-base-image
retention-days: 1
role-to-assume: ${{ secrets.SMITHY_RS_PUBLIC_ECR_PUSH_ROLE_ARN }}
role-session-name: GitHubActions
aws-region: us-west-2
- name: Upload image
run: |
IMAGE_TAG="$(./smithy-rs/.github/scripts/docker-image-hash)"
docker tag "smithy-rs-base-image:${IMAGE_TAG}" "${{ env.ecr_repository }}:${IMAGE_TAG}"
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws
docker push "${{ env.ecr_repository }}:${IMAGE_TAG}"

# Run shared CI after the Docker build image has either been rebuilt or found in ECR
ci:
needs: acquire-base-image
if: ${{ github.event.pull_request.head.repo.full_name == 'awslabs/smithy-rs' }}
uses: ./.github/workflows/ci.yml
with:
run_sdk_examples: true

# The PR bot requires a Docker build image, so make it depend on the `acquire-base-image` job.
pr_bot:
name: PR Bot
if: ${{ github.event.pull_request.head.repo.full_name == 'awslabs/smithy-rs' }}
needs: acquire-base-image
# Only run this job on pull requests (not directly on main)
if: ${{ github.head_ref }}
uses: ./.github/workflows/pull-request-bot.yml
with:
issue_number: ${{ github.event.number }}
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
strategy:
fail-fast: false
matrix:
# These correspond to scripts in tools/ci-build/scripts that will be run in the Docker build image
# These correspond to scripts in tools/ci-scripts that will be run in the Docker build image
actions:
- action: generate-aws-sdk
- action: generate-aws-sdk-smoketest
Expand Down Expand Up @@ -64,7 +64,7 @@ jobs:
strategy:
fail-fast: false
matrix:
# These correspond to scripts in tools/ci-build/scripts that will be run in the Docker build image
# These correspond to scripts in tools/ci-scripts that will be run in the Docker build image
test:
- action: check-aws-sdk-adhoc-tests
- action: check-client-codegen-integration-tests
Expand Down Expand Up @@ -100,7 +100,7 @@ jobs:
strategy:
fail-fast: false
matrix:
# These correspond to scripts in tools/ci-build/scripts that will be run in the Docker build image
# These correspond to scripts in tools/ci-scripts that will be run in the Docker build image
test:
- action: check-aws-config
- action: check-aws-sdk-canary
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/claim-crate-names.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
fetch-depth: 0
- name: Acquire base image
id: acquire
run: ./smithy-rs/tools/ci-build/acquire-build-image
run: ./smithy-rs/.github/scripts/acquire-build-image
- name: Upload base image
uses: actions/upload-artifact@v3
with:
Expand All @@ -72,7 +72,7 @@ jobs:
RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN: ${{ secrets.RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN }}
run: |
cargo login -- "${RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN}"
cargo install --path tools/publisher
cargo install --path tools/ci-build/publisher
# Verify the publisher tool installed successfully
publisher --version
publisher claim-crate-names -y
2 changes: 1 addition & 1 deletion .github/workflows/manual-pull-request-bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
fetch-depth: 0
- name: Acquire base image
id: acquire
run: ./smithy-rs/tools/ci-build/acquire-build-image
run: ./smithy-rs/.github/scripts/acquire-build-image
- name: Upload base image
uses: actions/upload-artifact@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pull-request-bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ jobs:

cargo doc --no-deps --all-features
popd
./tools/generate-doc-preview-index.sh ${{ inputs.base_revision }}
./tools/ci-scripts/generate-doc-preview-index.sh ${{ inputs.base_revision }}

echo 'bot-message=A [new doc preview](https://d2luzm2xt3nokh.cloudfront.net/docs/'${{ inputs.head_revision }}'/index.html) is ready to view.' >> "${GITHUB_OUTPUT}"
- uses: aws-actions/configure-aws-credentials@v1-node16
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
fetch-depth: 0
- name: Acquire base image
id: acquire
run: ./smithy-rs/tools/ci-build/acquire-build-image
run: ./smithy-rs/.github/scripts/acquire-build-image
- name: Upload base image
uses: actions/upload-artifact@v3
with:
Expand Down Expand Up @@ -118,7 +118,7 @@ jobs:
RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN: ${{ secrets.RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN }}
run: |
cargo login -- "${RELEASE_AUTOMATION_BOT_CRATESIO_TOKEN}"
cargo install --path "$(realpath ../smithy-rs/tools/publisher)"
cargo install --path "$(realpath ../smithy-rs/tools/ci-build/publisher)"
# Verify the publisher tool installed successfully
publisher --version

Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-hooks/license-header.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ set -e
# SPDX-License-Identifier: Apache-2.0
#

cd "$(git rev-parse --show-toplevel)/tools/sdk-lints" && cargo run -- check --license --changelog
cd "$(git rev-parse --show-toplevel)/tools/ci-build/sdk-lints" && cargo run -- check --license --changelog
6 changes: 3 additions & 3 deletions aws/sdk/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ val smithyVersion: String by project
val defaultRustDocFlags: String by project
val properties = PropertyRetriever(rootProject, project)

val crateHasherToolPath = rootProject.projectDir.resolve("tools/crate-hasher")
val publisherToolPath = rootProject.projectDir.resolve("tools/publisher")
val sdkVersionerToolPath = rootProject.projectDir.resolve("tools/sdk-versioner")
val crateHasherToolPath = rootProject.projectDir.resolve("tools/ci-build/crate-hasher")
val publisherToolPath = rootProject.projectDir.resolve("tools/ci-build/publisher")
val sdkVersionerToolPath = rootProject.projectDir.resolve("tools/ci-build/sdk-versioner")
val outputDir = buildDir.resolve("aws-sdk")
val sdkOutputDir = outputDir.resolve("sdk")
val examplesOutputDir = outputDir.resolve("examples")
Expand Down
8 changes: 2 additions & 6 deletions ci.mk
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#

# This is a makefile executed by the `./ci` script that
# has a target for every single CI script in `tools/ci-build/scripts`,
# has a target for every single CI script in `tools/ci-scripts`,
# with dependencies between targets included so that it's not necessary
# to remember to generate a SDK for the targets that require one.

Expand All @@ -14,7 +14,7 @@ CI_ACTION=$(CI_BUILD)/ci-action

.PHONY: acquire-build-image
acquire-build-image:
$(CI_BUILD)/acquire-build-image
./smithy-rs/.github/scripts/acquire-build-image

.PHONY: check-aws-config
check-aws-config: generate-aws-sdk-smoketest
Expand Down Expand Up @@ -119,7 +119,3 @@ generate-codegen-diff:
.PHONY: generate-smithy-rs-release
generate-smithy-rs-release:
$(CI_ACTION) $@ $(ARGS)

.PHONY: sanity-test
sanity-test:
$(CI_ACTION) $@ $(ARGS)
2 changes: 1 addition & 1 deletion rust-runtime/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ tasks.register("fixRuntimeCrateVersions") {

tasks.register<ExecRustBuildTool>("fixManifests") {
description = "Run the publisher tool's `fix-manifests` sub-command on the runtime crates"
toolPath = rootProject.projectDir.resolve("tools/publisher")
toolPath = rootProject.projectDir.resolve("tools/ci-build/publisher")
binaryName = "publisher"
arguments = listOf("fix-manifests", "--location", runtimeOutputDir.absolutePath)
dependsOn("fixRuntimeCrateVersions")
Expand Down
Loading