diff --git a/.github/workflows/initiaterelease.yml b/.github/workflows/initiaterelease.yml new file mode 100644 index 000000000..90401249f --- /dev/null +++ b/.github/workflows/initiaterelease.yml @@ -0,0 +1,91 @@ +name: InitiateRelease + +# TODO: We will be changing this to run on a regular scheduled interval once all of the infrastructure has been set up. +on: + workflow_dispatch: + +jobs: + GenerateConfig: + runs-on: ubuntu-latest + outputs: + stage_exit_code: ${{ steps.stage.outputs.stage_exit_code }} + push_exit_code: ${{ steps.push.outputs.push_exit_code }} + pr_exit_code: ${{ steps.pr.outputs.pr_exit_code }} + permissions: + id-token: write + contents: write + pull-requests: write + env: + GH_TOKEN: ${{ github.token }} + steps: + - name: Checkout + uses: actions/checkout@v5 + - name: Create Release Branch + run: | + date=$(date '+%Y%m%d') + git checkout -b release-${date} + - name: Configure Bot Alias + run: | + git config --global user.name "GenerateConfig Action" + git config --global user.email "gcabot@github.com" + - name: Check Update + run: ./scripts/check-update.sh + - name: Check for changes + id: stage + run: | + # Git diff returns exit code of 1 when there is a change staged + # We need the set statements to prevent erroring out + set +e + git diff --cached --quiet + if [[ $? -ne 0 ]]; then echo "stage_exit_code=42" >> "$GITHUB_OUTPUT"; else echo "stage_exit_code=0" >> "$GITHUB_OUTPUT"; fi + set -e + - name: Commit and Push Changes + id: push + if: ${{ steps.stage.outputs.stage_exit_code == 42 }} + run: | + date=$(date '+%Y%m%d') + git commit -m "Release ${date}" + git status + git push --set-upstream origin release-${date} + echo "push_exit_code=$?" >> "$GITHUB_OUTPUT" + - name: Open PR for Branch + id: pr + if: ${{ steps.stage.outputs.stage_exit_code == 42 && steps.push.outputs.push_exit_code == 0 }} + run: | + date=$(date '+%Y%m%d') + gh pr create --base mainline --head release-${date} --title "Release ${date}" --body "Dummy Release PR" + echo "pr_exit_code=$?" >> "$GITHUB_OUTPUT" + MetricPublish: + needs: GenerateConfig + if: success() || failure() + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + steps: + - name: Checkout + uses: actions/checkout@v5 + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v5 + with: + # TODO: Add the role as a secret once infrastructure has been set up. + role-to-assume: ${{ secrets.CW_METRIC_ROLE }} + aws-region: us-west-2 + - name: Failure Scenario + if: ${{ needs.GenerateConfig.result == 'failure' }} + run: | + # TODO: Cloudwatch metric namespace will need to be created + echo "ERROR: Encounter error when checking for new release." + aws cloudwatch put-metric-data --metric-name FluentBitGithubActionFailure --namespace FluentBitRelease --value "-1" + - name: Release Kickoff Scenario + if: ${{ needs.GenerateConfig.outputs.stage_exit_code == 42 }} + run: | + # TODO: Cloudwatch metric namespace will need to be created + echo "Kicking off new release." + aws cloudwatch put-metric-data --metric-name FluentBitGithubActionKickoff --namespace FluentBitRelease --value 1 + - name: No Release Scenario + if: ${{ needs.GenerateConfig.outputs.stage_exit_code == 0 }} + run: | + # TODO: Cloudwatch metric namespace will need to be created + echo "No new release needed at this time." + aws cloudwatch put-metric-data --metric-name FluentBitGithubActionKickoff --namespace FluentBitRelease --value 0 diff --git a/.github/workflows/postkickoff.yml b/.github/workflows/postkickoff.yml new file mode 100644 index 000000000..1a1d57d62 --- /dev/null +++ b/.github/workflows/postkickoff.yml @@ -0,0 +1,27 @@ +name: Post-release merge action +run-name: Post-release merge action + +on: + pull_request: + types: [closed] + branches: [mainline] + +jobs: + ResetReleaseMetric: + if: github.event.pull_request.merged == true && startsWith(github.head_ref, 'release-') + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + steps: + - uses: actions/checkout@v5 + - name: Run on merged PR + run: echo "PR merged from ${{ github.head_ref }} to ${{ github.base_ref }}" + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v5 + with: + # TODO: Add the role as a secret once infrastructure has been set up. + role-to-assume: ${{ secrets.CW_METRIC_ROLE }} + aws-region: us-west-2 + - name: Reset release alarm + run: aws cloudwatch put-metric-data --metric-name FluentBitGithubActionKickoff --namespace FluentBitRelease --value 0 diff --git a/linux.version b/linux.version index a28d5f719..6a500010e 100644 --- a/linux.version +++ b/linux.version @@ -3,14 +3,17 @@ "linux": { "major-version": "2", "version": "2.34.1.20251031", + "release-version": "2.34.1.20251031", "latest": "true", "build": "1", "fluent-bit": "1.9.10", + "release-fluent-bit": "1.9.10", "kinesis-plugin": "v1.10.3", "firehose-plugin": "v1.7.2", "cloudwatch-plugin": "v1.9.4", "al-tag": "2", "flb-repository": "https://github.com/amazon-contributing/upstream-to-fluent-bit.git", + "amazon-linux-sha": "", "publish": "true" } }, @@ -18,14 +21,17 @@ "linux": { "major-version": "3", "version": "3.0.0", + "release-version": "3.0.0", "latest": "false", "build": "1", "fluent-bit": "v4.1.1", + "release-fluent-bit": "v4.1.1", "kinesis-plugin": "v1.10.3", "firehose-plugin": "v1.7.2", "cloudwatch-plugin": "v1.9.4", "al-tag": "2023", "flb-repository": "https://github.com/fluent/fluent-bit.git", + "amazon-linux-sha": "", "publish": "false" } } diff --git a/scripts/check-update.sh b/scripts/check-update.sh new file mode 100644 index 000000000..a47e57205 --- /dev/null +++ b/scripts/check-update.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +set -euo pipefail + +readonly VERSION_FILE="linux.version" +readonly ECR_REPO="public.ecr.aws/amazonlinux/amazonlinux" + +# List of docker tags that we want to clean up after +tags_to_cleanup=() + +# Cleanup function that removes the pulled AL docker images +cleanup() { + for i in "${tags_to_cleanup[@]}"; do + docker rmi "${ECR_REPO}:$i" || true + done +} + +# Helper function to update the specific JSON key/field within the release config file +update_json_field() { + local key="$1" field="$2" value="$3" + jq ".[$key].linux.\"$field\" = \"$value\"" "$VERSION_FILE" > tmp.json && mv tmp.json "$VERSION_FILE" +} + +# Function that checks and updates the release config file for any of the following: +# - New Amazon Linux docker image (tracked by image SHA) +# - New upstream Fluentbit version to consumed +# - New AWS Fluentbit version to be released (Updated to pull in any other updates/changes.) +check_and_update() { + local update="false" + + for i in $(jq 'keys[]' "$VERSION_FILE"); do + current_sha=$(jq -r ".[$i].linux.\"amazon-linux-sha\"" "$VERSION_FILE") + tag=$(jq -r ".[$i].linux.\"al-tag\"" "$VERSION_FILE") + + if ! docker pull "${ECR_REPO}:$tag"; then + echo "Warning: Failed to pull ${ECR_REPO}:$tag" >&2 + continue + fi + + tags_to_cleanup+=("$tag") + new_al_sha=$(docker inspect --format='{{index .RepoDigests 0}}' "${ECR_REPO}:$tag") + + if [[ "$new_al_sha" != "$current_sha" ]]; then + echo "New base amazon linux image for $tag. Updating..." + update_json_field "$i" "amazon-linux-sha" "$new_al_sha" + update="true" + fi + + curr_fluentbit_version=$(jq -r ".[$i].linux.\"fluent-bit\"" "$VERSION_FILE") + release_fluentbit_version=$(jq -r ".[$i].linux.\"release-fluent-bit\"" "$VERSION_FILE") + if [[ "$curr_fluentbit_version" != "$release_fluentbit_version" ]]; then + echo "Upgrading to new Fluentbit version." + update_json_field "$i" "fluent-bit" "$release_fluentbit_version" + update="true" + fi + + curr_aws_fb_version=$(jq -r ".[$i].linux.\"version\"" "$VERSION_FILE") + release_aws_fb_version=$(jq -r ".[$i].linux.\"release-version\"" "$VERSION_FILE") + if [[ "$curr_aws_fb_version" != "$release_aws_fb_version" ]]; then + echo "Upgrading to new AWS Fluentbit version." + update_json_field "$i" "version" "$release_aws_fb_version" + update="true" + fi + done + + if [[ "$update" = "true" ]]; then + git add "$VERSION_FILE" + git status + fi +} + +main() { + check_and_update +} + +trap cleanup EXIT + +main "$@"