diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml index a759f43..bd98f76 100644 --- a/.github/workflows/create_release.yml +++ b/.github/workflows/create_release.yml @@ -1,13 +1,12 @@ -# yamllint --format github .github/workflows/create_release.yml --- name: create_release -# We create a release version on a trigger tag, regardless of if the commit is documentation-only. -# -# See https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet -on: +# We create a release version on a trigger tag, regardless of if the commit is +# documentation-only. +on: # yamllint disable-line rule:truthy push: - tags: 'release-[0-9]+.[0-9]+.[0-9]+**' # Ex. release-1.2.3 + tags: # e.g. release-1.2.3 + - 'release-[0-9]+.[0-9]+.[0-9]+**' jobs: create_release: @@ -16,10 +15,10 @@ jobs: - name: Checkout Repository uses: actions/checkout@v4 with: - # Prevent use of implicit GitHub Actions read-only token GITHUB_TOKEN. We don't deploy on - # the tag MAJOR.MINOR.PATCH event, but we still need to deploy the maven-release-plugin master commit. + # Prevent use of implicit GitHub Actions read-only GITHUB_TOKEN + # because maven-release-plugin pushes commits to master. token: ${{ secrets.GH_TOKEN }} - fetch-depth: 1 # only need the HEAD commit as license check isn't run + fetch-depth: 1 # license check is skipped, so we don't need history - name: Setup java uses: actions/setup-java@v4 with: @@ -36,9 +35,9 @@ jobs: # GH_USER= GH_USER: ${{ secrets.GH_USER }} # GH_TOKEN= - # - makes release commits and tags - # - needs repo:status, public_repo - # - referenced in .settings.xml + # * makes release commits and tags + # * needs repo:status, public_repo + # * referenced in .settings.xml GH_TOKEN: ${{ secrets.GH_TOKEN }} run: | # GITHUB_REF will be refs/tags/release-MAJOR.MINOR.PATCH build-bin/git/login_git && diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c556768..64b3959 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -4,13 +4,14 @@ name: deploy # We deploy on master and release versions, regardless of if the commit is # documentation-only or not. -# -# See https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet -on: +on: # yamllint disable-line rule:truthy push: - # Don't deploy tags as they conflict with [maven-release-plugin] prepare release MAJOR.MINOR.PATCH - tags: '' - branches: master + branches: + - master + # Don't deploy tags because the same commit for MAJOR.MINOR.PATCH is also + # on master: Redundant deployment of a release version will fail uploading. + tags-ignore: + - '*' jobs: deploy: @@ -19,10 +20,11 @@ jobs: - name: Checkout Repository uses: actions/checkout@v4 with: - # Prevent use of implicit GitHub Actions read-only token GITHUB_TOKEN. - # We push Javadocs to the gh-pages branch on commit. + # Prevent use of implicit GitHub Actions read-only GITHUB_TOKEN + # because javadoc_to_gh_pages pushes commits to the gh-pages branch. token: ${{ secrets.GH_TOKEN }} - fetch-depth: 0 # allow build-bin/idl_to_gh_pages to get the full history + # allow build-bin/javadoc_to_gh_pages to get the full history + fetch-depth: 0 - name: Setup java uses: actions/setup-java@v4 with: @@ -42,30 +44,30 @@ jobs: # GH_USER= GH_USER: ${{ secrets.GH_USER }} # GH_TOKEN= - # - pushes Docker images to ghcr.io - # - create via https://github.com/settings/tokens - # - needs repo:status, public_repo, write:packages, delete:packages + # * pushes gh-pages during build-bin/javadoc_to_gh_pages + # * pushes Docker images to ghcr.io + # * create via https://github.com/settings/tokens + # * needs repo:status, public_repo, write:packages, delete:packages GH_TOKEN: ${{ secrets.GH_TOKEN }} GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }} # GPG_PASSPHRASE= - # - referenced in .settings.xml + # * referenced in .settings.xml GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} # SONATYPE_USER= - # - deploys snapshots and releases to Sonatype - # - needs access to io.zipkin via https://issues.sonatype.org/browse/OSSRH-16669 - # - generate via https://oss.sonatype.org/#profile;User%20Token - # - referenced in .settings.xml + # * deploys snapshots and releases to Sonatype + # * needs access to io.zipkin via OSSRH-16669 + # * generate via https://oss.sonatype.org/#profile;User%20Token + # * referenced in .settings.xml SONATYPE_USER: ${{ secrets.SONATYPE_USER }} # SONATYPE_PASSWORD= - # - referenced in .settings.xml + # * referenced in .settings.xml SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} # DOCKERHUB_USER= - # - only push top-level projects: zipkin zipkin-aws zipkin-dependencies zipkin-gcp to Docker Hub, only on release - # - login like this: echo "$DOCKERHUB_TOKEN"| docker login -u "$DOCKERHUB_USER" --password-stdin + # * only push repos in openzipkin org to Docker Hub on release DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }} # DOCKERHUB_TOKEN= - # - Access Token from here https://hub.docker.com/settings/security + # * Access Token from here https://hub.docker.com/settings/security DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - run: | # GITHUB_REF will be refs/heads/master or refs/tags/MAJOR.MINOR.PATCH + run: | # GITHUB_REF = refs/heads/master or refs/tags/MAJOR.MINOR.PATCH build-bin/configure_deploy && build-bin/deploy $(echo ${GITHUB_REF} | cut -d/ -f 3) diff --git a/.github/workflows/docker_push.yml b/.github/workflows/docker_push.yml index 14dd23c..30966d5 100644 --- a/.github/workflows/docker_push.yml +++ b/.github/workflows/docker_push.yml @@ -1,13 +1,12 @@ -# yamllint --format github .github/workflows/docker_push.yml --- name: docker_push -# We re-push docker images on a trigger tag, regardless of if the commit is documentation-only. -# -# See https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet -on: +# We re-push docker on a trigger tag, regardless of if the commit is +# documentation-only. +on: # yamllint disable-line rule:truthy push: - tags: 'docker-[0-9]+.[0-9]+.[0-9]+**' # Ex. docker-1.2.3 + tags: # e.g. release-1.2.3 + - 'release-[0-9]+.[0-9]+.[0-9]+**' jobs: docker_push: @@ -21,7 +20,7 @@ jobs: # via forks, and login session ends up in ~/.docker. This is ok because # we publish DOCKER_PARENT_IMAGE to ghcr.io, hence local to the runner. - name: Docker Push - run: | # GITHUB_REF will be refs/tags/docker-MAJOR.MINOR.PATCH + run: | # GITHUB_REF = refs/tags/docker-MAJOR.MINOR.PATCH build-bin/git/login_git && build-bin/docker/configure_docker_push && build-bin/docker_push $(echo ${GITHUB_REF} | cut -d/ -f 3) @@ -29,14 +28,13 @@ jobs: # GH_USER= GH_USER: ${{ secrets.GH_USER }} # GH_TOKEN= - # - pushes Docker images to ghcr.io - # - create via https://github.com/settings/tokens - # - needs repo:status, public_repo, write:packages, delete:packages + # * pushes Docker images to ghcr.io + # * create via https://github.com/settings/tokens + # * needs repo:status, public_repo, write:packages, delete:packages GH_TOKEN: ${{ secrets.GH_TOKEN }} # DOCKERHUB_USER= - # - only push top-level projects: zipkin zipkin-aws zipkin-dependencies zipkin-gcp to Docker Hub, only on release - # - login like this: echo "$DOCKERHUB_TOKEN"| docker login -u "$DOCKERHUB_USER" --password-stdin + # * only push repos in openzipkin org to Docker Hub on release DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }} # DOCKERHUB_TOKEN= - # - Access Token from here https://hub.docker.com/settings/security + # * Access Token from here https://hub.docker.com/settings/security DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} diff --git a/.github/workflows/test_markdown.yml b/.github/workflows/lint.yml similarity index 69% rename from .github/workflows/test_markdown.yml rename to .github/workflows/lint.yml index 7b0a741..6004746 100644 --- a/.github/workflows/test_markdown.yml +++ b/.github/workflows/lint.yml @@ -1,6 +1,5 @@ -# yamllint --format github .github/workflows/test_markdown.yml --- -name: test_markdown +name: lint on: # yamllint disable-line rule:truthy push: # non-tagged pushes to master @@ -10,24 +9,28 @@ on: # yamllint disable-line rule:truthy - '*' paths: - '**/*.md' + - '.github/workflows/*.yml' + - './build-bin/*lint' - ./build-bin/mlc_config.json pull_request: # pull requests targeted at the master branch. branches: - master paths: - '**/*.md' + - '.github/workflows/*.yml' + - './build-bin/*lint' - ./build-bin/mlc_config.json jobs: - test-markdown: - name: Test Markdown + lint: + name: Lint runs-on: ubuntu-22.04 # newest available distribution, aka jellyfish # skip commits made by the release plugin if: "!contains(github.event.head_commit.message, 'maven-release-plugin')" steps: - name: Checkout Repository uses: actions/checkout@v4 - - name: Check Markdown links - uses: gaurav-nelson/github-action-markdown-link-check@v1 - with: - config-file: './build-bin/mlc_config.json' + - name: Lint + run: | + build-bin/configure_lint + build-bin/lint diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f34aa28..3bdf143 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,59 +1,42 @@ -# yamllint --format github .github/workflows/test.yml --- name: test # We don't test documentation-only commits. -on: - # We run tests on non-tagged pushes to master that aren't a commit made by the release plugin - push: - tags: '' - branches: master - paths-ignore: '**/*.md' - # We also run tests on pull requests targeted at the master branch. - pull_request: - branches: master - paths-ignore: '**/*.md' +on: # yamllint disable-line rule:truthy + push: # non-tagged pushes to master + branches: + - master + tags-ignore: + - '*' + paths-ignore: + - '**/*.md' + - './build-bin/*lint' + - ./build-bin/mlc_config.json + pull_request: # pull requests targeted at the master branch. + branches: + - master + paths-ignore: + - '**/*.md' + - './build-bin/*lint' + - ./build-bin/mlc_config.json jobs: - test-javadoc: - name: Test JavaDoc Builds - runs-on: ubuntu-22.04 # newest available distribution, aka jellyfish - if: "!contains(github.event.head_commit.message, 'maven-release-plugin')" - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 # full git history for license check - - name: Setup java - uses: actions/setup-java@v4 - with: - distribution: 'zulu' # zulu as it supports a wide version range - java-version: '17' # earliest LTS supported by Spring Boot 3 - - name: Cache local Maven repository - uses: actions/cache@v3 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-jdk-17-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-jdk-17-maven- - - name: Build JavaDoc - run: ./mvnw clean javadoc:aggregate -Prelease - test: name: test (JDK ${{ matrix.java_version }}) - runs-on: ubuntu-22.04 # newest available distribution, aka jellyfish + runs-on: ubuntu-22.04 # newest available distribution, aka jellyfish if: "!contains(github.event.head_commit.message, 'maven-release-plugin')" strategy: - fail-fast: false # don't fail fast as sometimes failures are operating system specific - matrix: # use latest available versions and be consistent on all workflows! + fail-fast: false # don't fail fast as some failures are LTS specific + matrix: # match with maven-enforcer-plugin rules in pom.xml include: - java_version: 17 # earliest LTS supported by Spring Boot 3 - maven_args: -Prelease -Dgpg.skip -Dmaven.javadoc.skip=true + maven_args: -Prelease -Dgpg.skip - java_version: 21 # Most recent LTS steps: - name: Checkout Repository uses: actions/checkout@v4 with: - fetch-depth: 0 # full git history for license check + fetch-depth: 0 # full git history for license check - name: Setup java uses: actions/setup-java@v4 with: @@ -63,6 +46,7 @@ jobs: uses: actions/cache@v3 with: path: ~/.m2/repository + # yamllint disable-line rule:line-length key: ${{ runner.os }}-jdk-${{ matrix.java_version }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-jdk-${{ matrix.java_version }}-maven- # Don't attempt to cache Docker. Sensitive information can be stolen diff --git a/build-bin/README.md b/build-bin/README.md index 27e0e88..bb99131 100755 --- a/build-bin/README.md +++ b/build-bin/README.md @@ -8,15 +8,6 @@ configuration settings. [docker-compose-zipkin-gcp.xml](docker-compose-zipkin-gcp.yml) ensures GCP authentication works. It is not run on pull request, as the required secure variable is only available on master push. -[mlc_config.json](mlc_config.json) is run by GitHub Action, but you can also run it locally, -assuming you installed markdown-link-check via NPM. - -```bash -$ find . -name \*.md |xargs markdown-link-check -c ./build-bin/mlc_config.json -``` - -[//]: # (Below here should be standard for all projects) - ## Build Overview `build-bin` holds portable scripts used in CI to test and deploy the project. @@ -31,14 +22,78 @@ CI-provider specific tools, doing so can easily create a dependency where no one release anymore. Do not use provider-specific mechanisms to implement release flow. Instead, automate triggering of the scripts here. -The only scripts that should be modified per project are in the base directory. Those in sub -directories, such as [docker], should not vary project to project except accident of version drift. -Intentional changes in sub directories should be relevant and tested on multiple projects to ensure -they can be blindly copy/pasted. +The only scripts that should be modified per project are in the base directory. Those in +subdirectories, such as [docker](docker), should not vary project to project except accident of +version drift. Intentional changes in subdirectories should be relevant and tested on multiple +projects to ensure they can be blindly copy/pasted. Conversely, the files in the base directory are project specific entry-points for test and deploy actions and are entirely appropriate to vary per project. Here's an overview: +## Lint + +Lint makes sure that documentation and workflows are in-tact. CI providers should be configured to +run lint on pull requests or pushes to the master branch, notably when the tag is blank. Linters +should only run on documentation-only commits or those who affect workflow files. Linters must not +depend on authenticated resources, as running lint can leak credentials. + +* [configure_lint](configure_lint) - Ensures linters are installed +* [lint](lint) - Runs the linters + +We minimally check the following: + +* [markdown-link-check](https://github.com/tcort/markdown-link-check) on our Markdown content. + * we maintain [mlc_config.json](mlc_config.json) for exceptions +* [yamllint](https://github.com/adrienverge/yamllint) on our GitHub Actions Workflow YAML. + * occasionally need line length exceptions via `# yamllint disable-line rule:line-length` + +### Example GitHub Actions setup + +A simplest GitHub Actions `lint.yml` runs linters after configuring them, but only on relevant event +conditions. The name `lint.yml` and job `lint` allows easy references to status badges and parity of +the scripts it uses. + +The `on:` section obviates job creation and resource usage for irrelevant events. Notably, GitHub +Actions includes the ability to skip documentation-only jobs. + +Here's a partial `lint.yml` including only the aspects mentioned above. +```yaml +--- +on: # yamllint disable-line rule:truthy + push: # non-tagged pushes to master + branches: + - master + tags-ignore: + - '*' + paths: + - '**/*.md' + - '.github/workflows/*.yml' + - './build-bin/*lint' + - ./build-bin/mlc_config.json + pull_request: # pull requests targeted at the master branch. + branches: + - master + paths: + - '**/*.md' + - '.github/workflows/*.yml' + - './build-bin/*lint' + - ./build-bin/mlc_config.json + +jobs: + lint: + name: Lint + runs-on: ubuntu-22.04 # newest available distribution, aka jellyfish + # skip commits made by the release plugin + if: "!contains(github.event.head_commit.message, 'maven-release-plugin')" + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + - name: Lint + run: | + build-bin/configure_lint + build-bin/lint +``` + ## Test Test builds and runs any tests of the project, including integration tests. CI providers should be @@ -47,8 +102,8 @@ blank. Tests should not run on documentation-only commits. Tests must not depend resources, as running tests can leak credentials. Git checkouts should include the full history so that license headers or other git analysis can take place. -* [configure_test] - Sets up build environment for tests. -* [test] - Builds and runs tests for this project. +* [configure_test](configure_test) - Sets up build environment for tests. +* [test](test) - Builds and runs tests for this project. ### Example GitHub Actions setup @@ -61,14 +116,23 @@ Actions includes the ability to skip documentation-only jobs. Here's a partial `test.yml` including only the aspects mentioned above. ```yaml -on: - push: - tags: '' - branches: master - paths-ignore: '**/*.md' - pull_request: - branches: master - paths-ignore: '**/*.md' +on: # yamllint disable-line rule:truthy + push: # non-tagged pushes to master + branches: + - master + tags-ignore: + - '*' + paths-ignore: + - '**/*.md' + - './build-bin/*lint' + - ./build-bin/mlc_config.json + pull_request: # pull requests targeted at the master branch. + branches: + - master + paths-ignore: + - '**/*.md' + - './build-bin/*lint' + - ./build-bin/mlc_config.json jobs: test: @@ -90,8 +154,8 @@ providers deploy pushes to master on when the tag is blank, but not on documenta Releases should deploy on version tags (ex `/^[0-9]+\.[0-9]+\.[0-9]+/`), without consideration of if the commit is documentation only or not. -* [configure_deploy] - Sets up environment and logs in, assuming [configure_test] was not called. -* [deploy] - deploys the project, with arg0 being "master" or a release commit like "1.2.3" +* [configure_deploy](configure_deploy) - Sets up environment and logs in. +* [deploy](deploy) - deploys the project, with arg1 being "master" or a release commit like "1.2.3" ### Example GitHub Actions setup @@ -107,24 +171,28 @@ Here's a partial `deploy.yml` including only the aspects mentioned above. Notice explicitly defined and `on.tags` is a [glob pattern](https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet). ```yaml -on: +on: # yamllint disable-line rule:truthy push: - tags: '[0-9]+.[0-9]+.[0-9]+**' # e.g. 8.272.10 or 15.0.1_p9 - branches: master + branches: + - master + # Don't deploy tags because the same commit for MAJOR.MINOR.PATCH is also + # on master: Redundant deployment of a release version will fail uploading. + tags-ignore: + - '*' jobs: deploy: + runs-on: ubuntu-22.04 # newest available distribution, aka jellyfish steps: - name: Checkout Repository uses: actions/checkout@v4 with: fetch-depth: 1 # only needed to get the sha label - - name: Configure Deploy - run: build-bin/configure_deploy + - name: Deploy env: GH_USER: ${{ secrets.GH_USER }} GH_TOKEN: ${{ secrets.GH_TOKEN }} - - name: Deploy - # GITHUB_REF will be refs/heads/master or refs/tags/1.2.3 - run: build-bin/deploy $(echo ${GITHUB_REF} | cut -d/ -f 3) + run: | # GITHUB_REF = refs/heads/master or refs/tags/MAJOR.MINOR.PATCH + build-bin/configure_deploy && + build-bin/deploy $(echo ${GITHUB_REF} | cut -d/ -f 3) ``` diff --git a/build-bin/configure_lint b/build-bin/configure_lint new file mode 100755 index 0000000..3d32fd7 --- /dev/null +++ b/build-bin/configure_lint @@ -0,0 +1,7 @@ +#!/bin/sh -ue + +# Attempt to install markdown-link-check if absent +markdown-link-check -V || npm install -g markdown-link-check + +# Attempt to install yamllint if absent +yamllint || pip install --user yamllint diff --git a/build-bin/lint b/build-bin/lint new file mode 100755 index 0000000..f1da6b7 --- /dev/null +++ b/build-bin/lint @@ -0,0 +1,4 @@ +#!/bin/sh -ue + +yamllint --format github .github/workflows/*.yml +find . -name \*.md |grep -v node|xargs markdown-link-check -c ./build-bin/mlc_config.json