Skip to content

Commit b90d59b

Browse files
Merge pull request #171 from llnl/copilot/issue-170-spack-packages-references
Add weekly workflow to create issue when monitored spack-packages change
2 parents e694cc7 + 0a88d2d commit b90d59b

1 file changed

Lines changed: 244 additions & 0 deletions

File tree

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
name: Track spack-packages updates
2+
3+
on:
4+
pull_request:
5+
schedule:
6+
- cron: '17 6 * * 1'
7+
8+
permissions:
9+
contents: read
10+
issues: write
11+
12+
jobs:
13+
track:
14+
name: Track ${{ matrix.name }}
15+
runs-on: ubuntu-latest
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
include:
20+
# Watch a curated list of packages used by this env.
21+
- name: shared-ci
22+
spack_yaml: .gitlab/spack/envs/shared-ci/spack.yaml
23+
packages: |
24+
camp
25+
umpire
26+
raja
27+
raja-perf
28+
chai
29+
care
30+
caliper
31+
# Watch a specific upstream file.
32+
- name: cached-cmake
33+
spack_yaml: .gitlab/spack/envs/cached-cmake/spack.yaml
34+
files: |
35+
repos/spack_repo/builtin/build_systems/cached_cmake.py
36+
37+
env:
38+
SPACK_PACKAGES_REPO: https://github.com/spack/spack-packages.git
39+
SPACK_YAML: ${{ matrix.spack_yaml }}
40+
41+
steps:
42+
- name: Checkout repository
43+
uses: actions/checkout@v6
44+
45+
- name: Resolve current and latest spack-packages commits
46+
id: commits
47+
shell: bash
48+
run: |
49+
set -euo pipefail
50+
51+
# Read the upstream pin from spack.repos.builtin.commit.
52+
# Spack stores full 40-character SHA-1 hashes here.
53+
CURRENT_COMMIT=$(yq '.spack.repos.builtin.commit' "${SPACK_YAML}")
54+
if [[ -z "${CURRENT_COMMIT}" || "${CURRENT_COMMIT}" == "null" ]]; then
55+
echo "Missing .spack.repos.builtin.commit in ${SPACK_YAML}." >&2
56+
exit 1
57+
fi
58+
if ! [[ "${CURRENT_COMMIT}" =~ ^[0-9a-f]{40}$ ]]; then
59+
echo "Invalid commit hash in ${SPACK_YAML}: ${CURRENT_COMMIT}" >&2
60+
exit 1
61+
fi
62+
63+
SPACK_PACKAGES_DIR="${RUNNER_TEMP}/spack-packages"
64+
git clone "${SPACK_PACKAGES_REPO}" "${SPACK_PACKAGES_DIR}"
65+
66+
DEFAULT_BRANCH=$(git -C "${SPACK_PACKAGES_DIR}" remote show origin \
67+
| sed -n '/HEAD branch/s/.*: //p')
68+
if [[ -z "${DEFAULT_BRANCH}" ]]; then
69+
echo "Unable to determine default branch of ${SPACK_PACKAGES_REPO}." >&2
70+
exit 1
71+
fi
72+
LATEST_COMMIT=$(git -C "${SPACK_PACKAGES_DIR}" rev-parse "origin/${DEFAULT_BRANCH}")
73+
if [[ -z "${LATEST_COMMIT}" || ! "${LATEST_COMMIT}" =~ ^[0-9a-f]{40}$ ]]; then
74+
echo "Unable to resolve latest commit on ${DEFAULT_BRANCH}." >&2
75+
exit 1
76+
fi
77+
LATEST_COMMIT_SHORT=$(git -C "${SPACK_PACKAGES_DIR}" rev-parse --short=12 "${LATEST_COMMIT}")
78+
79+
echo "current_commit=${CURRENT_COMMIT}" >> "${GITHUB_OUTPUT}"
80+
echo "latest_commit=${LATEST_COMMIT}" >> "${GITHUB_OUTPUT}"
81+
echo "latest_commit_short=${LATEST_COMMIT_SHORT}" >> "${GITHUB_OUTPUT}"
82+
83+
echo "Current commit : ${CURRENT_COMMIT}"
84+
echo "Latest commit : ${LATEST_COMMIT}"
85+
86+
- name: Resolve watched paths
87+
id: paths
88+
shell: bash
89+
env:
90+
PACKAGES: ${{ matrix.packages }}
91+
FILES: ${{ matrix.files }}
92+
run: |
93+
set -euo pipefail
94+
95+
PACKAGES_PREFIX="repos/spack_repo/builtin/packages"
96+
WATCHED_PATHS_FILE="${RUNNER_TEMP}/watched_paths.txt"
97+
: > "${WATCHED_PATHS_FILE}"
98+
99+
# Each watched package becomes its upstream directory.
100+
# Spack maps hyphens to underscores (raja-perf -> raja_perf).
101+
while IFS= read -r PKG; do
102+
[[ -z "${PKG// /}" ]] && continue
103+
echo "${PACKAGES_PREFIX}/${PKG//-/_}" >> "${WATCHED_PATHS_FILE}"
104+
done <<< "${PACKAGES:-}"
105+
106+
# Literal files under spack-packages.
107+
while IFS= read -r FILE; do
108+
[[ -z "${FILE// /}" ]] && continue
109+
echo "${FILE}" >> "${WATCHED_PATHS_FILE}"
110+
done <<< "${FILES:-}"
111+
112+
if [[ ! -s "${WATCHED_PATHS_FILE}" ]]; then
113+
echo "Matrix entry declared neither packages nor files." >&2
114+
exit 1
115+
fi
116+
117+
echo "Watched paths:"
118+
cat "${WATCHED_PATHS_FILE}"
119+
120+
- name: Detect relevant upstream changes
121+
id: detect
122+
shell: bash
123+
env:
124+
CURRENT_COMMIT: ${{ steps.commits.outputs.current_commit }}
125+
LATEST_COMMIT: ${{ steps.commits.outputs.latest_commit }}
126+
run: |
127+
set -euo pipefail
128+
129+
SPACK_PACKAGES_DIR="${RUNNER_TEMP}/spack-packages"
130+
WATCHED_PATHS_FILE="${RUNNER_TEMP}/watched_paths.txt"
131+
CHANGED_PATHS_FILE="${RUNNER_TEMP}/changed-paths.txt"
132+
DIFF_FILE="${RUNNER_TEMP}/spack-packages-diff.txt"
133+
: > "${CHANGED_PATHS_FILE}"
134+
: > "${DIFF_FILE}"
135+
136+
if [[ "${CURRENT_COMMIT}" == "${LATEST_COMMIT}" ]]; then
137+
echo "should_update=false" >> "${GITHUB_OUTPUT}"
138+
echo "reason=already_up_to_date" >> "${GITHUB_OUTPUT}"
139+
exit 0
140+
fi
141+
142+
readarray -t WATCH < "${WATCHED_PATHS_FILE}"
143+
144+
if ! git -C "${SPACK_PACKAGES_DIR}" rev-parse --verify --quiet "${CURRENT_COMMIT}^{commit}" >/dev/null; then
145+
echo "Current commit ${CURRENT_COMMIT} not in upstream history; forcing update." >&2
146+
echo "should_update=true" >> "${GITHUB_OUTPUT}"
147+
echo "reason=current_commit_not_found" >> "${GITHUB_OUTPUT}"
148+
exit 0
149+
fi
150+
151+
CHANGED=$(git -C "${SPACK_PACKAGES_DIR}" diff --name-only \
152+
"${CURRENT_COMMIT}..${LATEST_COMMIT}" -- "${WATCH[@]}")
153+
if [[ -z "${CHANGED}" ]]; then
154+
echo "should_update=false" >> "${GITHUB_OUTPUT}"
155+
echo "reason=no_relevant_changes" >> "${GITHUB_OUTPUT}"
156+
exit 0
157+
fi
158+
159+
# Surface which watched paths actually changed (file or prefix match).
160+
TRACKED_AND_CHANGED=()
161+
for W in "${WATCH[@]}"; do
162+
while IFS= read -r C; do
163+
if [[ "${C}" == "${W}" || "${C}" == "${W}/"* ]]; then
164+
TRACKED_AND_CHANGED+=("${W}")
165+
echo "Detected relevant change in ${C}"
166+
break
167+
fi
168+
done <<< "${CHANGED}"
169+
done
170+
printf '%s\n' "${TRACKED_AND_CHANGED[@]}" > "${CHANGED_PATHS_FILE}"
171+
172+
git -C "${SPACK_PACKAGES_DIR}" diff "${CURRENT_COMMIT}..${LATEST_COMMIT}" \
173+
-- "${TRACKED_AND_CHANGED[@]}" > "${DIFF_FILE}"
174+
175+
echo "should_update=true" >> "${GITHUB_OUTPUT}"
176+
echo "reason=relevant_changes_found" >> "${GITHUB_OUTPUT}"
177+
178+
- name: Create issue
179+
if: steps.detect.outputs.should_update == 'true'
180+
env:
181+
GH_TOKEN: ${{ github.token }}
182+
CURRENT_COMMIT: ${{ steps.commits.outputs.current_commit }}
183+
LATEST_COMMIT: ${{ steps.commits.outputs.latest_commit }}
184+
LATEST_COMMIT_SHORT: ${{ steps.commits.outputs.latest_commit_short }}
185+
MATRIX_NAME: ${{ matrix.name }}
186+
run: |
187+
set -euo pipefail
188+
189+
CHANGED_PATHS_FILE="${RUNNER_TEMP}/changed-paths.txt"
190+
DIFF_FILE="${RUNNER_TEMP}/spack-packages-diff.txt"
191+
192+
if [[ ! -s "${CHANGED_PATHS_FILE}" ]]; then
193+
CHANGED_SECTION="_Could not determine changed paths (current commit not found in upstream history)._"
194+
else
195+
CHANGED_SECTION=""
196+
while IFS= read -r P; do
197+
CHANGED_SECTION+="- \`${P}\`"$'\n'
198+
done < "${CHANGED_PATHS_FILE}"
199+
fi
200+
201+
DIFF_CONTENT=$(cat "${DIFF_FILE}")
202+
if [[ -z "${DIFF_CONTENT}" ]]; then
203+
DIFF_SECTION="_Diff unavailable (current commit not found in upstream history)._"
204+
else
205+
# GitHub issue bodies are capped at 65536 characters; leave headroom
206+
# for surrounding markdown by truncating the diff earlier.
207+
MAX_DIFF_CHARS=60000
208+
if [[ "${#DIFF_CONTENT}" -gt "${MAX_DIFF_CHARS}" ]]; then
209+
DIFF_CONTENT="${DIFF_CONTENT:0:${MAX_DIFF_CHARS}}"$'\n'"... _(truncated, diff exceeds ${MAX_DIFF_CHARS} characters)_"
210+
fi
211+
DIFF_SECTION='```diff'$'\n'"${DIFF_CONTENT}"$'\n''```'
212+
fi
213+
214+
BODY_FILE="${RUNNER_TEMP}/issue-body.md"
215+
{
216+
echo "Automated weekly check detected relevant changes in \`spack/spack-packages\` for **${MATRIX_NAME}**."
217+
echo
218+
echo "## spack-packages references"
219+
echo
220+
echo "| | Commit |"
221+
echo "|---|---|"
222+
echo "| Current | \`${CURRENT_COMMIT}\` |"
223+
echo "| New | \`${LATEST_COMMIT}\` |"
224+
echo
225+
echo "## Changed paths"
226+
echo
227+
printf '%s' "${CHANGED_SECTION}"
228+
echo "## Diff"
229+
echo
230+
echo "Changes in \`spack/spack-packages\` from \`${CURRENT_COMMIT}\` to \`${LATEST_COMMIT}\`:"
231+
echo
232+
echo "${DIFF_SECTION}"
233+
} > "${BODY_FILE}"
234+
235+
gh issue create \
236+
--repo "${GITHUB_REPOSITORY}" \
237+
--title "[${MATRIX_NAME}] Update spack-packages reference to ${LATEST_COMMIT_SHORT}" \
238+
--body-file "${BODY_FILE}" \
239+
--label "automation"
240+
241+
- name: Log decision
242+
if: steps.detect.outputs.should_update != 'true'
243+
run: |
244+
echo "No issue created. Reason: ${{ steps.detect.outputs.reason }}"

0 commit comments

Comments
 (0)