Build And Upload Distributor #4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build And Upload Distributor | |
| env: | |
| CWA_GITHUB_TEST_REPO_NAME: "aws/amazon-cloudwatch-agent-test" | |
| CWA_GITHUB_TEST_REPO_BRANCH: "fix/msiexec-hang-qn-norestart" | |
| CHECKOUT_ROOT_DIR: "test" | |
| SSM_DISTRIBUTOR_VERSION_LIMIT: 25 | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| BucketKey: | |
| # e.g. s3://<bucket>/integration-test/binary/<SHA>" | |
| # e.g. s3://<bucket>/nonprod | |
| # e.g. s3://<bucket>/release | |
| description: "S3 URI to upload artifacts into." | |
| required: true | |
| type: string | |
| PackageBucketKey: | |
| description: "Integration tests put the MSI and PKG in a different bucket path than the binaries." | |
| required: true | |
| type: string | |
| Region: | |
| description: "Region to upload binaries" | |
| required: false | |
| type: string | |
| default: "us-west-2" | |
| TerraformAWSAssumeRole: | |
| description: "Role to assume to upload artifacts" | |
| required: true | |
| type: string | |
| Bucket: | |
| description: "Bucket to upload the artifacts to" | |
| required: true | |
| type: string | |
| DistributorName: | |
| description: "SSM Distributor document name" | |
| required: true | |
| type: string | |
| workflow_call: | |
| inputs: | |
| BucketKey: | |
| # e.g. s3://<bucket>/integration-test/binary/<SHA>" | |
| # e.g. s3://<bucket>/nonprod | |
| # e.g. s3://<bucket>/release | |
| description: "S3 URI to upload artifacts into." | |
| required: true | |
| type: string | |
| PackageBucketKey: | |
| description: "Integration tests put the MSI and PKG in a different bucket path than the binaries." | |
| required: true | |
| type: string | |
| Region: | |
| description: "Region to upload binaries" | |
| required: false | |
| type: string | |
| default: "us-west-2" | |
| TerraformAWSAssumeRole: | |
| description: "Role to assume to upload artifacts" | |
| required: true | |
| type: string | |
| Bucket: | |
| description: "Bucket to upload the artifacts to" | |
| required: true | |
| type: string | |
| DistributorName: | |
| description: "SSM Distributor document name" | |
| required: true | |
| type: string | |
| jobs: | |
| AgentVersion: | |
| name: 'AgentVersion' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| id-token: write | |
| contents: read | |
| outputs: | |
| agent-version: ${{ steps.version.outputs.version }} | |
| should-build: ${{ steps.check.outputs.should-build }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: Configure AWS Credentials | |
| uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 | |
| with: | |
| role-to-assume: ${{ inputs.TerraformAWSAssumeRole }} | |
| aws-region: ${{ inputs.Region }} | |
| - name: Free up disk space | |
| run: .github/scripts/free-disk-space.sh | |
| - name: Agent Version | |
| id: version | |
| env: | |
| INPUT_BUCKET: ${{ inputs.Bucket }} | |
| INPUT_BUCKET_KEY: ${{ inputs.BucketKey }} | |
| run: | | |
| aws s3 cp "s3://$INPUT_BUCKET/$INPUT_BUCKET_KEY/CWAGENT_VERSION" . | |
| echo "version=$(cat CWAGENT_VERSION)" >> "$GITHUB_OUTPUT" | |
| - name: Check if SSM distributor version already exists | |
| id: check | |
| env: | |
| INPUT_DISTRIBUTOR_NAME: ${{ inputs.DistributorName }} | |
| INPUT_REGION: ${{ inputs.Region }} | |
| AGENT_VERSION: ${{ steps.version.outputs.version }} | |
| run: | | |
| VERSION_EXISTS=$(aws ssm list-document-versions \ | |
| --name "$INPUT_DISTRIBUTOR_NAME" \ | |
| --region "$INPUT_REGION" \ | |
| --no-paginate \ | |
| --query "DocumentVersions[?VersionName=='$AGENT_VERSION']" \ | |
| --output text 2>/dev/null) | |
| if [ -n "$VERSION_EXISTS" ]; then | |
| echo "should-build=false" >> "$GITHUB_OUTPUT" | |
| echo "Version $AGENT_VERSION already exists, skipping build" | |
| else | |
| echo "should-build=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| PackageLinux: | |
| name: 'PackageLinux' | |
| runs-on: ubuntu-latest | |
| needs: [AgentVersion] | |
| if: needs.AgentVersion.outputs.should-build == 'true' | |
| permissions: | |
| id-token: write | |
| contents: read | |
| strategy: | |
| matrix: | |
| arch: [amd64, arm64] | |
| env: | |
| SOURCE_S3_PATH: s3://${{ inputs.Bucket }}/${{ inputs.BucketKey }}/linux/${{ matrix.arch }} | |
| DESTINATION_S3_PATH: s3://${{ inputs.Bucket }}/${{ inputs.PackageBucketKey }}/linux/${{ matrix.arch }}/${{ needs.AgentVersion.outputs.agent-version }} | |
| WORKING_DIRECTORY: distributor/linux/${{ matrix.arch }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| repository: ${{env.CWA_GITHUB_TEST_REPO_NAME}} | |
| ref: ${{ env.CWA_GITHUB_TEST_REPO_BRANCH }} | |
| path: ${{ env.CHECKOUT_ROOT_DIR }} | |
| - name: Configure AWS Credentials | |
| uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 | |
| with: | |
| role-to-assume: ${{ inputs.TerraformAWSAssumeRole }} | |
| aws-region: ${{ inputs.Region }} | |
| - name: Prepare Linux package | |
| run: | | |
| mkdir -p "$WORKING_DIRECTORY" | |
| aws s3 cp "$SOURCE_S3_PATH/amazon-cloudwatch-agent.rpm" "$WORKING_DIRECTORY/" | |
| aws s3 cp "$SOURCE_S3_PATH/amazon-cloudwatch-agent.deb" "$WORKING_DIRECTORY/" | |
| cp "${{ env.CHECKOUT_ROOT_DIR }}/packaging/linux/install.sh" "$WORKING_DIRECTORY/" | |
| cp "${{ env.CHECKOUT_ROOT_DIR }}/packaging/linux/uninstall.sh" "$WORKING_DIRECTORY/" | |
| cp "${{ env.CHECKOUT_ROOT_DIR }}/packaging/linux/detect-system.sh" "$WORKING_DIRECTORY/" | |
| - name: Create manifest JSON | |
| env: | |
| INPUT_DISTRIBUTOR_NAME: ${{ inputs.DistributorName }} | |
| MATRIX_ARCH: ${{ matrix.arch }} | |
| AGENT_VERSION: ${{ needs.AgentVersion.outputs.agent-version }} | |
| run: | | |
| cat > "$WORKING_DIRECTORY/manifest.json" << EOF | |
| { | |
| "name": "$INPUT_DISTRIBUTOR_NAME", | |
| "platform": "linux", | |
| "architecture": "$MATRIX_ARCH", | |
| "version": "$AGENT_VERSION" | |
| } | |
| EOF | |
| - name: Zip | |
| run: zip -j AmazonCloudWatchAgent.zip "$WORKING_DIRECTORY"/* | |
| - name: Upload zip | |
| run: aws s3 cp AmazonCloudWatchAgent.zip "$DESTINATION_S3_PATH/AmazonCloudWatchAgent.zip" | |
| - name: Calculate checksum | |
| run: echo "$(sha256sum AmazonCloudWatchAgent.zip | cut -d' ' -f1)" > checksum.txt | |
| - name: Upload checksum | |
| run: aws s3 cp checksum.txt "$DESTINATION_S3_PATH/checksum.txt" | |
| PackageDarwin: | |
| name: 'PackageDarwin' | |
| runs-on: ubuntu-latest | |
| needs: [AgentVersion] | |
| if: needs.AgentVersion.outputs.should-build == 'true' | |
| permissions: | |
| id-token: write | |
| contents: read | |
| strategy: | |
| matrix: | |
| arch: [amd64, arm64] | |
| env: | |
| SOURCE_S3_PATH: s3://${{ inputs.Bucket }}/${{ inputs.PackageBucketKey }}/${{ matrix.arch }} | |
| DESTINATION_S3_PATH: s3://${{ inputs.Bucket }}/${{ inputs.PackageBucketKey }}/darwin/${{ matrix.arch }}/${{ needs.AgentVersion.outputs.agent-version }} | |
| WORKING_DIRECTORY: distributor/darwin/${{ matrix.arch }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| repository: ${{env.CWA_GITHUB_TEST_REPO_NAME}} | |
| ref: ${{ env.CWA_GITHUB_TEST_REPO_BRANCH }} | |
| path: ${{ env.CHECKOUT_ROOT_DIR }} | |
| - name: Configure AWS Credentials | |
| uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 | |
| with: | |
| role-to-assume: ${{ inputs.TerraformAWSAssumeRole }} | |
| aws-region: ${{ inputs.Region }} | |
| - name: Prepare macOS package | |
| run: | | |
| mkdir -p "$WORKING_DIRECTORY" | |
| aws s3 cp "$SOURCE_S3_PATH/amazon-cloudwatch-agent.pkg" "$WORKING_DIRECTORY/" | |
| cp "${{ env.CHECKOUT_ROOT_DIR }}/packaging/darwin/install.sh" "$WORKING_DIRECTORY/" | |
| cp "${{ env.CHECKOUT_ROOT_DIR }}/packaging/darwin/uninstall.sh" "$WORKING_DIRECTORY/" | |
| - name: Create manifest JSON | |
| env: | |
| INPUT_DISTRIBUTOR_NAME: ${{ inputs.DistributorName }} | |
| MATRIX_ARCH: ${{ matrix.arch }} | |
| AGENT_VERSION: ${{ needs.AgentVersion.outputs.agent-version }} | |
| run: | | |
| cat > "$WORKING_DIRECTORY/manifest.json" << EOF | |
| { | |
| "name": "$INPUT_DISTRIBUTOR_NAME", | |
| "platform": "mac_os_x", | |
| "architecture": "$MATRIX_ARCH", | |
| "version": "$AGENT_VERSION" | |
| } | |
| EOF | |
| - name: Zip | |
| run: zip -j AmazonCloudWatchAgent.zip "$WORKING_DIRECTORY"/* | |
| - name: Upload zip | |
| run: aws s3 cp AmazonCloudWatchAgent.zip "$DESTINATION_S3_PATH/AmazonCloudWatchAgent.zip" | |
| - name: Calculate checksum | |
| run: echo "$(sha256sum AmazonCloudWatchAgent.zip | cut -d' ' -f1)" > checksum.txt | |
| - name: Upload checksum | |
| run: aws s3 cp checksum.txt "$DESTINATION_S3_PATH/checksum.txt" | |
| PackageWindows: | |
| name: 'PackageWindows' | |
| runs-on: ubuntu-latest | |
| needs: [AgentVersion] | |
| if: needs.AgentVersion.outputs.should-build == 'true' | |
| permissions: | |
| id-token: write | |
| contents: read | |
| env: | |
| SOURCE_S3_PATH: s3://${{ inputs.Bucket }}/${{ inputs.PackageBucketKey }} | |
| DESTINATION_S3_PATH: s3://${{ inputs.Bucket }}/${{ inputs.PackageBucketKey }}/windows/amd64/${{ needs.AgentVersion.outputs.agent-version }} | |
| WORKING_DIRECTORY: distributor/windows/amd64 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| repository: ${{env.CWA_GITHUB_TEST_REPO_NAME}} | |
| ref: ${{ env.CWA_GITHUB_TEST_REPO_BRANCH }} | |
| path: ${{ env.CHECKOUT_ROOT_DIR }} | |
| - name: Configure AWS Credentials | |
| uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 | |
| with: | |
| role-to-assume: ${{ inputs.TerraformAWSAssumeRole }} | |
| aws-region: ${{ inputs.Region }} | |
| - name: Prepare Windows package | |
| run: | | |
| mkdir -p "$WORKING_DIRECTORY" | |
| aws s3 cp "$SOURCE_S3_PATH/amazon-cloudwatch-agent.msi" "$WORKING_DIRECTORY/" | |
| cp "${{ env.CHECKOUT_ROOT_DIR }}/packaging/windows/install.ps1" "$WORKING_DIRECTORY/" | |
| cp "${{ env.CHECKOUT_ROOT_DIR }}/packaging/windows/uninstall.ps1" "$WORKING_DIRECTORY/" | |
| - name: Create manifest JSON | |
| env: | |
| INPUT_DISTRIBUTOR_NAME: ${{ inputs.DistributorName }} | |
| AGENT_VERSION: ${{ needs.AgentVersion.outputs.agent-version }} | |
| run: | | |
| cat > "$WORKING_DIRECTORY/manifest.json" << EOF | |
| { | |
| "name": "$INPUT_DISTRIBUTOR_NAME", | |
| "platform": "windows", | |
| "architecture": "amd64", | |
| "version": "$AGENT_VERSION" | |
| } | |
| EOF | |
| - name: Zip | |
| run: zip -j AmazonCloudWatchAgent.zip "$WORKING_DIRECTORY"/* | |
| - name: Upload zip | |
| run: aws s3 cp AmazonCloudWatchAgent.zip "$DESTINATION_S3_PATH/AmazonCloudWatchAgent.zip" | |
| - name: Calculate checksum | |
| run: echo "$(sha256sum AmazonCloudWatchAgent.zip | cut -d' ' -f1)" > checksum.txt | |
| - name: Upload checksum | |
| run: aws s3 cp checksum.txt "$DESTINATION_S3_PATH/checksum.txt" | |
| UploadDistributor: | |
| name: 'UploadDistributor' | |
| runs-on: ubuntu-latest | |
| needs: [AgentVersion, PackageLinux, PackageDarwin, PackageWindows] | |
| if: needs.AgentVersion.outputs.should-build == 'true' | |
| permissions: | |
| id-token: write | |
| contents: read | |
| env: | |
| AGENT_VERSION: ${{ needs.AgentVersion.outputs.agent-version }} | |
| S3_PATH: s3://${{ inputs.Bucket }}/${{ inputs.PackageBucketKey }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| repository: ${{env.CWA_GITHUB_TEST_REPO_NAME}} | |
| ref: ${{ env.CWA_GITHUB_TEST_REPO_BRANCH }} | |
| path: ${{ env.CHECKOUT_ROOT_DIR }} | |
| - name: Configure AWS Credentials | |
| uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 | |
| with: | |
| role-to-assume: ${{ inputs.TerraformAWSAssumeRole }} | |
| aws-region: ${{ inputs.Region }} | |
| - name: Download checksums | |
| run: | | |
| mkdir -p checksum/{windows/amd64,linux/{amd64,arm64},darwin/{amd64,arm64}} | |
| aws s3 cp "$S3_PATH/windows/amd64/$AGENT_VERSION/checksum.txt" checksum/windows/amd64/ | |
| aws s3 cp "$S3_PATH/linux/amd64/$AGENT_VERSION/checksum.txt" checksum/linux/amd64/ | |
| aws s3 cp "$S3_PATH/linux/arm64/$AGENT_VERSION/checksum.txt" checksum/linux/arm64/ | |
| aws s3 cp "$S3_PATH/darwin/amd64/$AGENT_VERSION/checksum.txt" checksum/darwin/amd64/ | |
| aws s3 cp "$S3_PATH/darwin/arm64/$AGENT_VERSION/checksum.txt" checksum/darwin/arm64/ | |
| - name: Create manifest JSON | |
| run: | | |
| export WINDOWS_AMD64_SHA=$(cat checksum/windows/amd64/checksum.txt) | |
| export LINUX_AMD64_SHA=$(cat checksum/linux/amd64/checksum.txt) | |
| export LINUX_ARM64_SHA=$(cat checksum/linux/arm64/checksum.txt) | |
| export DARWIN_AMD64_SHA=$(cat checksum/darwin/amd64/checksum.txt) | |
| export DARWIN_ARM64_SHA=$(cat checksum/darwin/arm64/checksum.txt) | |
| envsubst < "${{ env.CHECKOUT_ROOT_DIR }}/packaging/manifest.json" > manifest.json | |
| - name: Upload manifest JSON to S3 | |
| run: aws s3 cp manifest.json "$S3_PATH/manifest.json" | |
| - name: Check if distributor exists | |
| id: check-distributor | |
| env: | |
| INPUT_DISTRIBUTOR_NAME: ${{ inputs.DistributorName }} | |
| INPUT_REGION: ${{ inputs.Region }} | |
| run: | | |
| if aws ssm describe-document --name "$INPUT_DISTRIBUTOR_NAME" --region "$INPUT_REGION" 2>/dev/null; then | |
| echo "exists=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "exists=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Create distributor | |
| if: steps.check-distributor.outputs.exists == 'false' | |
| env: | |
| INPUT_DISTRIBUTOR_NAME: ${{ inputs.DistributorName }} | |
| INPUT_REGION: ${{ inputs.Region }} | |
| AGENT_VERSION: ${{ needs.AgentVersion.outputs.agent-version }} | |
| run: | | |
| aws ssm create-document \ | |
| --name "$INPUT_DISTRIBUTOR_NAME" \ | |
| --content file://manifest.json \ | |
| --attachments Key="SourceUrl",Values="$S3_PATH" \ | |
| --version-name "$AGENT_VERSION" \ | |
| --document-type Package \ | |
| --region "$INPUT_REGION" | |
| - name: Remove oldest if limit hit | |
| if: steps.check-distributor.outputs.exists == 'true' | |
| env: | |
| INPUT_DISTRIBUTOR_NAME: ${{ inputs.DistributorName }} | |
| INPUT_REGION: ${{ inputs.Region }} | |
| run: | | |
| VERSION_COUNT=$(aws ssm list-document-versions --name "$INPUT_DISTRIBUTOR_NAME" --region "$INPUT_REGION" --no-paginate --query 'length(DocumentVersions)' --output text) | |
| if [ "$VERSION_COUNT" -ge "${{ env.SSM_DISTRIBUTOR_VERSION_LIMIT }}" ]; then | |
| OLDEST_VERSION=$(aws ssm list-document-versions --name "$INPUT_DISTRIBUTOR_NAME" --region "$INPUT_REGION" --no-paginate --query 'DocumentVersions[-1].DocumentVersion' --output text) | |
| echo "Deleting oldest version: $OLDEST_VERSION" | |
| aws ssm delete-document --name "$INPUT_DISTRIBUTOR_NAME" --document-version "$OLDEST_VERSION" --region "$INPUT_REGION" | |
| fi | |
| - name: Update distributor | |
| if: steps.check-distributor.outputs.exists == 'true' | |
| env: | |
| INPUT_DISTRIBUTOR_NAME: ${{ inputs.DistributorName }} | |
| INPUT_REGION: ${{ inputs.Region }} | |
| AGENT_VERSION: ${{ needs.AgentVersion.outputs.agent-version }} | |
| run: | | |
| aws ssm update-document \ | |
| --name "$INPUT_DISTRIBUTOR_NAME" \ | |
| --content file://manifest.json \ | |
| --attachments Key="SourceUrl",Values="$S3_PATH" \ | |
| --version-name "$AGENT_VERSION" \ | |
| --document-version "\$LATEST" \ | |
| --region "$INPUT_REGION" | |
| - name: Verify distributor | |
| uses: nick-fields/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2.9.0 | |
| env: | |
| INPUT_DISTRIBUTOR_NAME: ${{ inputs.DistributorName }} | |
| INPUT_REGION: ${{ inputs.Region }} | |
| with: | |
| max_attempts: 6 | |
| timeout_minutes: 5 | |
| retry_wait_seconds: 10 | |
| command: | | |
| STATUS=$(aws ssm describe-document --name "$INPUT_DISTRIBUTOR_NAME" --region "$INPUT_REGION" --query 'Document.Status' --output text) | |
| if [ "$STATUS" != "Active" ]; then | |
| echo "Error: Document status is $STATUS, expected Active" | |
| exit 1 | |
| fi | |
| echo "Document is Active" | |
| - name: Update default version | |
| env: | |
| INPUT_DISTRIBUTOR_NAME: ${{ inputs.DistributorName }} | |
| INPUT_REGION: ${{ inputs.Region }} | |
| run: | | |
| CURRENT_DEFAULT=$(aws ssm describe-document --name "$INPUT_DISTRIBUTOR_NAME" --region "$INPUT_REGION" --query 'Document.DefaultVersion' --output text) | |
| LATEST_VERSION=$(aws ssm describe-document --name "$INPUT_DISTRIBUTOR_NAME" --region "$INPUT_REGION" --query 'Document.LatestVersion' --output text) | |
| if [ "$CURRENT_DEFAULT" != "$LATEST_VERSION" ]; then | |
| aws ssm update-document-default-version \ | |
| --name "$INPUT_DISTRIBUTOR_NAME" \ | |
| --document-version "$LATEST_VERSION" \ | |
| --region "$INPUT_REGION" | |
| else | |
| echo "Default version already matches latest version" | |
| fi |