Skip to content

Commit 0e6382a

Browse files
authored
Merge pull request #2 from auths-dev/dev-dogFooding
feat: add ci dogfooding
2 parents ab7453e + 57e304e commit 0e6382a

9 files changed

Lines changed: 238 additions & 29 deletions

File tree

.auths/allowed_signers

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# auths:managed — do not edit manually
2+
# Current identity (E6IXlw5-lnX88r3WZCt3u1qyN_Xlq7nQjtoTmuOfMIjI)
3+
z6MktnihicwetvA16FtHFynaJTn9eDZw51eizUEA1yGJCR4o@auths.local namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINT/yz5N7+GkzsRTHiyaueZbDy+fovwYUXyJ9uwD67tk
4+
# Previous identities
5+
z6MkipUqayiDZWM8j4YktjiEFZcCGw51YDVvLM7SrYPqLLyZ@auths.local namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEDeaOmUEcUjzChUedAsPyDO4mnjIa8j92fD9rGpuZd0
6+
z6MkhfnUUc2UJJ5C9sQQ7GvXmSbQJsdtNKV6HNYcQtTjc7xE@auths.local namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC/Ib83sxXogDnEVzLjFBkyC+DhP+cssbPzZAmQhB+Lz
7+
z6Mkio7WpoPy5EfeMJwhiZzePFch7xxuDeF9tpAf9q15nnHf@auths.local namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIECEt+3NgK9ws6M65lPSqW1FgWFjCYQVj1fsDedIvkRi

.github/workflows/ci.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,15 @@ jobs:
3232
echo "::error::dist/ is out of date. Run 'just build' (or 'npm run build') and commit the result."
3333
exit 1
3434
}
35+
36+
verify-commits:
37+
runs-on: ubuntu-latest
38+
steps:
39+
- uses: actions/checkout@v4
40+
with:
41+
fetch-depth: 0
42+
43+
- name: Verify commit signatures
44+
uses: ./
45+
with:
46+
fail-on-unsigned: true

dist/index.js

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39487,7 +39487,7 @@ const fs = __importStar(__nccwpck_require__(9896));
3948739487
const path = __importStar(__nccwpck_require__(6928));
3948839488
const os = __importStar(__nccwpck_require__(857));
3948939489
// Repository that hosts the public auths CLI releases
39490-
const CLI_RELEASE_REPO = 'auths-dev/auths-releases';
39490+
const CLI_RELEASE_REPO = 'auths-dev/auths';
3949139491
/**
3949239492
* Classify a verification error string into a structured failure type.
3949339493
*/
@@ -39529,11 +39529,11 @@ async function runPreflightChecks() {
3952939529
}
3953039530
// git command failed, not necessarily a problem
3953139531
}
39532-
// Check for ssh-keygen (required by auths verify-commit)
39532+
// Check for ssh-keygen (required by auths verify)
3953339533
try {
3953439534
const sshKeygenPath = await io.which('ssh-keygen', false);
3953539535
if (!sshKeygenPath) {
39536-
core.warning('ssh-keygen not found in PATH. The auths verify-commit command requires OpenSSH 8.0+.\n' +
39536+
core.warning('ssh-keygen not found in PATH. The auths verify command requires OpenSSH 8.0+.\n' +
3953739537
'GitHub-hosted runners include it by default. Self-hosted runners may need to install openssh-client.');
3953839538
}
3953939539
}
@@ -39542,7 +39542,7 @@ async function runPreflightChecks() {
3954239542
}
3954339543
}
3954439544
/**
39545-
* Verify commits in the given range using auths verify-commit
39545+
* Verify commits in the given range using auths verify
3954639546
*/
3954739547
async function verifyCommits(commitRange, options) {
3954839548
const { allowedSignersPath, identityBundlePath, skipMergeCommits } = options;
@@ -39551,7 +39551,15 @@ async function verifyCommits(commitRange, options) {
3955139551
// Validate inputs
3955239552
if (!useIdentityBundle && !fs.existsSync(allowedSignersPath)) {
3955339553
core.warning(`Allowed signers file not found: ${allowedSignersPath}`);
39554-
core.warning('Create one with: echo "user@example.com ssh-ed25519 AAAA..." > .auths/allowed_signers');
39554+
core.warning('To set up commit verification:\n' +
39555+
' 1. auths init # create identity\n' +
39556+
' 2. auths git allowed-signers -o .auths/allowed_signers # generate file\n' +
39557+
' 3. git add .auths/allowed_signers && git commit # commit it\n' +
39558+
'\n' +
39559+
'Or use an identity bundle for stateless CI (no file needed):\n' +
39560+
' auths id export-bundle --alias <ALIAS> --output bundle.json\n' +
39561+
'\n' +
39562+
'Docs: https://docs.auths.dev/cli/commands/advanced/#auths-git-allowed-signers');
3955539563
const commits = await getCommitsInRange(commitRange, skipMergeCommits);
3955639564
return commits.map(commit => ({
3955739565
commit,
@@ -39583,15 +39591,15 @@ async function verifyCommits(commitRange, options) {
3958339591
return mergeResults;
3958439592
}
3958539593
// Build CLI arguments
39586-
const cliArgs = ['verify-commit'];
39594+
const cliArgs = ['verify'];
3958739595
if (useIdentityBundle) {
3958839596
cliArgs.push('--identity-bundle', identityBundlePath);
3958939597
}
3959039598
else {
3959139599
cliArgs.push('--allowed-signers', allowedSignersPath);
3959239600
}
3959339601
cliArgs.push('--json', commitRange);
39594-
// Run auths verify-commit with --json flag
39602+
// Run auths verify with --json flag
3959539603
let stdout = '';
3959639604
let stderr = '';
3959739605
try {
@@ -39608,8 +39616,8 @@ async function verifyCommits(commitRange, options) {
3960839616
});
3960939617
}
3961039618
catch (error) {
39611-
core.debug(`auths verify-commit stderr: ${stderr}`);
39612-
core.debug(`auths verify-commit stdout: ${stdout}`);
39619+
core.debug(`auths verify stderr: ${stderr}`);
39620+
core.debug(`auths verify stdout: ${stdout}`);
3961339621
}
3961439622
// Parse JSON output
3961539623
let verifyResults = [];
@@ -39668,7 +39676,7 @@ async function verifyCommitsOneByOne(authsPath, commits, options) {
3966839676
for (const commit of commits) {
3966939677
let stdout = '';
3967039678
let exitCode = 0;
39671-
const cliArgs = ['verify-commit'];
39679+
const cliArgs = ['verify'];
3967239680
if (useIdentityBundle) {
3967339681
cliArgs.push('--identity-bundle', identityBundlePath);
3967439682
}

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/verifier.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export interface VerifyOptions {
2323
*/
2424
export declare function runPreflightChecks(): Promise<void>;
2525
/**
26-
* Verify commits in the given range using auths verify-commit
26+
* Verify commits in the given range using auths verify
2727
*/
2828
export declare function verifyCommits(commitRange: string, options: VerifyOptions): Promise<VerificationResult[]>;
2929
/**

docs/release.py

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Tag and push a GitHub release from the version in package.json.
4+
5+
Usage:
6+
python docs/release.py # dry-run (shows what would happen)
7+
python docs/release.py --push # create tag and push to trigger release workflow
8+
9+
What it does:
10+
1. Reads the version from package.json
11+
2. Checks that the npm package version has been bumped (if published)
12+
3. Checks that the git tag doesn't already exist on GitHub
13+
4. Ensures dist/ is built and committed
14+
5. Creates a git tag v{version} and pushes it to origin
15+
6. The release workflow creates a GitHub Release and updates the floating v1 tag
16+
17+
Requires:
18+
- python3 (no external dependencies)
19+
- git on PATH
20+
- network access to npmjs.org
21+
"""
22+
23+
import json
24+
import subprocess
25+
import sys
26+
import urllib.request
27+
from pathlib import Path
28+
29+
REPO_ROOT = Path(__file__).resolve().parents[1]
30+
PACKAGE_JSON = REPO_ROOT / "package.json"
31+
NPM_PACKAGE = "@auths/verify-action"
32+
GITHUB_REPO = "auths-dev/auths-verify-github-action"
33+
34+
35+
def get_package_version() -> str:
36+
data = json.loads(PACKAGE_JSON.read_text())
37+
version = data.get("version")
38+
if not version:
39+
print("ERROR: No version field in package.json", file=sys.stderr)
40+
sys.exit(1)
41+
return version
42+
43+
44+
def get_npm_version() -> str | None:
45+
url = f"https://registry.npmjs.org/{NPM_PACKAGE}/latest"
46+
req = urllib.request.Request(url, headers={"User-Agent": "auths-release-script/1.0"})
47+
try:
48+
with urllib.request.urlopen(req, timeout=10) as resp:
49+
data = json.loads(resp.read())
50+
return data.get("version")
51+
except Exception:
52+
return None
53+
54+
55+
def git(*args: str) -> str:
56+
result = subprocess.run(
57+
["git", *args],
58+
capture_output=True,
59+
text=True,
60+
cwd=REPO_ROOT,
61+
)
62+
if result.returncode != 0:
63+
print(f"ERROR: git {' '.join(args)} failed:\n{result.stderr.strip()}", file=sys.stderr)
64+
sys.exit(1)
65+
return result.stdout.strip()
66+
67+
68+
def local_tag_exists(tag: str) -> bool:
69+
result = subprocess.run(
70+
["git", "tag", "-l", tag],
71+
capture_output=True,
72+
text=True,
73+
cwd=REPO_ROOT,
74+
)
75+
return bool(result.stdout.strip())
76+
77+
78+
def remote_tag_exists(tag: str) -> bool:
79+
result = subprocess.run(
80+
["git", "ls-remote", "--tags", "origin", f"refs/tags/{tag}"],
81+
capture_output=True,
82+
text=True,
83+
cwd=REPO_ROOT,
84+
)
85+
return bool(result.stdout.strip())
86+
87+
88+
def delete_local_tag(tag: str) -> None:
89+
subprocess.run(
90+
["git", "tag", "-d", tag],
91+
capture_output=True,
92+
cwd=REPO_ROOT,
93+
)
94+
95+
96+
def main() -> None:
97+
push = "--push" in sys.argv
98+
99+
version = get_package_version()
100+
tag = f"v{version}"
101+
print(f"package.json version: {version}")
102+
print(f"Git tag: {tag}")
103+
104+
# Check npm for version collision (this action isn't published to npm,
105+
# but check anyway in case it ever is)
106+
published = get_npm_version()
107+
if published:
108+
print(f"npm version: {published}")
109+
if published == version:
110+
print(f"\nWARNING: Version {version} matches npm. Consider bumping.", file=sys.stderr)
111+
else:
112+
print("npm version: (not published)")
113+
114+
# GitHub is the source of truth for tags.
115+
if remote_tag_exists(tag):
116+
print(f"\nERROR: Git tag {tag} already exists on origin.", file=sys.stderr)
117+
print("Bump the version in package.json or delete the remote tag/release first.", file=sys.stderr)
118+
sys.exit(1)
119+
120+
if local_tag_exists(tag):
121+
print(f"Local tag {tag} exists but not on origin — deleting stale local tag.")
122+
delete_local_tag(tag)
123+
124+
# Check we're on a clean working tree
125+
status = git("status", "--porcelain")
126+
if status:
127+
print(f"\nERROR: Working tree is not clean:\n{status}", file=sys.stderr)
128+
print("Commit or stash changes before releasing.", file=sys.stderr)
129+
sys.exit(1)
130+
131+
# Check dist/ is committed (the release workflow validates this too)
132+
diff = subprocess.run(
133+
["git", "diff", "--name-only", "--", "dist/"],
134+
capture_output=True,
135+
text=True,
136+
cwd=REPO_ROOT,
137+
)
138+
if diff.stdout.strip():
139+
print(f"\nERROR: dist/ has uncommitted changes:\n{diff.stdout.strip()}", file=sys.stderr)
140+
print("Run `npm run build` and commit dist/ before releasing.", file=sys.stderr)
141+
sys.exit(1)
142+
143+
if not push:
144+
print(f"\nDry run: would create and push tag {tag}")
145+
print("Run with --push to execute.")
146+
return
147+
148+
print(f"\nCreating tag {tag}...", flush=True)
149+
result = subprocess.run(
150+
["git", "tag", "-a", tag, "-m", f"release: {version}"],
151+
cwd=REPO_ROOT,
152+
)
153+
if result.returncode != 0:
154+
print(f"\nERROR: git tag failed (exit {result.returncode})", file=sys.stderr)
155+
sys.exit(1)
156+
157+
print(f"Pushing tag {tag} to origin...", flush=True)
158+
result = subprocess.run(
159+
["git", "push", "origin", tag],
160+
cwd=REPO_ROOT,
161+
)
162+
if result.returncode != 0:
163+
print(f"\nERROR: git push failed (exit {result.returncode})", file=sys.stderr)
164+
sys.exit(1)
165+
166+
print(f"\nDone. Release workflow will run at:")
167+
print(f" https://github.com/{GITHUB_REPO}/actions")
168+
print(f"\nThe workflow will also update the floating v1 tag.")
169+
170+
171+
if __name__ == "__main__":
172+
main()

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@auths/verify-action",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "GitHub Action to verify commit signatures using Auths identity keys",
55
"main": "dist/index.js",
66
"scripts": {

src/__tests__/verifier.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ describe('getAuthsDownloadUrl', () => {
6060

6161
const url = getAuthsDownloadUrl('');
6262
expect(url).toBe(
63-
'https://github.com/auths-dev/auths-releases/releases/latest/download/auths-linux-x86_64.tar.gz'
63+
'https://github.com/auths-dev/auths/releases/latest/download/auths-linux-x86_64.tar.gz'
6464
);
6565
});
6666

@@ -70,7 +70,7 @@ describe('getAuthsDownloadUrl', () => {
7070

7171
const url = getAuthsDownloadUrl('');
7272
expect(url).toBe(
73-
'https://github.com/auths-dev/auths-releases/releases/latest/download/auths-macos-aarch64.tar.gz'
73+
'https://github.com/auths-dev/auths/releases/latest/download/auths-macos-aarch64.tar.gz'
7474
);
7575
});
7676

@@ -80,7 +80,7 @@ describe('getAuthsDownloadUrl', () => {
8080

8181
const url = getAuthsDownloadUrl('');
8282
expect(url).toBe(
83-
'https://github.com/auths-dev/auths-releases/releases/latest/download/auths-windows-x86_64.zip'
83+
'https://github.com/auths-dev/auths/releases/latest/download/auths-windows-x86_64.zip'
8484
);
8585
});
8686

@@ -90,7 +90,7 @@ describe('getAuthsDownloadUrl', () => {
9090

9191
const url = getAuthsDownloadUrl('0.5.0');
9292
expect(url).toBe(
93-
'https://github.com/auths-dev/auths-releases/releases/download/v0.5.0/auths-linux-x86_64.tar.gz'
93+
'https://github.com/auths-dev/auths/releases/download/v0.5.0/auths-linux-x86_64.tar.gz'
9494
);
9595
});
9696

@@ -116,7 +116,7 @@ describe('getAuthsDownloadUrl', () => {
116116

117117
const url = getAuthsDownloadUrl('');
118118
expect(url).toBe(
119-
'https://github.com/auths-dev/auths-releases/releases/latest/download/auths-macos-x86_64.tar.gz'
119+
'https://github.com/auths-dev/auths/releases/latest/download/auths-macos-x86_64.tar.gz'
120120
);
121121
});
122122

@@ -126,7 +126,7 @@ describe('getAuthsDownloadUrl', () => {
126126

127127
const url = getAuthsDownloadUrl('');
128128
expect(url).toBe(
129-
'https://github.com/auths-dev/auths-releases/releases/latest/download/auths-linux-aarch64.tar.gz'
129+
'https://github.com/auths-dev/auths/releases/latest/download/auths-linux-aarch64.tar.gz'
130130
);
131131
});
132132
});

0 commit comments

Comments
 (0)