From fe283d583b9ce7f16c8ef6e5316e7d168ed62915 Mon Sep 17 00:00:00 2001 From: Hugo Hakim Damer Date: Wed, 18 Dec 2024 15:11:40 +0100 Subject: [PATCH] feat(ci): build and deploy docs --- .github/workflows/report.yml | 194 +++++++++++++++++++---------------- README.md | 7 +- 2 files changed, 112 insertions(+), 89 deletions(-) diff --git a/.github/workflows/report.yml b/.github/workflows/report.yml index 5d5d03d3..430af0cc 100644 --- a/.github/workflows/report.yml +++ b/.github/workflows/report.yml @@ -1,9 +1,9 @@ -name: Generate and Provide Reports +name: Docs, Coverage Report and PR updates # WARNING: This Workflow is executed with the workflow_run trigger, which means that # it is run in the context of the target/upstream repository and granted *write access* # to the target/upstream repository. -# It should *only* be used for actions that require write access (e.g., to generate/deploy +# It *should only* be used for actions that require write access (e.g., to generate/deploy # the documentation/coverage report to GitHub Pages or to create a PR comment) and *must # never* execute code contained in the repository. @@ -19,81 +19,83 @@ env: RUST_TEST_TIME_UNIT: 60,120 RUST_TEST_TIME_INTEGRATION: 60,120 RUST_TEST_TIME_DOCTEST: 60,120 + BRANCH: |- + ${{ + (github.event.workflow_run.head_repository.owner.login != github.event.workflow_run.repository.owner.login) + && format('{0}:{1}', github.event.workflow_run.head_repository.owner.login, github.event.workflow_run.head_branch) + || github.event.workflow_run.head_branch + }} + HEAD_REF: ${{ github.event.workflow_run.head_sha }} + REPO_URL: "${{ github.server_url }}/${{ github.repository }}" + +concurrency: + # env context is not available here, so i just copied the code for env.BRANCH. + group: ${{ github.workflow }}-${{ + (github.event.workflow_run.head_repository.owner.login != github.event.workflow_run.repository.owner.login) + && format('{0}:{1}', github.event.workflow_run.head_repository.owner.login, github.event.workflow_run.head_branch) + || github.event.workflow_run.head_branch + }} + cancel-in-progress: true jobs: - #lint: - # name: lint - # runs-on: ubuntu-latest - # env: - # BRANCH: |- - # ${{ - # (github.event.workflow_run.head_repository.owner.login != github.event.workflow_run.repository.owner.login) - # && format('{0}:{1}', github.event.workflow_run.head_repository.owner.login, github.event.workflow_run.head_branch) - # || github.event.workflow_run.head_branch - # }} - # strategy: - # matrix: - # crate: [ libcoap-sys, libcoap-rs ] - # steps: - # - uses: actions/checkout@v4 - # with: - # submodules: true - # ref: ${{ env.BRANCH }} - # - uses: reviewdog/action-setup@v1 - # with: - # reviewdog_version: latest - # - uses: dtolnay/rust-toolchain@stable - # with: - # components: clippy - # - uses: baptiste0928/cargo-install@v3 - # with: - # crate: clippy-reviewdog-filter - # - env: - # REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # run: reviewdog -reporter=github-pr-check -fail-level=any - #fmt: - # name: rustfmt - # runs-on: ubuntu-latest - # env: - # BRANCH: |- - # ${{ - # (github.event.workflow_run.head_repository.owner.login != github.event.workflow_run.repository.owner.login) - # && format('{0}:{1}', github.event.workflow_run.head_repository.owner.login, github.event.workflow_run.head_branch) - # || github.event.workflow_run.head_branch - # }} - # strategy: - # fail-fast: false - # matrix: - # crate: [ libcoap-sys, libcoap-rs ] - # steps: - # - uses: actions/checkout@v4 - # with: - # ref: ${{ env.BRANCH }} - # - uses: dtolnay/rust-toolchain@stable - # with: - # components: rustfmt - # - run: cargo fmt -p ${{ matrix.crate }} - # - name: Generate PR suggestions from rustfmt changes - # uses: reviewdog/action-suggester@v1 - # with: - # tool_name: rustfmt - # fail_on_error: true - # reviewdog_args: -reporter=github-pr-check + docs: + runs-on: ubuntu-latest + outputs: + docs_dl: ${{ format('{0}/actions/runs/{1}/artifacts/{2}', env.REPO_URL, github.run_id, steps.upload-docs.outputs.artifact-id) }} + docs_url: |- + ${{ + (github.event.workflow_run.head_repository.owner.login == github.event.workflow_run.repository.owner.login) + && format('{0}/docs/{1}/libcoap_rs/', vars.DOCS_AND_COV_URL, env.BRANCH) + || '' + }} + steps: + - uses: actions/checkout@v4 + with: + submodules: true + ref: ${{ env.HEAD_REF }} + # --all-features uses GNUTLS als backend, must provide it. + - uses: awalsh128/cache-apt-pkgs-action@latest + with: + packages: libgnutls28-dev libgnutls30 + version: 1.0 + - uses: dtolnay/rust-toolchain@nightly + with: + components: rustc + - name: Build documentation + run: cargo doc --all-features --no-deps --workspace + - uses: actions/upload-artifact@v4 + id: upload-docs + with: + name: docs + path: | + ./target/doc + # Deploy to GitHub Pages only if the PR is not from a forked repository. + # For security reasons, we don't want PRs from forked PRs to upload coverage data to our GitHub Pages. + - if: ${{ github.event.workflow_run.head_repository.owner.login == github.event.workflow_run.repository.owner.login }} + uses: peaceiris/actions-gh-pages@v4 + with: + publish_dir: ./target/doc + publish_branch: main + external_repository: ${{ vars.DOCS_AND_COV_REPO }} + personal_token: ${{ secrets.DOCS_AND_COV_REPO_TOKEN }} + destination_dir: docs/${{ env.BRANCH }} coverage-report: name: coverage-report runs-on: ubuntu-latest - env: + env: LLVM_PROFILE_FILE: './coverage-data/coverage/libcoap-rs-%p-%m.profraw' - BRANCH: |- - ${{ - (github.event.workflow_run.head_repository.owner.login != github.event.workflow_run.repository.owner.login) - && format('{0}:{1}', github.event.workflow_run.head_repository.owner.login, github.event.workflow_run.head_branch) - || github.event.workflow_run.head_branch - }} outputs: report: ${{ steps.cov-report.outputs.summary }} + report_dl: ${{ format('{0}/actions/runs/{1}/artifacts/{2}', env.REPO_URL, github.run_id, steps.upload-cov-report.outputs.artifact-id) }} + report_url: |- + ${{ + (github.event.workflow_run.head_repository.owner.login == github.event.workflow_run.repository.owner.login) + && format('{0}/coverage/{1}', vars.DOCS_AND_COV_URL, env.BRANCH) + || '' + }} + badge_url: ${{ format('{0}/coverage/{1}/badges/flat.svg', vars.DOCS_AND_COV_URL, env.BRANCH) }} permissions: actions: write contents: write @@ -101,7 +103,7 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - ref: ${{ env.BRANCH }} + ref: ${{ env.HEAD_REF }} - uses: actions/download-artifact@v4 with: pattern: test-coverage-data-* @@ -127,6 +129,7 @@ jobs: echo "$EOF" } >> "$GITHUB_OUTPUT" - uses: actions/upload-artifact@v4 + id: upload-cov-report with: name: coverage-report path: | @@ -136,38 +139,48 @@ jobs: - if: ${{ github.event.workflow_run.head_repository.owner.login == github.event.workflow_run.repository.owner.login }} uses: peaceiris/actions-gh-pages@v4 with: - github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./coverage/html - publish_branch: _gh_pages + publish_branch: main + external_repository: ${{ vars.DOCS_AND_COV_REPO }} + personal_token: ${{ secrets.DOCS_AND_COV_REPO_TOKEN }} destination_dir: coverage/${{ env.BRANCH }} + # For forked repositories, only upload the generated badge. + - if: ${{ github.event.workflow_run.head_repository.owner.login != github.event.workflow_run.repository.owner.login }} + uses: peaceiris/actions-gh-pages@v4 + with: + publish_dir: ./coverage/html/badges + publish_branch: main + external_repository: ${{ vars.DOCS_AND_COV_REPO }} + personal_token: ${{ secrets.DOCS_AND_COV_REPO_TOKEN }} + destination_dir: coverage/${{ env.BRANCH }}/badges pr-comment: name: pr-comment runs-on: ubuntu-latest + # All other jobs here should also run on a push to main. This one is specific to pull requests, however. if: ${{ always() && github.event.workflow_run.event == 'pull_request' }} - needs: [ fmt ] + needs: [ coverage-report, docs ] env: COV_OUTPUT: ${{ needs.coverage-report.outputs.report }} + COV_DL: ${{ needs.coverage-report.outputs.report_dl }} + COV_BADGE: ${{ needs.coverage-report.outputs.badge_url }} + DOCS_DL: ${{ needs.docs.outputs.docs_dl }} + COV_URL: ${{ needs.coverage-report.outputs.report_url }} + DOCS_URL: ${{ needs.docs.outputs.docs_url }} + # Token required for GH CLI: + GH_TOKEN: ${{ github.token }} + # Best practice for scripts is to reference via ENV at runtime. Avoid using the expression syntax in the script content directly: + PR_TARGET_REPO: ${{ github.repository }} steps: + - uses: actions/checkout@v4 + with: + submodules: false # See https://github.com/orgs/community/discussions/25220#discussioncomment-11316244 - name: 'Get PR context' id: pr-context - env: - # Token required for GH CLI: - GH_TOKEN: ${{ github.token }} - # Best practice for scripts is to reference via ENV at runtime. Avoid using the expression syntax in the script content directly: - PR_TARGET_REPO: ${{ github.repository }} - PR_TARGET_REPO_URL: ${{ github.server_url }}/${{ github.repository }} - # If the PR is from a fork, prefix it with `:`, otherwise only the PR branch name is relevant: - PR_BRANCH: |- - ${{ - (github.event.workflow_run.head_repository.owner.login != github.event.workflow_run.repository.owner.login) - && format('{0}:{1}', github.event.workflow_run.head_repository.owner.login, github.event.workflow_run.head_branch) - || github.event.workflow_run.head_branch - }} # Query the PR number by repo + branch, then assign to step output: run: | - gh pr view --repo "${PR_TARGET_REPO}" "${PR_BRANCH}" \ + gh pr view --repo "${PR_TARGET_REPO}" "${BRANCH}" \ --json 'number' --jq '"number=\(.number)"' \ >> "${GITHUB_OUTPUT}" - name: "Generate Markdown Report" @@ -179,12 +192,19 @@ jobs: echo "# Workflow Status Report" echo "Generated for commit ${{ github.sha }} on `date -u`." echo "" - echo "[![Test and Analyze](${PR_TARGET_REPO_URL}/actions/workflows/test.yml/badge.svg?branch=${GITHUB_HEAD_REF}&hash=${{ github.sha }})](${PR_TARGET_REPO_URL}/actions/workflows/test.yml?query=branch%3A${PR_BRANCH})" + echo "[![Test and Analyze](${REPO_URL}/actions/workflows/test.yml/badge.svg?branch=${GITHUB_HEAD_REF}&hash=${{ github.sha }})](${REPO_URL}/actions/workflows/test.yml?query=branch%3A${BRANCH})" + echo "[![Docs, Coverage Report and PR Updates](${REPO_URL}/actions/workflows/report.yml/badge.svg?branch=${GITHUB_HEAD_REF}&hash=${{ github.sha }})](${REPO_URL}/actions/workflows/report.yml?query=branch%3A${BRANCH})" echo "" echo "In case of failure, clippy warnings and rustfmt changes (if any) will be indicated as CI check warnings in the file comparison view." echo "" + echo "Documentation: ${{ (env.DOCS_URL != '') && format('[Read Online]({0})', env.DOCS_URL) || '' }} [Download](${DOCS_DL})" + echo "" + echo "Coverage Report: ${{ (env.COV_URL != '') && format('[Read Online]({0})', env.COV_URL) || '' }} [Download](${COV_DL})" + echo "" + echo "Note: Online versions of documentation and coverage reports may not be available indefinitely, especially after the pull request was merged." + echo "" echo "## Code Coverage Report" - echo "[![Coverage](https://namib-project.github.io/libcoap-rs/coverage/${{ github.event.workflow_run.head_branch }}/badges/flat.svg?hash=${{ github.sha }})](https://namib-project.github.io/libcoap-rs/coverage/${{ github.event.workflow_run.head_branch }})" + echo "[![Coverage](${COV_BADGE}?hash=${{ github.sha }})](${{ (env.COV_URL == '') && env.COV_DL || env.COV_URL}})" echo "" echo "Coverage target is 80%." echo "" diff --git a/README.md b/README.md index 9e2efb6f..ff5435e1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ # libcoap-rs -[![CI Status](https://github.com/namib-project/libcoap-rs/actions/workflows/ci.yml/badge.svg)](https://github.com/namib-project/libcoap-rs/actions/workflows/ci.yml) -![Coverage](https://namib-project.github.io/libcoap-rs/coverage/main/badges/flat.svg) +[![latest release on crates.io](https://img.shields.io/crates/v/libcoap_rs)](https://crates.io/crates/libcoap-rs) +[![Documentation (latest release)](https://img.shields.io/badge/docs-latest_release-blue)](https://docs.rs/libcoap_rs/) +[![Documentation (main)](https://img.shields.io/badge/docs-main-blue)](https://namib-project.github.io/libcoap-rs-docs/docs/main/libcoap_rs/) +[![Test and Analyze](https://github.com/namib-project/libcoap-rs/actions/workflows/test.yml/badge.svg)](https://github.com/namib-project/libcoap-rs/actions/workflows/test.yml) +[![Coverage (main)](https://namib-project.github.io/libcoap-rs-docs/coverage/main/badges/flat.svg)](https://namib-project.github.io/libcoap-rs-docs/coverage/main/) Raw binding and safe wrapper for the [libcoap CoAP libary](https://github.com/obgm/libcoap).