diff --git a/.github/workflows/build-check-install.yaml b/.github/workflows/build-check-install.yaml deleted file mode 100644 index c7d934d..0000000 --- a/.github/workflows/build-check-install.yaml +++ /dev/null @@ -1,841 +0,0 @@ ---- -name: R CMD Check ๐Ÿงฌ - -on: - push: - tags: - - "v*" - branches: - - main - pull_request: - types: - - opened - - synchronize - - reopened - - ready_for_review - branches: - - main - workflow_dispatch: - workflow_call: - secrets: - REPO_GITHUB_TOKEN: - description: | - Github token with read access to repositories, required for staged.dependencies installation - required: false - inputs: - install-system-dependencies: - description: Check for and install system dependencies - required: false - default: false - type: boolean - enable-staged-dependencies-check: - description: Enable staged dependencies YAML check - required: false - default: false - type: boolean - R_CHECK_FORCE_SUGGESTS: - description: If true, give an error if suggested packages are not available - required: false - default: true - type: boolean - skip-r-cmd-check: - description: Skip the R CMD check step in this workflow - required: false - default: false - type: boolean - skip-r-cmd-install: - description: Skip the R CMD INSTALL step in this workflow - required: false - default: true - type: boolean - enforce-note-blocklist: - description: Whether to check for specific NOTEs via regexes that should cause the pipeline to fail - required: false - default: false - type: boolean - note-blocklist: - description: | - List of regular expressions appearing in NOTEs that should cause the pipeline to fail. - Example usage: - note-blocklist: | - checking package dependencies ... NOTE( )+Depends: includes the non-default packages - checking R code for possible problems ... NOTE( )+.*: no visible global function definition for - checking for unstated dependencies in vignettes ... NOTE( )+\'.*\' import not declared from - checking dependencies in R code ... NOTE( )+Namespace in Imports field not imported from - checking installed package size ... NOTE( )+installed size is - required: false - default: "" - type: string - additional-r-cmd-check-params: - description: Additional flags or parameters to add to R CMD check - required: false - default: "" - type: string - disable-unit-test-reports: - description: Do not produce unit test reports - required: false - default: false - type: boolean - additional-env-vars: - description: | - Extra environment variables, as a 'key=value' pair, with each pair on a new line. - Example usage: - additional-env-vars: | - ABC=123 - XYZ=456 - required: false - default: "" - type: string - junit-xml-storage: - description: Branch name to store JUnit XML reports - required: false - default: "_junit_xml_reports" - type: string - junit-xml-diff-branch: - description: Against which branch should the JUnit XML report from the current branch be compared? - required: false - default: main - type: string - junit-xml-comparison: - description: Turn on JUnit XML comparison - required: false - default: true - type: boolean - junit-xml-negative-threshold: - description: | - If time difference during JUnit XML comparison is between negative-threshold and 0: it's treated as 0. - This means that if test suite/case executes up to negative-threshold seconds faster, - this time difference is ignored as insignificant, and test suite/case is not shown in the table - required: false - default: 1.0 - type: string - junit-xml-positive-threshold: - description: | - If time difference during JUnit XML comparison is between 0 and positive-threshold: it's treated as 0. - This means that if test suite/case executes up to positive-threshold seconds slower, - this time difference is ignored as insignificant, and test suite/case is not shown in the table - required: false - default: 1.0 - type: string - sd-direction: - description: The direction to use to install staged dependencies. Choose between 'upstream', 'downstream' and 'all' - required: false - type: string - default: upstream - unit-test-report-brand: - description: Image URL to use in unit test report for branding. If empty, the default xunit-viewer brand will be used. - required: false - type: string - default: "" - publish-unit-test-report-gh-pages: - description: Publish HTML unit test report to GitHub Pages alongside pkgdown docs. - required: false - type: boolean - default: true - latest-tag-alt-name: - description: | - The name of directory to store unit test report when running for latest tag. - The variable is named this way to keep it consistent with r-pkgdown-multiversion input name. - required: false - type: string - default: "latest-tag" - release-candidate-alt-name: - description: | - The name of directory to store unit test report when running for rc tag. - The variable is named this way to keep it consistent with r-pkgdown-multiversion input name. - required: false - type: string - default: "release-candidate" - package-subdirectory: - description: Subdirectory in the repository, where the R package is located. - required: false - type: string - default: "" - additional-caches: - description: | - Additional cache directories. One cache path per new line. - Example usage: - additional-caches: | - ~/awesome-cache - /tmp/some-cache - required: false - type: string - default: "" - -concurrency: - group: r-cmd-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - build-install-check: - strategy: - fail-fast: false - matrix: - config: - - image: ghcr.io/insightsengineering/rstudio - tag: latest - name: ${{ matrix.config.image }}, version ${{ matrix.config.tag }} - runs-on: ubuntu-latest - if: > - !contains(github.event.commits[0].message, '[skip r-cmd]') - && github.event.pull_request.draft == false - container: - image: ${{ matrix.config.image }}:${{ matrix.config.tag }} - outputs: - publish-unit-test-html-report: ${{ steps.junit-output.outputs.junit-upload }} - current-branch-or-tag: ${{ steps.current-branch-or-tag.outputs.ref-name }} - is-latest-tag: ${{ steps.current-branch-or-tag.outputs.is-latest-tag }} - is-rc-tag: ${{ steps.current-branch-or-tag.outputs.is-rc-tag }} - multiversion-docs: ${{ steps.current-branch-or-tag.outputs.multiversion-docs }} - - steps: - - name: Setup token ๐Ÿ”‘ - id: github-token - run: | - if [ "${{ secrets.REPO_GITHUB_TOKEN }}" == "" ]; then - echo "REPO_GITHUB_TOKEN is empty. Substituting it with GITHUB_TOKEN." - echo "token=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_OUTPUT - else - echo "Using REPO_GITHUB_TOKEN." - echo "token=${{ secrets.REPO_GITHUB_TOKEN }}" >> $GITHUB_OUTPUT - fi - shell: bash - - - name: Get branch names ๐ŸŒฟ - id: branch-name - uses: tj-actions/branch-names@v6 - - - name: Checkout gh-pages ๐Ÿ›Ž - if: >- - inputs.publish-unit-test-report-gh-pages == true - && github.event_name != 'pull_request' - id: checkout-gh-pages - uses: actions/checkout@v3 - with: - ref: gh-pages - path: gh-pages - repository: ${{ github.event.pull_request.head.repo.full_name }} - continue-on-error: true - - - name: Get current branch or tag ๐Ÿท๏ธ - if: >- - inputs.publish-unit-test-report-gh-pages == true - && github.event_name != 'pull_request' - id: current-branch-or-tag - run: | - if [ "${{ steps.branch-name.outputs.is_tag }}" == "true" ]; then - echo "Current tag: ${{ steps.branch-name.outputs.tag }}" - echo "ref-name=${{ steps.branch-name.outputs.tag }}" >> $GITHUB_OUTPUT - current_tag="${{ steps.branch-name.outputs.tag }}" - if [ "$(echo "$current_tag" | grep -E "^v([0-9]+\.)?([0-9]+\.)?([0-9]+)$")" != "" ]; then - echo "Running for latest-tag." - echo "is-latest-tag=true" >> $GITHUB_OUTPUT - elif [ "$(echo "$current_tag" | grep -E "^v([0-9]+\.)?([0-9]+\.)?([0-9]+)(-rc[0-9]+)$")" != "" ]; then - echo "Running for rc-tag." - echo "is-rc-tag=true" >> $GITHUB_OUTPUT - fi - else - echo "Current branch: ${{ steps.branch-name.outputs.current_branch }}" - echo "ref-name=${{ steps.branch-name.outputs.current_branch }}" >> $GITHUB_OUTPUT - fi - # Check if pkgdown multiversion docs are used at all. - if [ $(grep -rl '' gh-pages | wc -l) -gt 0 ]; then - echo "multiversion-docs=true" >> $GITHUB_OUTPUT - else - echo "multiversion-docs=false" >> $GITHUB_OUTPUT - fi - shell: bash - - - name: Normalize variables ๐Ÿ“ - run: | - junit_xml_storage_input="${{ inputs.junit-xml-storage }}" - junit_xml_diff_branch_input="${{ inputs.junit-xml-diff-branch }}" - junit_xml_comparison_input="${{ inputs.junit-xml-comparison }}" - junit_xml_positive_threshold="${{ inputs.junit-xml-positive-threshold }}" - junit_xml_negative_threshold="${{ inputs.junit-xml-negative-threshold }}" - echo "junit_xml_storage=${junit_xml_storage_input:-_junit_xml_reports}" >> $GITHUB_ENV - echo "junit_xml_diff_branch=${junit_xml_diff_branch_input:-main}" >> $GITHUB_ENV - echo "junit_xml_comparison=${junit_xml_comparison_input:-true}" >> $GITHUB_ENV - echo "junit_xml_positive_threshold=${junit_xml_positive_threshold:-1.0}" >> $GITHUB_ENV - echo "junit_xml_negative_threshold=${junit_xml_negative_threshold:-1.0}" >> $GITHUB_ENV - shell: bash - - - name: Restore npm cache ๐Ÿ’ฐ - if: >- - inputs.publish-unit-test-report-gh-pages == true - && github.event_name != 'pull_request' - uses: actions/cache@v3 - with: - key: npm-${{ runner.os }}-${{ github.job }} - restore-keys: | - npm-${{ runner.os }}- - path: node_modules - - - name: Setup NodeJS โ˜Š - if: >- - inputs.publish-unit-test-report-gh-pages == true - && github.event_name != 'pull_request' - uses: actions/setup-node@v3 - id: npm-cache - with: - node-version: 18 - - - name: Install xunit-viewer โš™๏ธ - if: >- - steps.npm-cache.outputs.cache-hit != 'true' - && inputs.publish-unit-test-report-gh-pages == true - && github.event_name != 'pull_request' - run: npm i -g xunit-viewer - shell: bash - - - name: Checkout repo (PR) ๐Ÿ›Ž - uses: actions/checkout@v3 - if: github.event_name == 'pull_request' - with: - ref: ${{ steps.branch-name.outputs.head_ref_branch }} - path: ${{ github.event.repository.name }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - - name: Checkout repo ๐Ÿ›Ž - uses: actions/checkout@v3 - if: github.event_name != 'pull_request' - with: - ref: ${{ steps.branch-name.outputs.head_ref_branch }} - path: ${{ github.event.repository.name }} - - - name: Restore SD cache ๐Ÿ’ฐ - uses: actions/cache@v3 - with: - key: sd-${{ runner.os }}-${{ github.event.repository.name }} - path: ~/.staged.dependencies - - - name: Run Staged dependencies ๐ŸŽฆ - uses: insightsengineering/staged-dependencies-action@v1 - env: - GITHUB_PAT: ${{ steps.github-token.outputs.token }} - with: - path: ${{ github.event.repository.name }}/${{ inputs.package-subdirectory }} - enable-check: ${{ inputs.enable-staged-dependencies-check }} - run-system-dependencies: ${{ inputs.install-system-dependencies }} - direction: ${{ inputs.sd-direction }} - - - name: Show session info and installed packages โ„น - run: | - sessionInfo() - as.data.frame(installed.packages()[, c("LibPath", "Version")]) - if (grepl("--as-cran", "${{ inputs.additional-r-cmd-check-params }}", fixed = TRUE)) { - x <- desc::desc_del("Remotes") - } - if ("${{ inputs.disable-unit-test-reports }}" != "true") { - x <- desc::desc_set_dep("xml2", "Suggests") - } - shell: Rscript {0} - working-directory: ${{ github.event.repository.name }}/${{ inputs.package-subdirectory }} - - - name: Get package name ๐Ÿ“ฆ - run: | - echo "PKGBUILD=$(echo $(awk -F: '/Package:/{gsub(/[ ]+/,"") ; print $2}' DESCRIPTION)_"\ - "$(awk -F: '/Version:/{gsub(/[ ]+/,"") ; print $2}' DESCRIPTION).tar.gz)" >> $GITHUB_ENV - echo "PKGNAME=$(echo $(awk -F: '/Package:/{gsub(/[ ]+/,"") ; print $2}' DESCRIPTION))" >> $GITHUB_ENV - shell: bash - working-directory: ${{ github.event.repository.name }}/${{ inputs.package-subdirectory }} - - - name: Replace testthat.R for test reporting ๐ŸŽš - if: inputs.disable-unit-test-reports != 'true' - run: | - if [ -f "tests/testthat.R" ]; then { - # Overwrite testthat.R for JUnit XML reporting - cat > tests/testthat.R < /tmp/dotenv.env - export $(tr '\n' ' ' < /tmp/dotenv.env) - } - fi - R CMD build ${{ github.event.repository.name }}/${{ inputs.package-subdirectory }} - shell: bash - - - name: Set TESTING_DEPTH โš™ - env: - COMMIT_NEWEST_MESSAGE: ${{ github.event.head_commit.message }} - COMMIT_OLDEST_MESSAGE: ${{ github.event.commits[0].message }} - run: | - # set TESTING_DEPTH for PR - if [[ ! -z "${GITHUB_HEAD_REF}" ]]; then - TESTING_DEPTH=3 - echo "TESTING_DEPTH=3" >> $GITHUB_ENV - COMMIT_NEWEST_MESSAGE=$(git log --format=%B -n 1 ${{ github.event.after }}) - fi - if [[ $COMMIT_NEWEST_MESSAGE == *"[skip tests]"* ]]; then - echo "NO_TESTS=1" >> $GITHUB_ENV - fi - # default TESTING_DEPTH - if [[ -z "${TESTING_DEPTH}" ]]; then - echo "TESTING_DEPTH=1" >> $GITHUB_ENV - fi - shell: bash - working-directory: ${{ github.event.repository.name }}/${{ inputs.package-subdirectory }} - - - name: Run R CMD check ๐Ÿ - run: | - if [ "${{ inputs.skip-r-cmd-check }}" == "true" ] - then { - echo "Skipping R CMD check as 'skip-r-cmd-check' was set to 'true'" - exit 0 - } - fi - if [ "${{ inputs.R_CHECK_FORCE_SUGGESTS }}" == "" ] - then { - _R_CHECK_FORCE_SUGGESTS_="FALSE" - } - fi - ADDITIONAL_PARAMS=${{ inputs.additional-r-cmd-check-params }} - if [[ ! -z "${{ env.NO_TESTS }}" ]] - then { - ADDITIONAL_PARAMS="${ADDITIONAL_PARAMS} --no-tests" - } - fi - if [ "${{ inputs.additional-env-vars }}" != "" ] - then { - echo -e "${{ inputs.additional-env-vars }}" > /tmp/dotenv.env - export $(tr '\n' ' ' < /tmp/dotenv.env) - } - fi - Rscript - <- - steps.check-junit-xml.outputs.files_exists == 'true' - && inputs.publish-unit-test-report-gh-pages == true - && github.event_name != 'pull_request' - run: | - brand_option="" - if [ "${{ inputs.unit-test-report-brand }}" != "" ]; then - brand_option='--brand ${{ inputs.unit-test-report-brand }}' - fi - xunit-viewer -r "${{ env.PKGNAME }}.Rcheck/tests/testthat/junit-result.xml" \ - -o index.html \ - -f "https://www.clipboardmaster.com/favicon.ico" \ - -t "${{ env.PKGNAME }} Unit Test Results" \ - $brand_option - shell: bash - - - name: Publish JUnit XML as artifact ๐Ÿ“ฐ - if: >- - steps.check-junit-xml.outputs.files_exists == 'true' - && inputs.publish-unit-test-report-gh-pages == true - && github.event_name != 'pull_request' - uses: actions/upload-artifact@v3 - with: - name: unit-test-report - path: "index.html" - - - name: Set output โš™๏ธ - id: junit-output - if: >- - steps.check-junit-xml.outputs.files_exists == 'true' - && inputs.publish-unit-test-report-gh-pages == true - && github.event_name != 'pull_request' - run: echo "junit-upload=true" >> $GITHUB_OUTPUT - - - name: Publish Unit Test Summary ๐Ÿ“‘ - uses: EnricoMi/publish-unit-test-result-action@v2 - id: test-results - # Second line of the condition skips the step if workflow is running in a fork. - if: | - steps.check-junit-xml.outputs.files_exists == 'true' && github.event_name == 'pull_request' && - github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name - with: - check_name: Unit Tests Summary - junit_files: "${{ env.PKGNAME }}.Rcheck/tests/testthat/junit-result.xml" - - - name: Fetch JUnit XML reports from ${{ env.junit_xml_storage }} โคต๏ธ - if: steps.check-junit-xml.outputs.files_exists == 'true' && env.junit_xml_comparison == 'true' - uses: actions/checkout@v3 - with: - path: ${{ env.junit_xml_storage }} - fetch-depth: 0 - - - name: Set up ${{ env.junit_xml_storage }} branch for reports ๐Ÿ—ƒ๏ธ - if: steps.check-junit-xml.outputs.files_exists == 'true' && env.junit_xml_comparison == 'true' - run: | - BRANCH=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}} - echo "diff_storage_branch=$BRANCH" >> $GITHUB_ENV - mkdir -p ${{ env.junit_xml_storage }}/data/${BRANCH} - shell: bash - - - name: Commit JUnit XML report ๐Ÿ“„ - if: steps.check-junit-xml.outputs.files_exists == 'true' && env.junit_xml_comparison == 'true' - working-directory: ${{ env.junit_xml_storage }}/data - run: | - git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - git switch ${{ env.junit_xml_storage }} || true - git config pull.rebase false - git pull origin ${{ env.junit_xml_storage }} || true - cp ../../${{ env.PKGNAME }}.Rcheck/tests/testthat/junit-result.xml \ - ./${{ env.diff_storage_branch }}/junit-result.xml - git add -f "${{ env.diff_storage_branch }}/junit-result.xml" - git commit -m "Add/Update JUnit report: ${{ github.sha }}" || true - shell: bash - - - name: Push JUnit XML report to ${{ env.junit_xml_storage }} ๐Ÿ“„ - if: steps.check-junit-xml.outputs.files_exists == 'true' && env.junit_xml_comparison == 'true' - uses: ad-m/github-push-action@master - with: - github_token: ${{ steps.github-token.outputs.token }} - branch: ${{ env.junit_xml_storage }} - directory: ${{ env.junit_xml_storage }}/data - continue-on-error: true - - - name: Run XML comparison ๐Ÿ” - if: steps.check-junit-xml.outputs.files_exists == 'true' && env.junit_xml_comparison == 'true' - run: | - cp ${{ env.junit_xml_storage }}/data/${{ env.diff_storage_branch }}/junit-result.xml new.xml - if [ ! -f ${{ env.junit_xml_storage }}/data/${{ env.junit_xml_diff_branch }}/junit-result.xml ]; then - # If XML for the branch against which we're comparing doesn't exist, we're skipping the comparison. - echo "JUnit report for branch \`${{ env.junit_xml_diff_branch }}\` " \ - "doesn't exist on \`${{ env.junit_xml_storage }}\` branch yet." > output.md - echo "Once this workflow runs on \`${{ env.junit_xml_diff_branch }}\` branch, " \ - "you'll see comparison of tests performance between \`${{ env.junit_xml_diff_branch }}\` " \ - "and \`${{ env.diff_storage_branch }}\` as a PR comment." >> output.md - else - cp ${{ env.junit_xml_storage }}/data/${{ env.junit_xml_diff_branch }}/junit-result.xml old.xml - wget https://github.com/insightsengineering/junit-xml-diff/releases/download/v0.4.0/junit-xml-diff_0.4.0_linux_amd64.tar.gz \ - -O junit-xml-diff.tar.gz - tar xzf junit-xml-diff.tar.gz - ./junit-xml-diff old.xml new.xml output.md '${{ env.junit_xml_diff_branch }}' \ - '${{ env.junit_xml_positive_threshold }}' '${{ env.junit_xml_negative_threshold }}' - if [ "$(du -b output.md | awk '{print $1}')" != "0" ]; then - # Non-empty output which means that there is at least one test suite/case in the table. - # Empty table won't be published since junit_xml_comparison_result_method won't be set. - echo "junit_xml_comparison_result_method=comment" >> $GITHUB_ENV - echo "" >> output.md - echo "Results for commit ${{ github.sha }}" >> output.md - echo "" >> output.md - echo "โ™ป๏ธ This comment has been updated with latest results." >> output.md - cp output.md output-artifact.md - echo "Size of markdown: $(du -b output.md | awk '{print $1}') bytes" - if [ "$(du -b output.md | awk '{print $1}')" -ge "60000" ]; then - echo "The result of JUnit XML file comparison exceeded maximum size. " \ - "The report has therefore been uploaded as an R CMD check workflow artifact." > output.md - echo "junit_xml_comparison_result_method=artifact" >> $GITHUB_ENV - fi - echo "Markdown output:" - cat output.md - else - echo "No test suites/cases in JUnit XML file difference." - fi - fi - - - name: Post JUnit XML comparison as comment ๐Ÿ’ฌ - if: > - steps.check-junit-xml.outputs.files_exists == 'true' && - env.junit_xml_comparison == 'true' && - env.junit_xml_comparison_result_method == 'comment' && - !github.event.pull_request.head.repo.fork && - github.event_name == 'pull_request' - uses: marocchino/sticky-pull-request-comment@v2 - with: - header: markdown-table - path: output.md - continue-on-error: true - - - name: Upload JUnit XML comparison โคด - if: > - steps.check-junit-xml.outputs.files_exists == 'true' && - env.junit_xml_comparison == 'true' && - env.junit_xml_comparison_result_method == 'artifact' && - !github.event.pull_request.head.repo.fork && - github.event_name == 'pull_request' - uses: actions/upload-artifact@v3 - with: - path: output-artifact.md - name: junit-xml-report-comparison - continue-on-error: true - - - name: Show R CMD check logs ๐Ÿ”Ž - if: inputs.skip-r-cmd-check != true - run: | - find ${{ env.PKGNAME }}.Rcheck -type f -regextype posix-egrep \ - -regex '.*00install.out|.*00check.log|.*00build.out' -print0 | while IFS= read -r -d $'\0' file; do - printf "==================================\n$file\n==================================\n" - cat $file - done - shell: bash - - - name: Catch warnings in R CMD check output ๐Ÿ—ณ - id: catch-errors - run: | - check_log <- "${{ env.PKGNAME }}.Rcheck/00check.log" - if (file.exists(check_log)) { - x <- tail(readLines(check_log), 1) - if (grepl("ERROR", x)) { - writeLines(readLines(check_log)) - stop("โŒ R CMD check has errors. Please refer to the 'Show R CMD check logs ๐Ÿ”Ž' step above.") - } - if (grepl("WARNING", x)) { - writeLines(readLines(check_log)) - stop("โš  R CMD check has warnings. Please refer to the 'Show R CMD check logs ๐Ÿ”Ž' step above.") - } - if ("${{ inputs.enforce-note-blocklist }}" == "true") { - print("Checking notes...") - regexes <- "${{ inputs.note-blocklist }}" - regexes <- unlist(strsplit(regexes, split = "\n")) - lines <- paste(readLines(check_log), collapse = "\n") - notes_result <- vapply( - regexes, - function(r){ - if (grepl(paste0(r, "\n"), lines, perl=T)) { - print(r) - return(TRUE) - } - return(FALSE) - }, - logical(1) - ) - if (any(notes_result)) { - stop("NOTEs on the blocklist were found. Please refer to the 'Run R CMD check ๐Ÿ' step above.") - } - } - } - shell: Rscript {0} - - - name: Install R package ๐Ÿšง - run: | - if [ "${{ inputs.skip-r-cmd-install }}" == "true" ] - then { - echo "Skipping R CMD INSTALL as 'skip-r-cmd-install' was set to 'true'" - exit 0 - } - fi - if [ "${{ inputs.additional-env-vars }}" != "" ] - then { - echo -e "${{ inputs.additional-env-vars }}" > /tmp/dotenv.env - export $(tr '\n' ' ' < /tmp/dotenv.env) - } - fi - R CMD INSTALL ${{ env.PKGBUILD }} - shell: bash - - - name: Rebuild R package ๐Ÿ— - if: > - (inputs.disable-unit-test-reports != 'true' || - startsWith(github.ref, 'refs/tags/v')) && - github.event_name != 'pull_request' - run: | - # Undo changes to DESCRIPTION and tests/testthat.R - git checkout DESCRIPTION - if [ -f "tests/testthat.R" ]; then - git checkout tests/testthat.R - fi - if [ "${{ inputs.additional-env-vars }}" != "" ] - then { - echo -e "${{ inputs.additional-env-vars }}" > /tmp/dotenv.env - export $(tr '\n' ' ' < /tmp/dotenv.env) - } - fi - R CMD build . - shell: bash - working-directory: ${{ github.event.repository.name }}/${{ inputs.package-subdirectory }} - - - name: Upload package build โคด - if: startsWith(github.ref, 'refs/tags/v') - uses: actions/upload-artifact@v3 - with: - path: ${{ github.event.repository.name }}/${{ inputs.package-subdirectory }}/${{ env.PKGBUILD }} - name: ${{ env.PKGBUILD }} - - publish-junit-html-report: - name: Publish JUnit HTML report ๐Ÿ“ฐ - runs-on: ubuntu-latest - needs: build-install-check - if: > - needs.build-install-check.outputs.publish-unit-test-html-report == 'true' - && github.event_name != 'pull_request' - # Only one job can publish to gh-pages branch concurrently. - concurrency: - group: ghpages - steps: - - name: Setup token ๐Ÿ”‘ - id: github-token - run: | - if [ "${{ secrets.REPO_GITHUB_TOKEN }}" == "" ]; then - echo "REPO_GITHUB_TOKEN is empty. Substituting it with GITHUB_TOKEN." - echo "token=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_OUTPUT - else - echo "Using REPO_GITHUB_TOKEN." - echo "token=${{ secrets.REPO_GITHUB_TOKEN }}" >> $GITHUB_OUTPUT - fi - shell: bash - - - name: Download JUnit HTML report as artifact โคต๏ธ - uses: actions/download-artifact@v3 - with: - name: unit-test-report - path: unit-test-report - - - name: Upload JUnit HTML report to GitHub pages ๐Ÿ—ž๏ธ - if: needs.build-install-check.outputs.multiversion-docs == 'true' - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ steps.github-token.outputs.token }} - publish_dir: ./unit-test-report - destination_dir: ${{ needs.build-install-check.outputs.current-branch-or-tag }}/unit-test-report - - - name: Upload JUnit HTML report to GitHub pages (latest-tag) ๐Ÿท๏ธ - if: > - needs.build-install-check.outputs.is-latest-tag == 'true' - && needs.build-install-check.outputs.multiversion-docs == 'true' - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ steps.github-token.outputs.token }} - publish_dir: ./unit-test-report - destination_dir: ${{ inputs.latest-tag-alt-name }}/unit-test-report - - - name: Upload JUnit HTML report to GitHub pages (release-candidate) ๐Ÿท๏ธ - if: > - needs.build-install-check.outputs.is-rc-tag == 'true' - && needs.build-install-check.outputs.multiversion-docs == 'true' - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ steps.github-token.outputs.token }} - publish_dir: ./unit-test-report - destination_dir: ${{ inputs.release-candidate-alt-name }}/unit-test-report - - - name: Upload JUnit HTML report to GitHub pages (non-multiversion) ๐Ÿ—ž๏ธ - if: needs.build-install-check.outputs.multiversion-docs == 'false' - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ steps.github-token.outputs.token }} - publish_dir: ./unit-test-report - destination_dir: unit-test-report - - upload-release-assets: - name: Upload build tar.gz - needs: build-install-check - runs-on: ubuntu-latest - if: > - startsWith(github.ref, 'refs/tags/v') - && (!contains(github.event.commits[0].message, '[skip r-cmd]')) - && github.event.pull_request.draft == false - steps: - - name: Checkout repo ๐Ÿ›Ž - uses: actions/checkout@v3 - - - name: Get package build filename ๐Ÿ“ฆ - run: | - echo "PKGBUILD=$(echo $(awk -F: '/Package:/{gsub(/[ ]+/,"") ; print $2}' DESCRIPTION)_"\ - "$(awk -F: '/Version:/{gsub(/[ ]+/,"") ; print $2}' DESCRIPTION).tar.gz)" >> $GITHUB_ENV - shell: bash - - - name: Download artifact โฌ - uses: actions/download-artifact@v3 - with: - name: ${{ env.PKGBUILD }} - - - name: Check if release exists - id: check-if-release-exists - uses: insightsengineering/release-existence-action@v1 - - - name: Upload binaries to release ๐Ÿ”ผ - if: >- - steps.check-if-release-exists.outputs.release-exists == 'true' - uses: svenstaro/upload-release-action@v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: ${{ env.PKGBUILD }} - asset_name: ${{ env.PKGBUILD }} - tag: ${{ github.ref }} - overwrite: true diff --git a/.github/workflows/common.yml b/.github/workflows/common.yml new file mode 100644 index 0000000..b793dd3 --- /dev/null +++ b/.github/workflows/common.yml @@ -0,0 +1,135 @@ +--- +# Source: https://github.com/pharmaverse/admiralci +# Common workflows designed for Admiral +# but can be easily used by any other R package +name: admiral CI/CD Workflows + +on: + # 'workflow_dispatch' gives you the ability + # to run this workflow on demand, anytime + workflow_dispatch: + # 'push' events are triggered when commits + # are pushed to one of these branches + push: + tags: + - "v*" + branches: + - main + # 'pull_request' events are triggered when PRs are + # created against one of these target branches. + pull_request: + branches: + - main + # 'release' events are triggered when... + # you guessed it - when releases are made. + release: + types: [published] + +# Docs on concurrency: +# https://docs.github.com/en/actions/using-jobs/using-concurrency +concurrency: + group: admiral-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + R_VERSION: "release" + +jobs: + get_r_version: + name: Get R version + runs-on: ubuntu-latest + outputs: + r-version: ${{ steps.get_r_version.outputs.R_VERSION }} + steps: + - name: Get R Version for Downstream Container Jobs + id: get_r_version + run: echo "R_VERSION=$R_VERSION" >> $GITHUB_OUTPUT + shell: bash + style: + name: Code Style + uses: pharmaverse/admiralci/.github/workflows/style.yml@main + if: github.event_name == 'pull_request' + needs: get_r_version + with: + r-version: "${{ needs.get_r_version.outputs.r-version }}" + spellcheck: + name: Spelling + uses: pharmaverse/admiralci/.github/workflows/spellcheck.yml@main + if: github.event_name == 'pull_request' + needs: get_r_version + with: + r-version: "${{ needs.get_r_version.outputs.r-version }}" + readme: + name: Render README + uses: pharmaverse/admiralci/.github/workflows/readme-render.yml@main + if: github.event_name == 'push' + needs: get_r_version + with: + r-version: "${{ needs.get_r_version.outputs.r-version }}" + validation: + name: Validation + uses: pharmaverse/admiralci/.github/workflows/r-pkg-validation.yml@main + if: github.event_name == 'release' + needs: get_r_version + with: + r-version: "${{ needs.get_r_version.outputs.r-version }}" + check: + name: Check + uses: pharmaverse/admiralci/.github/workflows/r-cmd-check.yml@main + with: + error-on: warning + if: github.event_name == 'pull_request' + docs: + name: Documentation + uses: pharmaverse/admiralci/.github/workflows/pkgdown.yml@main + if: github.event_name == 'push' || startsWith(github.ref, 'refs/tags/v') + needs: get_r_version + with: + r-version: "${{ needs.get_r_version.outputs.r-version }}" + skip-multiversion-docs: true + secrets: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + linter: + name: Lint + uses: pharmaverse/admiralci/.github/workflows/lintr.yml@main + needs: get_r_version + if: github.event_name == 'pull_request' + with: + r-version: "${{ needs.get_r_version.outputs.r-version }}" + links: + name: Links + uses: pharmaverse/admiralci/.github/workflows/links.yml@main + if: github.event_name == 'pull_request' + coverage: + name: Code Coverage + uses: pharmaverse/admiralci/.github/workflows/code-coverage.yml@main + if: > + github.event_name != 'release' + needs: get_r_version + with: + r-version: "${{ needs.get_r_version.outputs.r-version }}" + # Whether to skip code coverage badge creation + # Setting to 'false' will require you to create + # an orphan branch called 'badges' in your repository + skip-coverage-badges: false + man-pages: + name: Man Pages + uses: pharmaverse/admiralci/.github/workflows/man-pages.yml@main + if: github.event_name == 'pull_request' + needs: get_r_version + with: + r-version: "${{ needs.get_r_version.outputs.r-version }}" + templates: + name: Check Templates + uses: pharmaverse/admiralci/.github/workflows/check-templates.yml@main + secrets: inherit + if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' + needs: get_r_version + with: + r-version: "${{ needs.get_r_version.outputs.r-version }}" + vbump: + name: Version Bump ๐Ÿคœ๐Ÿค› + if: github.event_name == 'push' + uses: insightsengineering/r.pkg.template/.github/workflows/version-bump.yaml@main + secrets: + REPO_GITHUB_TOKEN: ${{ secrets.PHARMAVERSE_BOT }} diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml deleted file mode 100644 index ed7650c..0000000 --- a/.github/workflows/pkgdown.yaml +++ /dev/null @@ -1,48 +0,0 @@ -# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples -# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help -on: - push: - branches: [main, master] - pull_request: - branches: [main, master] - release: - types: [published] - workflow_dispatch: - -name: pkgdown - -jobs: - pkgdown: - runs-on: ubuntu-latest - # Only restrict concurrency for non-PR jobs - concurrency: - group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} - env: - GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - permissions: - contents: write - steps: - - uses: actions/checkout@v3 - - - uses: r-lib/actions/setup-pandoc@v2 - - - uses: r-lib/actions/setup-r@v2 - with: - use-public-rspm: true - - - uses: r-lib/actions/setup-r-dependencies@v2 - with: - extra-packages: any::pkgdown, local::. - needs: website - - - name: Build site - run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) - shell: Rscript {0} - - - name: Deploy to GitHub pages ๐Ÿš€ - if: github.event_name != 'pull_request' - uses: JamesIves/github-pages-deploy-action@v4.4.1 - with: - clean: false - branch: gh-pages - folder: docs diff --git a/.github/workflows/spelling.yaml b/.github/workflows/spelling.yaml deleted file mode 100644 index 94a9a5a..0000000 --- a/.github/workflows/spelling.yaml +++ /dev/null @@ -1,120 +0,0 @@ ---- -name: Spelling ๐Ÿ†Ž - -on: - push: - branches: - - main - pull_request: - types: - - opened - - synchronize - - reopened - - ready_for_review - branches: - - main - workflow_dispatch: - workflow_call: - secrets: - REPO_GITHUB_TOKEN: - description: Github token with write access to the repo - required: false - inputs: - package-subdirectory: - description: Subdirectory in the repository, where the R package is located. - required: false - type: string - default: "." - exclude: - description: Comma separated list of files or folders to exclude from spellcheck. Accepts globs. - type: string - default: "inst/extdata/*" - required: false - -concurrency: - group: spelling-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - spelling: - name: Check spelling ๐Ÿ”  - runs-on: ubuntu-latest - if: > - !contains(github.event.commits[0].message, '[skip spelling]') - && github.event.pull_request.draft == false - container: - image: ghcr.io/insightsengineering/rstudio:latest - - steps: - - name: Setup token ๐Ÿ”‘ - id: github-token - run: | - if [ "${{ secrets.REPO_GITHUB_TOKEN }}" == "" ]; then - echo "REPO_GITHUB_TOKEN is empty. Substituting it with GITHUB_TOKEN." - echo "token=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_OUTPUT - else - echo "Using REPO_GITHUB_TOKEN." - echo "token=${{ secrets.REPO_GITHUB_TOKEN }}" >> $GITHUB_OUTPUT - fi - shell: bash - - - name: Checkout Code ๐Ÿ›Ž - uses: actions/checkout@v3 - with: - token: ${{ steps.github-token.outputs.token }} - - - name: Normalize variables ๐Ÿ“ - run: | - package_subdirectory_input="${{ inputs.package-subdirectory }}" - echo "package_subdirectory=${package_subdirectory_input:-.}" >> $GITHUB_ENV - shell: bash - - - name: Run Spellcheck ๐Ÿ‘Ÿ - uses: insightsengineering/r-spellcheck-action@v2 - with: - exclude: ${{ inputs.exclude }} - path: ${{ env.package_subdirectory }} - - - name: Clean up WORDLIST ๐Ÿงผ - if: github.event_name == 'push' - run: | - x <- readLines('inst/WORDLIST') - file.remove('inst/WORDLIST') - spelling::update_wordlist(confirm = FALSE) - y <- readLines('inst/WORDLIST') - if (length(setdiff(y, x)) == 0 && length(setdiff(x, y)) > 0) { - message("Unnecessary entries on WORDLIST:") - message(cat(setdiff(x, y), sep='\n')) - } - shell: Rscript {0} - - - name: Checkout to main ๐Ÿ›Ž - if: github.event_name == 'push' - run: | - git config --global --add safe.directory $(pwd) - git fetch origin main - git checkout main - git pull origin main - - - name: Set file pattern to commit โš™๏ธ - if: github.event_name == 'push' - id: file-pattern - run: | - if [[ "${{ inputs.package-subdirectory }}" == "." ]]; then - FILE_PATTERN="inst/WORDLIST" - else - FILE_PATTERN="${{ inputs.package-subdirectory }}/inst/WORDLIST" - fi - echo "file-pattern=$FILE_PATTERN" >> $GITHUB_OUTPUT - shell: bash - - - name: Commit and push changes ๐Ÿ“Œ - if: github.event_name == 'push' - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: "[skip actions] Update WORDLIST" - file_pattern: "${{ steps.file-pattern.outputs.file-pattern }}" - commit_user_name: insights-engineering-bot - commit_user_email: >- - 68416928+insights-engineering-bot@users.noreply.github.com - continue-on-error: true diff --git a/.github/workflows/version-bump.yaml b/.github/workflows/version-bump.yaml deleted file mode 100644 index 9e3a73e..0000000 --- a/.github/workflows/version-bump.yaml +++ /dev/null @@ -1,161 +0,0 @@ ---- -name: Version bump โฌ† - -on: - push: - branches: - - main - workflow_dispatch: - workflow_call: - secrets: - REPO_GITHUB_TOKEN: - description: Github token with write access to the repo - required: false - inputs: - disable-precommit-autoupdate: - description: Disable precommit autoupdate - required: false - default: false - type: boolean - vbump-after-release: - description: Whether the vbump workflow is running after a release has been published - required: false - default: false - type: boolean - package-subdirectory: - description: Subdirectory in the repository, where the R package is located. - required: false - type: string - default: "." - -concurrency: - group: vbump-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - vbump: - name: Bump version โคด - runs-on: ubuntu-latest - if: | - !(contains(github.event.commits[0].message, '[skip vbump]') || - contains(github.event.head_commit.message, '[skip vbump]') - ) - container: - image: docker.io/rocker/tidyverse:4.3.1 - - steps: - - name: Setup token ๐Ÿ”‘ - id: github-token - run: | - if [ "${{ secrets.REPO_GITHUB_TOKEN }}" == "" ]; then - echo "REPO_GITHUB_TOKEN is empty. Substituting it with GITHUB_TOKEN." - echo "token=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_OUTPUT - else - echo "Using REPO_GITHUB_TOKEN." - echo "token=${{ secrets.REPO_GITHUB_TOKEN }}" >> $GITHUB_OUTPUT - fi - shell: bash - - - name: Checkout repo ๐Ÿ›Ž - uses: actions/checkout@v3 - with: - token: ${{ steps.github-token.outputs.token }} - - - name: Bump version in DESCRIPTION ๐Ÿ“œ - if: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/main') || inputs.vbump-after-release == true }} - run: desc::desc_bump_version("dev", normalize = TRUE) - shell: Rscript {0} - working-directory: ${{ inputs.package-subdirectory }} - - - name: Update Date field ๐Ÿ“… - run: if (desc::desc_has_fields("Date")) desc::desc_set("Date", Sys.Date()) - shell: Rscript {0} - working-directory: ${{ inputs.package-subdirectory }} - - - name: Bump version in NEWS.md ๐Ÿ“ฐ - run: | - if [ -f NEWS.md ] - then { - git config --global --add safe.directory $(pwd) - DESC_VERSION=$(R --slave -e 'cat(paste(desc::desc_get_version()))') - NEWS_VERSION=$(awk '/^#+ /{print $3,$4; exit}' NEWS.md) - FIRST_NEWS_LINE=$(head -1 NEWS.md) - if [ "${{ inputs.vbump-after-release }}" == "true" ]; then - # Add a new section with the released version that will be vbumped below. - printf "$FIRST_NEWS_LINE\n\n" | cat - NEWS.md > temp-news.md - mv temp-news.md NEWS.md - fi - # Replace only the first occurence of $NEWS_VERSION, - # but only if it's not already set to (development version) - if [ "$NEWS_VERSION" != "(development version)" ] - then { - sed -i "0,/$NEWS_VERSION/s/$NEWS_VERSION/$DESC_VERSION/" NEWS.md - } - fi - NEWS_VERSION=$(awk '/^#+ /{print $3,$4; exit}' NEWS.md) - echo "Updated NEWS.md version: $NEWS_VERSION" - if (test $DESC_VERSION != $NEWS_VERSION ); then - echo "๐Ÿ™ˆ Updated NEWS.md and DESCRIPTION have different versions!" - echo "Please ensure that the versions in the NEWS.md and DESCRIPTION are the same ๐Ÿ™" - exit 1 - fi - echo "NEW_PKG_VERSION=${DESC_VERSION}" >> $GITHUB_ENV - } - fi - shell: bash - working-directory: ${{ inputs.package-subdirectory }} - - - name: Check if a pre-commit config exists - id: precommit-config-exists - uses: andstor/file-existence-action@v2 - with: - files: ".pre-commit-config.yaml" - - - name: Setup Python ๐Ÿ - if: | - inputs.disable-precommit-autoupdate != 'true' && - steps.precommit-config-exists.outputs.files_exists == 'true' - uses: actions/setup-python@v4 - with: - python-version: '3.11' - - - name: Precommit autoupdate ๐Ÿ…ฟ๏ธ - if: | - inputs.disable-precommit-autoupdate != 'true' && - steps.precommit-config-exists.outputs.files_exists == 'true' - run: | - git config --global --add safe.directory $(pwd) - python -m pip -q install pre-commit - pre-commit autoupdate - - - name: Checkout to main ๐Ÿ›Ž - if: ${{ inputs.vbump-after-release == true }} - run: | - git fetch origin main - git checkout main - git pull origin main - - - name: Set file pattern to commit โš™๏ธ - id: file-pattern - run: | - if [[ "${{ inputs.package-subdirectory }}" == "." || "${{ inputs.package-subdirectory }}" == "" ]]; then - FILE_PATTERN="NEWS.md DESCRIPTION" - else - FILE_PATTERN="${{ inputs.package-subdirectory }}/NEWS.md ${{ inputs.package-subdirectory }}/DESCRIPTION" - fi - if [[ '${{ steps.precommit-config-exists.outputs.files_exists }}' == 'true' ]]; then - FILE_PATTERN="$FILE_PATTERN .pre-commit-config.yaml" - fi - echo "file-pattern=$FILE_PATTERN" >> $GITHUB_OUTPUT - shell: bash - - - name: Commit and push changes ๐Ÿ“Œ - if: ${{ env.NEW_PKG_VERSION }} - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: "[skip actions] Bump version to ${{ env.NEW_PKG_VERSION }}" - file_pattern: "${{ steps.file-pattern.outputs.file-pattern }}" - commit_user_name: insights-engineering-bot - commit_user_email: >- - 68416928+insights-engineering-bot@users.noreply.github.com - continue-on-error: true diff --git a/.lintr b/.lintr new file mode 100644 index 0000000..6e19e74 --- /dev/null +++ b/.lintr @@ -0,0 +1,6 @@ +linters: linters_with_defaults( + line_length_linter(120), + object_usage_linter=NULL, + cyclocomp_linter(complexity_limit = 22), + undesirable_function_linter = undesirable_function_linter() + ) diff --git a/staged_dependencies.yaml b/staged_dependencies.yaml new file mode 100644 index 0000000..9fcbf88 --- /dev/null +++ b/staged_dependencies.yaml @@ -0,0 +1,16 @@ +--- +upstream_repos: +- repo: pharmaverse/admiral + host: https://github.com +- repo: pharmaverse/admiralonco + host: https://github.com +- repo: pharmaverse/admiralophtha + host: https://github.com +- repo: pharmaverse/admiralvaccine + host: https://github.com + +downstream_repos: + +current_repo: + repo: pharmaverse/admiraldiscovery + host: https://github.com