Skip to content

Update DESCRIPTION to use latest 'easystats' dependencies #389

Update DESCRIPTION to use latest 'easystats' dependencies

Update DESCRIPTION to use latest 'easystats' dependencies #389

# GitHub Copilot Environment Setup for report 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]
permissions:
contents: read
pull-requests: read
issues: read
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: ${{ github.token }}
R_KEEP_PKG_SOURCE: yes
_R_CHECK_CRAN_INCOMING_: false
_R_CHECK_FORCE_SUGGESTS_: false
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Debug event/PR
run: |
echo "event_name=$GITHUB_EVENT_NAME"
echo "sha=$GITHUB_SHA"
echo "event payload:"
jq -r '. | {pull_request: .pull_request?.number, number: .number, action: .action}' "$GITHUB_EVENT_PATH"
- name: Wait for PR (and setup labels) up to 3 min
id: wait_pr
uses: actions/github-script@v9
with:
github-token: ${{ github.token }}
script: |
const {owner, repo} = context.repo
const sha = context.sha
const branch = process.env.GITHUB_REF_NAME
const REQUIRED = ['copilot-setup-full','copilot-setup-light']
const end = Date.now() + 3 * 60 * 1000
// 1) get PR number (works for dynamic + PR events)
let prNumber = context.payload.pull_request?.number || null
async function findPR() {
if (prNumber) return prNumber
// by commit
const byCommit = await github.request(
'GET /repos/{owner}/{repo}/commits/{sha}/pulls',
{ owner, repo, sha }
)
prNumber = byCommit.data[0]?.number || null
if (prNumber) return prNumber
// by head branch
if (branch) {
const byHead = await github.request(
'GET /repos/{owner}/{repo}/pulls',
{ owner, repo, state: 'open', head: `${owner}:${branch}` }
)
prNumber = byHead.data[0]?.number || null
}
return prNumber
}
while (!await findPR() && Date.now() < end) {
core.info('PR not created yet; waiting 5s…')
await new Promise(r => setTimeout(r, 5000))
}
if (!prNumber) { core.info('No PR found before timeout; continuing.'); return }
core.info(`Found PR #${prNumber}`)
core.setOutput('pr', String(prNumber))
// 2) (optional) wait briefly for one of the setup labels
const labelsEnd = Date.now() + 90_000
while (Date.now() < labelsEnd) {
const {data} = await github.rest.issues.listLabelsOnIssue({ owner, repo, issue_number: prNumber })
const names = data.map(l => l.name)
if (REQUIRED.some(r => names.includes(r))) {
core.info(`Setup labels present: [${names.join(', ')}]`)
core.setOutput('labels', names.join(','))
return
}
core.info(`Waiting for setup labels… current: [${names.join(', ')}]`)
await new Promise(r => setTimeout(r, 5000))
}
core.warning('Timed out waiting for setup labels; continuing anyway.')
- name: Determine if R setup is needed
id: check_r_needed
env:
API_TOKEN: ${{ github.token }}
PR_NUMBER_FROM_WAIT: ${{ steps.wait_pr.outputs.pr }}
run: |
set -euo pipefail
PR_NUMBER="${PR_NUMBER_FROM_WAIT:-}"
R_NEEDED=true
EXPLICIT_DECISION=""
# If we didn’t get one (very early run), try once more by commit
if [ -z "$PR_NUMBER" ]; then
PRS=$(
curl -sS --fail-with-body \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Accept: application/vnd.github+json" \
"${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/commits/${GITHUB_SHA}/pulls"
)
PR_NUMBER=$(echo "$PRS" | jq -r '.[0].number // empty')
fi
if [ -n "$PR_NUMBER" ]; then
# read labels from Issues endpoint
PR_LABELS=$(
curl -sS --fail-with-body \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Accept: application/vnd.github+json" \
"${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" \
| jq -r '.[].name' | tr '[:upper:]' '[:lower:]'
)
echo "PR labels: ${PR_LABELS:-<none>}"
if echo "$PR_LABELS" | grep -q '\bcopilot-setup-full\b'; then
EXPLICIT_DECISION=full; R_NEEDED=true
elif echo "$PR_LABELS" | grep -q '\bcopilot-setup-light\b'; then
EXPLICIT_DECISION=light; R_NEEDED=false
fi
fi
# …(keep your file-heuristics fallback if EXPLICIT_DECISION is empty)…
# Fallback heuristics when no explicit label decided
if [ -z "$EXPLICIT_DECISION" ]; then
if [ -n "$PR_NUMBER" ]; then
echo "Analyzing changed files in PR #$PR_NUMBER…"
FILES=$(
curl -sS --fail-with-body \
-H "Authorization: Bearer ${API_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}" > /tmp/pr_files.txt
else
echo "No PR; diffing against default branch."
DEFAULT_BRANCH=$(
curl -sS --fail-with-body \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Accept: application/vnd.github+json" \
"${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}" \
| jq -r '.default_branch'
)
git fetch --no-tags --depth=200 origin "$DEFAULT_BRANCH"
BASE=$(git merge-base HEAD "origin/${DEFAULT_BRANCH}")
git diff --name-only "${BASE}...HEAD" > /tmp/pr_files.txt
fi
echo "Files to examine:"; cat /tmp/pr_files.txt || true
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
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/pr_files.txt | grep -E '.' >/dev/null; then
R_NEEDED=true
else
R_NEEDED=false
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"
[ -n "$EXPLICIT_DECISION" ] && echo "Reason: explicit label ($EXPLICIT_DECISION)" || echo "Reason: heuristics"
else
echo "✓ R setup WILL BE SKIPPED"
[ -n "$EXPLICIT_DECISION" ] && echo "Reason: explicit label ($EXPLICIT_DECISION)" || echo "Reason: heuristics"
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::roxygen2
any::devtools
any::reprex
any::knitr
any::rmarkdown
any::clipr
any::cyclocomp
r-lib/lintr
r-lib/styler
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 (report) 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("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=== report Package (auto-installed by setup-r-dependencies) ===\n")
if (requireNamespace("report", quietly = TRUE)) {
library(report)
cat("✓ report - version", as.character(packageVersion("report")), "\n")
} else {
cat("✗ report - NOT AVAILABLE\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 " - report 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 ""
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 labels and/or 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