obsidian-dev-skills 1.2.2 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -104,6 +104,8 @@ jobs:
|
|
|
104
104
|
runs-on: ubuntu-latest
|
|
105
105
|
steps:
|
|
106
106
|
- uses: actions/checkout@v4
|
|
107
|
+
with:
|
|
108
|
+
fetch-depth: 0
|
|
107
109
|
- uses: pnpm/action-setup@v4
|
|
108
110
|
- uses: actions/setup-node@v4
|
|
109
111
|
with:
|
|
@@ -123,14 +125,66 @@ jobs:
|
|
|
123
125
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
124
126
|
VERSION: ${{ steps.version.outputs.version }}
|
|
125
127
|
run: |
|
|
128
|
+
COMMIT_NOTES=$(git log -1 --pretty=format:%B)
|
|
129
|
+
PREV_TAG=$(git tag --sort=-creatordate --merged HEAD | grep -v "^${VERSION}$" | head -n 1 || true)
|
|
130
|
+
if [ -n "$PREV_TAG" ]; then
|
|
131
|
+
COMPARE="**Full Changelog**: https://github.com/${GITHUB_REPOSITORY}/compare/${PREV_TAG}...${VERSION}"
|
|
132
|
+
else
|
|
133
|
+
COMPARE="**Full Changelog**: https://github.com/${GITHUB_REPOSITORY}/commits/${VERSION}"
|
|
134
|
+
fi
|
|
135
|
+
NOTES=$(printf "%s\n\n---\n\n%s\n" "$COMMIT_NOTES" "$COMPARE")
|
|
126
136
|
gh release create "$VERSION" \
|
|
127
137
|
--title="$VERSION" \
|
|
128
|
-
--
|
|
138
|
+
--notes "$NOTES" \
|
|
129
139
|
main.js styles.css manifest.json
|
|
130
140
|
```
|
|
131
141
|
|
|
132
142
|
Then cut releases by pushing a tag (e.g. `git tag 0.1.0 && git push origin 0.1.0`) instead of uploading files manually. The workflow attaches the assets and registers the attestation, which the scorecard checks against the source repo for byte-for-byte reproducibility.
|
|
133
143
|
|
|
144
|
+
### Build verification failed (non-reproducible build)
|
|
145
|
+
|
|
146
|
+
> Build verification failed: the `main.js` built from source does not match the release artifact.
|
|
147
|
+
|
|
148
|
+
This appears even when attestation passes — attestation proves CI built the
|
|
149
|
+
asset; build verification proves the asset can be **reproduced** byte-for-byte
|
|
150
|
+
from the tagged source. The single most common cause is an **inline sourcemap**
|
|
151
|
+
in the production build.
|
|
152
|
+
|
|
153
|
+
`sourcemap: "inline"` in `esbuild.config.mjs` base64-embeds the build machine's
|
|
154
|
+
**absolute file paths** into `main.js`. GitHub Actions builds at
|
|
155
|
+
`/home/runner/work/<repo>/...`; the scorecard's reproducer builds at a
|
|
156
|
+
different path. Same source, byte-different `main.js` → verification fails. (It
|
|
157
|
+
also bloats the shipped file and leaks build paths.)
|
|
158
|
+
|
|
159
|
+
**Fix**: gate the sourcemap on build mode so production ships without one.
|
|
160
|
+
Compute the flag before `esbuild.context(...)` and reference it on the
|
|
161
|
+
`sourcemap` field:
|
|
162
|
+
|
|
163
|
+
```js
|
|
164
|
+
// Production builds must be reproducible. An inline sourcemap embeds the
|
|
165
|
+
// build machine's absolute file paths into main.js, so CI and the scorecard
|
|
166
|
+
// reproducer produce byte-different output. Ship production with no
|
|
167
|
+
// sourcemap; keep the inline sourcemap only for the dev/watch build.
|
|
168
|
+
const isProduction =
|
|
169
|
+
process.argv.slice(2).includes("build") ||
|
|
170
|
+
process.argv.slice(2).includes("production");
|
|
171
|
+
|
|
172
|
+
const context = await esbuild.context({
|
|
173
|
+
// ...
|
|
174
|
+
sourcemap: isProduction ? false : "inline",
|
|
175
|
+
// ...
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
(`pnpm build` runs `node esbuild.config.mjs production`; `pnpm dev` runs it
|
|
180
|
+
with no args, so dev/watch keeps the inline sourcemap for local debugging.)
|
|
181
|
+
|
|
182
|
+
Other reproducibility killers to rule out if the sourcemap is already gated:
|
|
183
|
+
commit `pnpm-lock.yaml` and use `pnpm install --frozen-lockfile` in CI (so the
|
|
184
|
+
dependency tree is identical), pin the CI Node version, and never hand-edit
|
|
185
|
+
`main.js` after building or upload a locally built asset — let the workflow
|
|
186
|
+
build and attach it.
|
|
187
|
+
|
|
134
188
|
### Duplicate CSS selectors
|
|
135
189
|
|
|
136
190
|
> Unexpected duplicate selector ".foo .bar", first used at line N.
|
|
@@ -43,6 +43,8 @@ jobs:
|
|
|
43
43
|
runs-on: ubuntu-latest
|
|
44
44
|
steps:
|
|
45
45
|
- uses: actions/checkout@v4
|
|
46
|
+
with:
|
|
47
|
+
fetch-depth: 0
|
|
46
48
|
- uses: pnpm/action-setup@v4
|
|
47
49
|
- uses: actions/setup-node@v4
|
|
48
50
|
with:
|
|
@@ -65,15 +67,25 @@ jobs:
|
|
|
65
67
|
if gh release view "$VERSION" >/dev/null 2>&1; then
|
|
66
68
|
gh release upload "$VERSION" main.js styles.css manifest.json --clobber
|
|
67
69
|
else
|
|
70
|
+
COMMIT_NOTES=$(git log -1 --pretty=format:%B)
|
|
71
|
+
PREV_TAG=$(git tag --sort=-creatordate --merged HEAD | grep -v "^${VERSION}$" | head -n 1 || true)
|
|
72
|
+
if [ -n "$PREV_TAG" ]; then
|
|
73
|
+
COMPARE="**Full Changelog**: https://github.com/${GITHUB_REPOSITORY}/compare/${PREV_TAG}...${VERSION}"
|
|
74
|
+
else
|
|
75
|
+
COMPARE="**Full Changelog**: https://github.com/${GITHUB_REPOSITORY}/commits/${VERSION}"
|
|
76
|
+
fi
|
|
77
|
+
NOTES=$(printf "%s\n\n---\n\n%s\n" "$COMMIT_NOTES" "$COMPARE")
|
|
68
78
|
gh release create "$VERSION" \
|
|
69
79
|
--title="$VERSION" \
|
|
70
|
-
--
|
|
80
|
+
--notes "$NOTES" \
|
|
71
81
|
main.js styles.css manifest.json
|
|
72
82
|
fi
|
|
73
83
|
```
|
|
74
84
|
|
|
75
85
|
**Why read the version from `manifest.json`**: the workflow runs from either a tag push (where `github.ref_name` is the tag) or a `workflow_dispatch` from a branch (where `github.ref_name` is the branch name, e.g. `master`). Using `github.ref_name` directly would title a manually-triggered release after the branch. Reading from `manifest.json` is consistent across both triggers and matches what Obsidian's plugin loader actually reads.
|
|
76
86
|
|
|
87
|
+
**Why build the release notes manually instead of `--generate-notes`**: `--generate-notes` produces an auto-changelog headed by a "What's Changed" PR list and a "Full Changelog" compare link. For plugins maintained by a single person without a PR workflow, that auto-generated body is usually just the compare link with no context. Reading the latest commit message gives the reader the actual "what changed and why" up front. The compare link is still appended underneath for the full diff. `fetch-depth: 0` is required so `git tag --merged HEAD` has the tag history to find the previous version.
|
|
88
|
+
|
|
77
89
|
Cut releases by pushing a tag (`git tag 0.1.0 && git push origin 0.1.0`). The workflow attaches the three required assets and registers the attestation. The scorecard's "Build verified" signal also fires once the workflow has run, because the attested artifacts can be reproduced byte-for-byte from source.
|
|
78
90
|
|
|
79
91
|
For the full set of scorecard signals and their fixes, see [scorecard-compliance.md](scorecard-compliance.md).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "obsidian-dev-skills",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"description": "Agent skills for Obsidian plugin and theme development, including community scorecard compliance, release workflow attestation, and dependency vulnerability hygiene.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"obsidian",
|