mirror of
https://github.com/kennethnym/aris.git
synced 2026-03-20 17:11:17 +00:00
Compare commits
1 Commits
feat/post-
...
feat/gpg-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
507ea29eb8
|
43
.claude/skills/gpg-commit-signing/SKILL.md
Normal file
43
.claude/skills/gpg-commit-signing/SKILL.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
name: gpg-commit-signing
|
||||||
|
description: Sign git commits with GPG in non-interactive environments. Use when committing code and the `GPG_PRIVATE_KEY_PASSPHRASE` environment variable is available. Triggers on "commit", "sign commit", "GPG", "git commit -S", or any git operation requiring signed commits.
|
||||||
|
---
|
||||||
|
|
||||||
|
# GPG Commit Signing
|
||||||
|
|
||||||
|
Sign commits in headless/non-interactive environments where `/dev/tty` is unavailable.
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. Check whether `GPG_PRIVATE_KEY_PASSPHRASE` is set:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
test -n "$GPG_PRIVATE_KEY_PASSPHRASE" && echo "available" || echo "not set"
|
||||||
|
```
|
||||||
|
|
||||||
|
If not set, skip signing — commit without `-S`.
|
||||||
|
|
||||||
|
2. Try a direct signed commit first — the environment may already have loopback pinentry configured:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git commit -S -m "message"
|
||||||
|
```
|
||||||
|
|
||||||
|
If this succeeds, no further steps are needed.
|
||||||
|
|
||||||
|
3. If step 2 fails with a `/dev/tty` error, use `--pinentry-mode loopback` via a wrapper script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
printf '#!/bin/sh\ngpg --batch --pinentry-mode loopback --passphrase "$GPG_PRIVATE_KEY_PASSPHRASE" "$@"\n' > /tmp/gpg-sign.sh
|
||||||
|
chmod +x /tmp/gpg-sign.sh
|
||||||
|
git -c gpg.program=/tmp/gpg-sign.sh commit -S -m "message"
|
||||||
|
rm /tmp/gpg-sign.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
This passes the passphrase directly to gpg on each signing invocation, bypassing the need for a configured gpg-agent.
|
||||||
|
|
||||||
|
## Anti-patterns
|
||||||
|
|
||||||
|
- Do not echo or log `GPG_PRIVATE_KEY_PASSPHRASE`.
|
||||||
|
- Do not commit without `-S` when the passphrase is available — the project expects signed commits.
|
||||||
|
- Do not leave wrapper scripts on disk after committing.
|
||||||
@@ -177,7 +177,7 @@ export class FeedEngine<TItems extends FeedItem = FeedItem> {
|
|||||||
items: processedItems,
|
items: processedItems,
|
||||||
groupedItems,
|
groupedItems,
|
||||||
errors: postProcessorErrors,
|
errors: postProcessorErrors,
|
||||||
} = await this.applyPostProcessors(items as TItems[], context, errors)
|
} = await this.applyPostProcessors(items as TItems[], errors)
|
||||||
|
|
||||||
const result: FeedResult<TItems> = {
|
const result: FeedResult<TItems> = {
|
||||||
context,
|
context,
|
||||||
@@ -294,7 +294,6 @@ export class FeedEngine<TItems extends FeedItem = FeedItem> {
|
|||||||
|
|
||||||
private async applyPostProcessors(
|
private async applyPostProcessors(
|
||||||
items: TItems[],
|
items: TItems[],
|
||||||
context: Context,
|
|
||||||
errors: SourceError[],
|
errors: SourceError[],
|
||||||
): Promise<{ items: TItems[]; groupedItems: ItemGroup[]; errors: SourceError[] }> {
|
): Promise<{ items: TItems[]; groupedItems: ItemGroup[]; errors: SourceError[] }> {
|
||||||
let currentItems = items
|
let currentItems = items
|
||||||
@@ -304,7 +303,7 @@ export class FeedEngine<TItems extends FeedItem = FeedItem> {
|
|||||||
for (const processor of this.postProcessors) {
|
for (const processor of this.postProcessors) {
|
||||||
const snapshot = currentItems
|
const snapshot = currentItems
|
||||||
try {
|
try {
|
||||||
const enhancement = await processor(currentItems, context)
|
const enhancement = await processor(currentItems)
|
||||||
|
|
||||||
if (enhancement.additionalItems?.length) {
|
if (enhancement.additionalItems?.length) {
|
||||||
// Post-processors operate on FeedItem[] without knowledge of TItems.
|
// Post-processors operate on FeedItem[] without knowledge of TItems.
|
||||||
@@ -400,7 +399,7 @@ export class FeedEngine<TItems extends FeedItem = FeedItem> {
|
|||||||
items: processedItems,
|
items: processedItems,
|
||||||
groupedItems,
|
groupedItems,
|
||||||
errors: postProcessorErrors,
|
errors: postProcessorErrors,
|
||||||
} = await this.applyPostProcessors(items as TItems[], this.context, errors)
|
} = await this.applyPostProcessors(items as TItems[], errors)
|
||||||
|
|
||||||
const result: FeedResult<TItems> = {
|
const result: FeedResult<TItems> = {
|
||||||
context: this.context,
|
context: this.context,
|
||||||
|
|||||||
@@ -333,10 +333,12 @@ describe("FeedPostProcessor", () => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const engine = new FeedEngine().register(source).registerPostProcessor(async () => {
|
const engine = new FeedEngine()
|
||||||
callCount++
|
.register(source)
|
||||||
return {}
|
.registerPostProcessor(async () => {
|
||||||
})
|
callCount++
|
||||||
|
return {}
|
||||||
|
})
|
||||||
|
|
||||||
engine.start()
|
engine.start()
|
||||||
|
|
||||||
@@ -375,10 +377,12 @@ describe("FeedPostProcessor", () => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const engine = new FeedEngine().register(source).registerPostProcessor(async () => {
|
const engine = new FeedEngine()
|
||||||
callCount++
|
.register(source)
|
||||||
return {}
|
.registerPostProcessor(async () => {
|
||||||
})
|
callCount++
|
||||||
|
return {}
|
||||||
|
})
|
||||||
|
|
||||||
engine.start()
|
engine.start()
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import type { Context } from "./context"
|
|
||||||
import type { FeedItem } from "./feed"
|
import type { FeedItem } from "./feed"
|
||||||
|
|
||||||
export interface ItemGroup {
|
export interface ItemGroup {
|
||||||
@@ -21,4 +20,4 @@ export interface FeedEnhancement {
|
|||||||
* A function that transforms feed items and produces enhancement directives.
|
* A function that transforms feed items and produces enhancement directives.
|
||||||
* Use named functions for meaningful error attribution.
|
* Use named functions for meaningful error attribution.
|
||||||
*/
|
*/
|
||||||
export type FeedPostProcessor = (items: FeedItem[], context: Context) => Promise<FeedEnhancement>
|
export type FeedPostProcessor = (items: FeedItem[]) => Promise<FeedEnhancement>
|
||||||
|
|||||||
Reference in New Issue
Block a user