feat: local release workflow (signing + version sync); track updates.json; add .env.example
This commit is contained in:
		
					parent
					
						
							
								9d5a3e4224
							
						
					
				
			
			
				commit
				
					
						1c1f51a8b9
					
				
			
		
					 8 changed files with 158 additions and 3 deletions
				
			
		
							
								
								
									
										5
									
								
								.env.example
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.env.example
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
# Firefox AMO API credentials for web-ext signing
 | 
			
		||||
# Obtain from https://addons.mozilla.org/en-US/developers/addon/api/key/
 | 
			
		||||
AMO_JWT_ISSUER=your-amo-jwt-issuer
 | 
			
		||||
AMO_JWT_SECRET=your-amo-jwt-secret
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,4 +1,7 @@
 | 
			
		|||
dist/
 | 
			
		||||
.web-extension-id
 | 
			
		||||
node_modules/
 | 
			
		||||
 | 
			
		||||
.env
 | 
			
		||||
# Ignore all release artifacts except updates.json (tracked)
 | 
			
		||||
releases/*
 | 
			
		||||
!releases/updates.json
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -130,3 +130,20 @@ Issues and PRs are welcome. If proposing new filters or aria2 options, please in
 | 
			
		|||
## Disclaimer
 | 
			
		||||
 | 
			
		||||
This project is not affiliated with archive.org or aria2. Use responsibly and respect site terms of service.
 | 
			
		||||
 | 
			
		||||
## Release Workflow
 | 
			
		||||
 | 
			
		||||
- Stable ID: set a permanent add-on ID in `manifest.json` at `applications.gecko.id` (replace the `@example` value with your ID). If you self-host updates, set `applications.gecko.update_url` to your `updates.json` URL.
 | 
			
		||||
- Prepare (version bump + sync):
 | 
			
		||||
  - Patch: `npm run release:prepare:patch`
 | 
			
		||||
  - Minor: `npm run release:prepare:minor`
 | 
			
		||||
  - Major: `npm run release:prepare:major`
 | 
			
		||||
- Lint (Firefox): `npm run lint:fx`
 | 
			
		||||
- Dev ZIP: `npm run build:dev` → output in `dist/`
 | 
			
		||||
- Sign (unlisted):
 | 
			
		||||
  - Set environment secrets locally (do not commit): `AMO_JWT_ISSUER=... AMO_JWT_SECRET=...`
 | 
			
		||||
  - Run: `npm run release:sign`
 | 
			
		||||
  - Artifacts land in `releases/<version>/`
 | 
			
		||||
- Self-hosted updates: copy `releases/updates.example.json` to `releases/updates.json` and update with the new version and `update_link` pointing to your hosted `.xpi`.
 | 
			
		||||
 | 
			
		||||
Notes: Keep AMO secrets local. CI is optional. You can tag releases with `git tag vX.Y.Z` and push tags if desired.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,12 @@
 | 
			
		|||
  "name": "Archive.org Link Grabber",
 | 
			
		||||
  "version": "0.1.0",
 | 
			
		||||
  "description": "Filter and export archive.org /download links; copy or send to aria2 RPC.",
 | 
			
		||||
  "applications": {
 | 
			
		||||
    "gecko": {
 | 
			
		||||
      "id": "archive-org-link-grabber@example",
 | 
			
		||||
      "update_url": "https://example.com/updates.json"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "browser_action": {
 | 
			
		||||
    "default_title": "Archive.org Link Grabber",
 | 
			
		||||
    "default_popup": "src/popup/index.html"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								package.json
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								package.json
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -8,7 +8,15 @@
 | 
			
		|||
    "build": "web-ext build -o -a dist",
 | 
			
		||||
    "lint": "echo 'Add ESLint config to enable' && exit 0",
 | 
			
		||||
    "format": "echo 'Add Prettier config to enable' && exit 0",
 | 
			
		||||
    "test": "echo 'No tests yet' && exit 0"
 | 
			
		||||
    "test": "echo 'No tests yet' && exit 0",
 | 
			
		||||
    "lint:fx": "web-ext lint --source-dir .",
 | 
			
		||||
    "build:dev": "web-ext build -o -a dist",
 | 
			
		||||
    "release:prepare:patch": "npm version patch && node scripts/sync-version.js",
 | 
			
		||||
    "release:prepare:minor": "npm version minor && node scripts/sync-version.js",
 | 
			
		||||
    "release:prepare:major": "npm version major && node scripts/sync-version.js",
 | 
			
		||||
    "release:sign": "node scripts/release-sign.js"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "web-ext": "^8.3.0"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								releases/updates.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								releases/updates.json
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
{
 | 
			
		||||
  "addons": {
 | 
			
		||||
    "archive-org-link-grabber@example": {
 | 
			
		||||
      "updates": [
 | 
			
		||||
        {
 | 
			
		||||
          "version": "0.1.0",
 | 
			
		||||
          "update_link": "https://example.com/releases/0.1.0/archive-org-link-grabber-0.1.0.xpi",
 | 
			
		||||
          "applications": { "gecko": { "strict_min_version": "91.0" } }
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										63
									
								
								scripts/release-sign.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								scripts/release-sign.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,63 @@
 | 
			
		|||
#!/usr/bin/env node
 | 
			
		||||
/*
 | 
			
		||||
 * Signs an unlisted release via AMO using web-ext and outputs artifacts to releases/<version>/
 | 
			
		||||
 * Requires env: AMO_JWT_ISSUER, AMO_JWT_SECRET
 | 
			
		||||
 */
 | 
			
		||||
const fs = require('fs');
 | 
			
		||||
const path = require('path');
 | 
			
		||||
const { execSync } = require('child_process');
 | 
			
		||||
 | 
			
		||||
const root = path.join(__dirname, '..');
 | 
			
		||||
const pkg = require(path.join(root, 'package.json'));
 | 
			
		||||
const manifest = require(path.join(root, 'manifest.json'));
 | 
			
		||||
 | 
			
		||||
const issuer = process.env.AMO_JWT_ISSUER;
 | 
			
		||||
const secret = process.env.AMO_JWT_SECRET;
 | 
			
		||||
 | 
			
		||||
if (!issuer || !secret) {
 | 
			
		||||
  console.error('Missing AMO credentials. Set AMO_JWT_ISSUER and AMO_JWT_SECRET.');
 | 
			
		||||
  process.exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const addonId = manifest?.applications?.gecko?.id;
 | 
			
		||||
if (!addonId || addonId.includes('example')) {
 | 
			
		||||
  console.error('Invalid add-on id. Set applications.gecko.id in manifest.json to your stable ID.');
 | 
			
		||||
  process.exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const version = pkg.version;
 | 
			
		||||
if (!version) {
 | 
			
		||||
  console.error('package.json is missing version');
 | 
			
		||||
  process.exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const outDir = path.join(root, 'releases', version);
 | 
			
		||||
fs.mkdirSync(outDir, { recursive: true });
 | 
			
		||||
 | 
			
		||||
function run(cmd) {
 | 
			
		||||
  console.log(`> ${cmd}`);
 | 
			
		||||
  execSync(cmd, { stdio: 'inherit' });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
try {
 | 
			
		||||
  // Lint before signing
 | 
			
		||||
  run('npx --yes web-ext lint --source-dir .');
 | 
			
		||||
 | 
			
		||||
  // Sign (unlisted) and place artifacts in releases/<version>
 | 
			
		||||
  const signCmd = [
 | 
			
		||||
    'npx --yes web-ext sign',
 | 
			
		||||
    '--channel=unlisted',
 | 
			
		||||
    `--api-key="${issuer}"`,
 | 
			
		||||
    `--api-secret="${secret}"`,
 | 
			
		||||
    `--id="${addonId}"`,
 | 
			
		||||
    `--artifacts-dir "${outDir}"`,
 | 
			
		||||
  ].join(' ');
 | 
			
		||||
  run(signCmd);
 | 
			
		||||
 | 
			
		||||
  console.log('\nSigned artifacts written to:', outDir);
 | 
			
		||||
  console.log('Next: host .xpi and update updates.json (if self-hosting updates).');
 | 
			
		||||
} catch (err) {
 | 
			
		||||
  console.error('Release signing failed:', err.message);
 | 
			
		||||
  process.exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										39
									
								
								scripts/sync-version.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								scripts/sync-version.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
#!/usr/bin/env node
 | 
			
		||||
// Syncs manifest.json version with package.json version
 | 
			
		||||
const fs = require('fs');
 | 
			
		||||
const path = require('path');
 | 
			
		||||
 | 
			
		||||
const pkgPath = path.join(__dirname, '..', 'package.json');
 | 
			
		||||
const manifestPath = path.join(__dirname, '..', 'manifest.json');
 | 
			
		||||
 | 
			
		||||
function readJson(p) {
 | 
			
		||||
  return JSON.parse(fs.readFileSync(p, 'utf8'));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function writeJson(p, obj) {
 | 
			
		||||
  fs.writeFileSync(p, JSON.stringify(obj, null, 2) + '\n', 'utf8');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
try {
 | 
			
		||||
  const pkg = readJson(pkgPath);
 | 
			
		||||
  const manifest = readJson(manifestPath);
 | 
			
		||||
  const nextVersion = pkg.version;
 | 
			
		||||
 | 
			
		||||
  if (!nextVersion) {
 | 
			
		||||
    console.error('package.json is missing version');
 | 
			
		||||
    process.exit(1);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (manifest.version === nextVersion) {
 | 
			
		||||
    console.log(`manifest.json already at version ${nextVersion}`);
 | 
			
		||||
    process.exit(0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  manifest.version = nextVersion;
 | 
			
		||||
  writeJson(manifestPath, manifest);
 | 
			
		||||
  console.log(`Updated manifest.json version to ${nextVersion}`);
 | 
			
		||||
} catch (err) {
 | 
			
		||||
  console.error('Failed to sync versions:', err.message);
 | 
			
		||||
  process.exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue