Skip to content

Add comprehensive tests for utils.R and improve coverage for low-coverage files #36

Add comprehensive tests for utils.R and improve coverage for low-coverage files

Add comprehensive tests for utils.R and improve coverage for low-coverage files #36

# GitHub Copilot Environment Setup for lavaanExtra R Package
# This workflow sets up the development environment before Copilot starts working
# Based on: https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/customize-the-agent-environment
name: copilot-setup-steps
on:
workflow_dispatch:
# This workflow is automatically triggered by GitHub Copilot
# before the agent starts working in the repository
pull_request:
types: [opened, synchronize]
jobs:
copilot-setup-steps:
# Optional: only run on Copilot agent commits; remove this if you also want your own pushes to trigger it
if: >
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' &&
github.actor == 'github-copilot')
runs-on: ubuntu-latest
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
R_KEEP_PKG_SOURCE: yes
_R_CHECK_CRAN_INCOMING_: false
_R_CHECK_FORCE_SUGGESTS_: false
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Determine if R setup is needed
id: check_r_needed
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
echo "Checking if R environment setup is needed..."
R_NEEDED=true
# If this is a PR, use the PR's changed files (authoritative)
if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then
PR_NUMBER=$(jq -r '.number' < "$GITHUB_EVENT_PATH")
echo "PR number: $PR_NUMBER"
# Get changed files from the PR
FILES=$(curl -sS -H "Authorization: Bearer ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github+json" \
"${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}/files?per_page=100" \
| jq -r '.[].filename')
echo "Files in PR:"
echo "${FILES}"
# If ANY file is not in the "docs/config-only" set -> need R
# Allowed-only set (docs/config): tweak as you like
# Note: use a temporary file to avoid word-splitting issues
echo "${FILES}" > /tmp/pr_files.txt
if grep -E '\.(R|Rmd|Rd)$' /tmp/pr_files.txt >/dev/null || \
grep -E '^(R/|tests/|man/|vignettes/|src/)' /tmp/pr_files.txt >/dev/null; then
echo "Detected R-related paths in PR."
R_NEEDED=true
else
# Anything outside the allowed docs/config list? Then R is needed.
if grep -v -E '^(\.github/copilot-instructions\.md|\.github/workflows/|README\.md|\.gitignore|\.Rbuildignore|NEWS\.md|CONTRIBUTING\.md|LICENSE|CITATION\.cff|DESCRIPTION|cran-comments\.md|.+\.md$|.+\.ya?ml$)$' /tmp/pr_files.txt | grep -E '.' >/dev/null; then
echo "Changes go beyond docs/config-only."
R_NEEDED=true
else
echo "PR is docs/config-only."
R_NEEDED=false
fi
fi
else
# No PR context (Copilot run, pushes, etc.)
# Fallback: fast probe + light heuristics
echo "No PR context; using probe/heuristics."
# Example probe: if R already present and renv/cache present, skip
if command -v R >/dev/null 2>&1 && [ -f "renv.lock" ] && [ -d "~/.cache/R" ]; then
echo "R and cache present; likely no heavy setup needed."
R_NEEDED=false
else
# Last-commit heuristic (with full history available)
# Compare against the immediate parent only, to avoid "recent history" bias
if git rev-parse --verify HEAD~1 >/dev/null 2>&1; then
CHANGED=$(git diff --name-only HEAD~1...HEAD || true)
else
CHANGED=$(git ls-files) # first run in a new repo clone
fi
echo "${CHANGED}" > /tmp/changed.txt
if grep -E '\.(R|Rmd|Rd)$' /tmp/changed.txt >/dev/null || \
grep -E '^(R/|tests/|man/|vignettes/|src/)' /tmp/changed.txt >/dev/null; then
R_NEEDED=true
else
if grep -v -E '^(\.github/copilot-instructions\.md|\.github/workflows/|README\.md|\.gitignore|\.Rbuildignore|NEWS\.md|CONTRIBUTING\.md|LICENSE|CITATION\.cff|DESCRIPTION|cran-comments\.md|.+\.md$|.+\.ya?ml$)$' /tmp/changed.txt | grep -E '.' >/dev/null; then
R_NEEDED=true
else
R_NEEDED=false
fi
fi
fi
fi
echo "R_NEEDED=${R_NEEDED}" | tee -a "$GITHUB_OUTPUT"
echo ""
echo "=== FINAL DECISION ==="
if [ "$R_NEEDED" == "true" ]; then
echo "✓ R setup WILL be run"
echo "Reason: Analysis indicates R functionality is needed"
else
echo "✓ R setup WILL BE SKIPPED"
echo "Reason: Only documentation/config files detected"
fi
echo "Decision: R_NEEDED=$R_NEEDED"
- name: Setup R
if: steps.check_r_needed.outputs.R_NEEDED == 'true'
uses: r-lib/actions/setup-r@v2
with:
r-version: 'release'
use-public-rspm: true
- name: Setup pandoc (required for building vignettes and reprex)
if: steps.check_r_needed.outputs.R_NEEDED == 'true'
uses: r-lib/actions/setup-pandoc@v2
- name: Install system dependencies
if: steps.check_r_needed.outputs.R_NEEDED == 'true'
run: |
sudo apt-get update
sudo apt-get install -y \
libcurl4-openssl-dev \
libssl-dev \
libxml2-dev
- name: Setup R user library
if: steps.check_r_needed.outputs.R_NEEDED == 'true'
run: |
mkdir -p ~/R/library
echo 'R_LIBS_USER=~/R/library' >> ~/.Renviron
shell: bash
- name: Install R dependencies using pak
if: steps.check_r_needed.outputs.R_NEEDED == 'true'
uses: r-lib/actions/setup-r-dependencies@v2
with:
# Use stable pak for reliable dependency resolution
dependencies: '"hard"'
# Install core package dependencies and essential development tools
extra-packages: |
local::.
any::testthat
any::lintr
any::styler
any::roxygen2
any::devtools
any::reprex
any::knitr
any::rmarkdown
any::clipr
needs: check
# Let r-lib/actions handle caching automatically (more efficient than manual cache)
# NOTE: Suggested packages are NOT installed during setup to save time.
# Only core dependencies (Imports/Depends) and essential development tools are installed.
# Additional packages are installed on-demand based on specific PR requirements.
# See copilot-instructions.md for targeted installation guidance.
# NOTE: The local package (lavaanExtra) is automatically built and installed
# by setup-r-dependencies@v2 when using 'local::.', eliminating the need
# for manual build/install steps
- name: Verify R installation and packages
if: steps.check_r_needed.outputs.R_NEEDED == 'true'
run: |
cat("=== R Version ===\n")
print(R.version.string)
cat("\n=== Core Development Packages ===\n")
required_packages <- c("lavaan", "insight", "testthat", "lintr", "styler", "roxygen2", "reprex")
for (pkg in required_packages) {
if (requireNamespace(pkg, quietly = TRUE)) {
cat("✓", pkg, "- version", as.character(packageVersion(pkg)), "\n")
} else {
cat("✗", pkg, "- NOT AVAILABLE\n")
}
}
cat("\n=== lavaanExtra Package (auto-installed by setup-r-dependencies) ===\n")
if (requireNamespace("lavaanExtra", quietly = TRUE)) {
library(lavaanExtra)
cat("✓ lavaanExtra - version", as.character(packageVersion("lavaanExtra")), "\n")
} else {
cat("✗ lavaanExtra - NOT AVAILABLE\n")
}
shell: Rscript {0}
- name: Test core lavaanExtra functionality
if: steps.check_r_needed.outputs.R_NEEDED == 'true'
run: |
library(lavaanExtra)
cat("=== Testing Core Functions ===\n")
# Test basic data function
test_data <- data.frame(id = c(1,1,2,3), val = c(1,2,3,4))
duplicates <- extract_duplicates(test_data, id = "id")
cat("✓ extract_duplicates() works\n")
# Basic verification that package loads correctly
cat("✓ lavaanExtra package loads and core functions work\n")
cat("=== Core Function Tests Complete ===\n")
shell: Rscript {0}
- name: Display environment summary
run: |
echo "=== GitHub Copilot Environment Setup Complete ==="
echo ""
if [ "${{ steps.check_r_needed.outputs.R_NEEDED }}" == "true" ]; then
echo "✓ Optimized R development environment configured using pak:"
echo " - R and essential system dependencies installed"
echo " - Core package dependencies (Imports/Depends) installed via setup-r-dependencies"
echo " - lavaanExtra package automatically built and installed"
echo " - Essential development tools (lintr, styler, roxygen2, devtools)"
echo " - reprex dependencies ready (reprex + knitr + rmarkdown + pandoc)"
echo " - Efficient pak-based dependency resolution with automatic caching"
echo " - Suggested packages NOT installed (install as needed per PR)"
echo " - Minimal testing performed for faster setup"
echo ""
echo "The environment is ready for R package development work."
echo "Copilot can now build, test, lint, and create reproducible examples."
else
echo "✓ Minimal environment configured:"
echo " - Repository checked out and ready"
echo " - R setup SKIPPED - only documentation/config changes detected"
echo ""
if [ "${GITHUB_EVENT_NAME:-}" = "pull_request" ]; then
echo "Decision based on PR file analysis using GitHub API"
else
echo "Decision based on git diff analysis"
fi
echo "The environment is ready for documentation and configuration work."
echo "Perfect for version bumps, NEWS.md updates, and text editing tasks."
fi
shell: bash