diff --git a/.github/workflows/.aspect-workflows-reusable.yaml b/.github/workflows/.aspect-workflows-reusable.yaml new file mode 100644 index 00000000..b3a333f5 --- /dev/null +++ b/.github/workflows/.aspect-workflows-reusable.yaml @@ -0,0 +1,189 @@ +# ================================================================================================== +# Aspect Workflows Reusable Workflow for GitHub Actions (v5.12.0-alpha0.dev.68.g41b1e2f) +# +# https://github.com/marketplace/actions/aspect-workflows?version=5.12.0-alpha0.dev.68.g41b1e2f +# +# At this time, GitHub Actions does not allow referencing reusable workflows from public +# repositories in other organizations. See +# https://docs.github.com/en/actions/using-workflows/reusing-workflows#access-to-reusable-workflows +# for more info. +# +# Use the Aspect Workflows Reusable Workflow with GitHub Actions by doing one of the following: +# +# 1. Vendor this file into the `.github/workflows` folder of your repository and reference it with +# `uses:` in a workflow file such as `.github/workflows/aspect-workflows.yaml`: +# +# ``` +# name: Aspect Workflows +# +# on: +# push: +# branches: [main] +# pull_request: +# branches: [main] +# workflow_dispatch: +# +# jobs: +# aspect-workflows: +# name: Aspect Workflows +# uses: ./.github/workflows/.aspect-workflows-reusable.yaml +# ``` +# +# 2. Create a fork of https://github.com/aspect-build/workflows-action in your +# GitHub org and change the `uses` line above to reference the reusable work +# from your fork: +# +# ``` +# jobs: +# aspect-workflows: +# name: Aspect Workflows +# uses: my-github-org/workflows-action/.github/workflows/.aspect-workflows-reusable.yaml@5.12.0-alpha0.dev.68.g41b1e2f +# ``` +# ================================================================================================== +name: Aspect Workflows Reusable Workflow (v5.12.0-alpha0.dev.68.g41b1e2f) +on: + # Makes this workflow reusable, see + # https://github.blog/2022-02-10-using-reusable-workflows-github-actions + workflow_call: + inputs: + aspect-config: + description: Path to the Aspect Workflows config.yaml file + type: string + default: .aspect/workflows/config.yaml + delivery-workflow: + description: The name of the file which contains the delivery workflow + type: string + default: aspect-workflows-delivery.yaml + queue: + description: The queue / runner pool that the setup step will run on + type: string + default: aspect-default + slack_webhook_url: + description: 'If set, then a webhook notification will be sent for failing builds on a release branch. Input should match the name of a secret. "secrets: inherit" must also be set' + type: string + inherited_secrets: + description: 'Comma separated list of secrets or regex (Oniguruma) describing secrets to be made available during the build. "secrets: inherit" must also be set. The regex is used by jq internally which uses the Oniguruma regular expression library: https://jqlang.github.io/jq/manual/' + type: string +jobs: + setup: + runs-on: [self-hosted, aspect-workflows, "${{ inputs.queue }}"] + steps: + - uses: actions/checkout@v4 + - id: rosetta-generate + run: | + ROSETTA_RESULT=$( \ + rosetta steps \ + --config ${{ inputs.aspect-config }} \ + --gha_task generate \ + --gha_json_pretty_print=false \ + ) + tee "${GITHUB_OUTPUT}" <<< "json=${ROSETTA_RESULT}" + outputs: + cfg: ${{ steps.rosetta-generate.outputs.json }} + bazel: + needs: [setup] + runs-on: ${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].labels }} + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.setup.outputs.cfg).matrix_config }} + env: + ASPECT_WORKFLOWS_CONFIG: ${{ inputs.aspect-config }} + steps: + - name: Workflows environment + run: ${{ fromJson(needs.setup.outputs.cfg).platform.directories.WORKFLOWS_BIN_DIR }}/configure_workflows_env + - name: Clone repo + uses: actions/checkout@v4 + with: + fetch-depth: ${{ !endsWith(matrix.job, 'lint') && 1 || 2 }} + - name: Agent health check + # Set RUNNER_TRACKER_ID="" to prevent GitHub Actions from killing the Bazel server started + # during health check when "Cleaning up orphan processes" in the "Complete job" step. + # See https://github.com/actions/runner/issues/598. + run: RUNNER_TRACKING_ID="" && ${{ fromJson(needs.setup.outputs.cfg).platform.directories.WORKFLOWS_BIN_DIR }}/agent_health_check + timeout-minutes: ${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].health_check_timeout }} + - name: Process secrets + id: process_secrets + if: inputs.inherited_secrets != '' + run: | + REQUIRED_SECRETS=$(${{ fromJson(needs.setup.outputs.cfg).platform.directories.WORKFLOWS_BIN_DIR }}/jq -R --compact-output 'gsub("\\s+";"";"g") | split(",")' <<< "${{ inputs.inherited_secrets }}") + FILTERED_SECRETS=$(${{ fromJson(needs.setup.outputs.cfg).platform.directories.WORKFLOWS_BIN_DIR }}/jq --compact-output --argjson secrets "${REQUIRED_SECRETS}" 'with_entries( select (.key | test($secrets[]) ) )' <<< '''${{ toJson(secrets) }}''' ) + echo "filtered_secrets=${FILTERED_SECRETS}" | tee ${GITHUB_OUTPUT} + - name: Prepare archive directories + run: rm -rf ${{ join(fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].artifact_paths, ' ') }} + - name: Determine changed files + uses: tj-actions/changed-files@v42 + if: endsWith(matrix.job, 'format') + with: + json: true + write_output_files: true + output_dir: ${{ fromJson(needs.setup.outputs.cfg).platform.directories.ARTIFACTS_DIR }} + - name: Checkout health + uses: aspect-build/workflows-action@5.12.0-alpha0.dev.68.g41b1e2f + timeout-minutes: ${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].checkout_task_timeout }} + if: fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].has_checkout_task + with: + workspace: ${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].workspace }} + task: checkout + - name: ${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].name }} + uses: aspect-build/workflows-action@5.12.0-alpha0.dev.68.g41b1e2f + env: ${{ inputs.inherited_secrets != '' && fromJson(steps.process_secrets.outputs.filtered_secrets) || fromJson('{}') }} + timeout-minutes: ${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].timeout_in_minutes }} + with: + workspace: ${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].workspace }} + task: ${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].task }} + - name: Send notification to Slack + id: slack + # oncall cares about branches that do delivery, so key this on whether we produce a delivery manifest + if: inputs.slack_webhook_url != '' && failure() && fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].generate_manifest + uses: slackapi/slack-github-action@v1.27.0 + with: + payload: | + { + "gha_url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets[inputs.slack_webhook_url] }} + - name: Delivery manifest + if: fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].generate_manifest + uses: aspect-build/workflows-action@5.12.0-alpha0.dev.68.g41b1e2f + timeout-minutes: ${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].delivery_manifest_timeout }} + with: + workspace: ${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].workspace }} + task: delivery_manifest + args: "--data TARGETS_SOURCE=${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].task }}" + # Upload all artifacts for the workspace + - name: Upload artifacts + # The `always()` condition makes this step run even if a previous step failed. + # Setting `continue-on-error: true` on previous steps isn't ideal as the UI + # will flag them as having passed even if they failed. + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: ${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].artifact_prefix }}${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].task }}.artifacts + path: ${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].artifact_upload_pattern }} + overwrite: true + # Codecov + - name: Codecov upload + # The `always()` condition makes this step run even if a previous step failed. + # Setting `continue-on-error: true` on previous steps isn't ideal as the UI + # will flag them as having passed even if they failed. + if: ${{ always() && fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].codecov_upload }} + # https://github.com/marketplace/actions/codecov + uses: codecov/codecov-action@v4 + with: + files: bazel-out/_coverage/_coverage_report.dat + token: ${{ secrets.CODECOV_TOKEN }} + functionalities: search # Disable searching for coverage reports. If enabled, it gets confused + # by the bazel convenience symlinks and finds the same coverage report + # under bazel-out and {workspace}/bazel-out. + - name: Trigger delivery + # This uses the following API: https://docs.github.com/en/rest/actions/workflows?apiVersion=2022-11-28#create-a-workflow-dispatch-event + run: | + curl \ + -X POST \ + -H "Accept: application/vnd.github.v3+json" \ + -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + https://api.github.com/repos/${{ github.repository }}/actions/workflows/${{ inputs.delivery-workflow }}/dispatches \ + -d "{\"ref\":\"${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].branch }}\",\"inputs\":{\"delivery_commit\":\"${GITHUB_SHA}\",\"workspace\":\"${{ fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].workspace }}\"}}" + shell: bash + if: fromJson(needs.setup.outputs.cfg).workflows_config[matrix.job].delivery diff --git a/.github/workflows/aspect-workflows-warming.yaml b/.github/workflows/aspect-workflows-warming.yaml new file mode 100644 index 00000000..de767130 --- /dev/null +++ b/.github/workflows/aspect-workflows-warming.yaml @@ -0,0 +1,34 @@ +name: Aspect Workflows Warming + +on: + # Run the workflows on a cron schedule to periodically create an up-to-date warming archive + # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule + schedule: + - cron: '0 8 * * *' + + # Allow this to be triggered manually via the GitHub UI Actions tab + workflow_dispatch: + +jobs: + warming-archive: + name: Aspect Workflows Warming + runs-on: [self-hosted, aspect-workflows, aspect-warming] + env: + ASPECT_WORKFLOWS_BIN_DIR: /etc/aspect/workflows/bin + steps: + - name: Workflows environment + run: ${ASPECT_WORKFLOWS_BIN_DIR}/configure_workflows_env + - uses: actions/checkout@v4 + with: + ref: main-gha + - name: Agent health check + # Set RUNNER_TRACKER_ID="" to prevent GitHub Actions from killing the Bazel server started + # during health check when "Cleaning up orphan processes" in the "Complete job" step. + # See https://github.com/actions/runner/issues/598. + run: RUNNER_TRACKER_ID="" && ${ASPECT_WORKFLOWS_BIN_DIR}/agent_health_check + - name: Create warming archive + uses: aspect-build/workflows-action@5.12.0-alpha0.dev.68.g41b1e2f + with: + task: warming + - name: Archive warming tars + run: ${ASPECT_WORKFLOWS_BIN_DIR}/warming_archive diff --git a/.github/workflows/aspect-workflows.yaml b/.github/workflows/aspect-workflows.yaml new file mode 100644 index 00000000..f8b68f59 --- /dev/null +++ b/.github/workflows/aspect-workflows.yaml @@ -0,0 +1,24 @@ +name: Aspect Workflows + +on: + # Triggers the workflow on pull request events and on main + push: + branches: [main-gha] + pull_request: + branches: [main-gha] + + # Allow this to be triggered manually via the GitHub UI Actions tab + workflow_dispatch: + +concurrency: + # Cancel previous actions from the same PR or branch except 'main' branch. + # See https://docs.github.com/en/actions/using-jobs/using-concurrency and https://docs.github.com/en/actions/learn-github-actions/contexts for more info. + group: concurrency-group::${{ github.workflow }}::${{ github.event.pull_request.number > 0 && format('pr-{0}', github.event.pull_request.number) || github.ref_name }}${{ github.ref_name == 'main' && format('::{0}', github.run_id) || ''}} + cancel-in-progress: ${{ github.ref_name != 'main' }} + +jobs: + aspect-workflows: + name: Aspect Workflows + uses: ./.github/workflows/.aspect-workflows-reusable.yaml + with: + queue: aspect-small