feat(release): the keystores' passwords from Proton Pass too, and F-Droid's tools checked first
tool/with_signing_keys.sh reads each keystore's password from its item's hidden field "Password" and hands it to the release tool in its environment (<keystore variable>_PASSWORD), but for a dry run, which asks for no secret; the release tool takes a secret from there where it is set, else asks as before (the Forgejo token from HALKYON_FORGEJO_TOKEN). Typing them guarded nothing the Pass session didn't already open. The release tool checks fdroid, rsync, curl and jq with the other tools, so a dry run says when one is missing, rather than the F-Droid script after the passwords. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
50c0d28194
commit
7aa8ec7304
2 changed files with 79 additions and 9 deletions
|
|
@ -299,7 +299,10 @@ final class Releaser({
|
|||
}
|
||||
|
||||
_step('Asking for the secrets');
|
||||
var password = _secret('Password of $keystore: ');
|
||||
var password = _secret(
|
||||
'Password of $keystore: ',
|
||||
variable: '${app.android.keystoreVariable}_PASSWORD',
|
||||
);
|
||||
final keyCertificate = await _keyCertificate(
|
||||
tools.keytool,
|
||||
keystore,
|
||||
|
|
@ -319,13 +322,17 @@ final class Releaser({
|
|||
if (app.fdroid case final fdroid?) {
|
||||
fdroidEnvironment['HALKYON_FDROID_KEYSTORE_PASSWORD'] = _secret(
|
||||
"Password of the F-Droid repository's key: ",
|
||||
variable: 'HALKYON_FDROID_KEYSTORE_PASSWORD',
|
||||
);
|
||||
await _run(fdroid.script, ['--check'], environment: fdroidEnvironment);
|
||||
}
|
||||
final forgejo = _Forgejo(
|
||||
app.forgejo,
|
||||
app.repository,
|
||||
_secret('Forgejo token for ${app.forgejo} (write:repository): '),
|
||||
_secret(
|
||||
'Forgejo token for ${app.forgejo} (write:repository): ',
|
||||
variable: 'HALKYON_FORGEJO_TOKEN',
|
||||
),
|
||||
);
|
||||
try {
|
||||
await forgejo.checkAccess();
|
||||
|
|
@ -835,6 +842,18 @@ final class Releaser({
|
|||
_refuse('No JDK found (java, keytool).');
|
||||
}
|
||||
_environment['PATH'] = '$jdk:${_environment['PATH'] ?? ''}';
|
||||
// What the F-Droid repository's script needs, said before any secret
|
||||
// is asked for, and by the dry run.
|
||||
if (app.fdroid != null) {
|
||||
for (final tool in ['fdroid', 'rsync', 'curl', 'jq']) {
|
||||
if (_which(tool) == null) {
|
||||
_refuse(
|
||||
'$tool is missing, which ${app.fdroid!.script} needs'
|
||||
'${tool == 'fdroid' ? ' (pipx install fdroidserver==2.4.5)' : ''}.',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Asked only where snapcraft is there: without, the release was
|
||||
// refused above, and the dry run goes on to say what else it would.
|
||||
if (app.snap?.storeChannel case final channel?
|
||||
|
|
@ -1023,8 +1042,15 @@ final class Releaser({
|
|||
|
||||
void _step(String name) => stdout.writeln('▸ $name');
|
||||
|
||||
/// Asks for a secret on the terminal, without echoing it.
|
||||
String _secret(String prompt) {
|
||||
/// A secret: from the environment's [variable] where it holds one (as
|
||||
/// `tool/with_signing_keys.sh` hands the keystores' passwords over from
|
||||
/// Proton Pass), else asked for on the terminal, without echoing it.
|
||||
String _secret(String prompt, {required String variable}) {
|
||||
if (Platform.environment[variable] case final secret?
|
||||
when secret.isNotEmpty) {
|
||||
stdout.writeln('$prompt(from $variable)');
|
||||
return secret;
|
||||
}
|
||||
if (!stdin.hasTerminal) {
|
||||
throw const ReleaseFailure('Secrets are asked for on a terminal.');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,16 @@
|
|||
# kept (vault "Infra · Signing"): the app's Android keystore and the F-Droid index's,
|
||||
# each a note's attachment, downloaded into a folder in memory ($XDG_RUNTIME_DIR, a
|
||||
# tmpfs only the own user reads), handed to the release tool by the variables it reads
|
||||
# their paths from, and removed however the run ends. The keystores' passwords stay in
|
||||
# Pass: the release tool asks for them, as ever.
|
||||
# their paths from, and removed however the run ends. Their passwords, each item's hidden
|
||||
# field "Password", go to it in its environment (<keystore variable>_PASSWORD), so it
|
||||
# asks for none; a dry run asks for no secret, and gets none.
|
||||
#
|
||||
# tool/with_signing_keys.sh <app> [release.dart's arguments]
|
||||
# tool/with_signing_keys.sh train minor --dry-run
|
||||
#
|
||||
# Needs pass-cli, logged in (pass-cli login), and jq. Reads of the items take only their
|
||||
# IDs and their attachments' names, never a field.
|
||||
# Needs pass-cli, logged in (pass-cli login), and jq. Reads of the items take their IDs,
|
||||
# their attachments' names and, but for a dry run, the field "Password", which goes
|
||||
# nowhere but into the release tool's environment.
|
||||
set -euo pipefail
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
|
||||
|
|
@ -61,12 +63,33 @@ fetch() {
|
|||
[ -s "$to" ] || fail "The attachment $name of \"$item\" came empty."
|
||||
}
|
||||
|
||||
# The hidden field "Password" of the item titled $1.
|
||||
password() {
|
||||
local item="$1" value
|
||||
value=$(pass-cli item view --vault-name "$vault" --item-title "$item" --output json |
|
||||
jq -r '.item.content.extra_fields[]? | select(.name == "Password") | .content.Hidden // empty') ||
|
||||
fail "Can't read the item \"$item\" in $vault (pass-cli login?)."
|
||||
[ -n "$value" ] || fail "The item \"$item\" in $vault has no field Password."
|
||||
printf '%s' "$value"
|
||||
}
|
||||
|
||||
echo "▸ Fetching the signing keys from $vault"
|
||||
fetch "$app_item" android-release.p12 "$keys/android-release.p12"
|
||||
fetch "$fdroid_item" fdroid-index.p12 "$keys/fdroid-index.p12"
|
||||
|
||||
export "$app_variable=$keys/android-release.p12"
|
||||
export HALKYON_FDROID_KEYSTORE="$keys/fdroid-index.p12"
|
||||
dry_run=false
|
||||
for argument in "$@"; do
|
||||
[ "$argument" = --dry-run ] && dry_run=true
|
||||
done
|
||||
if ! $dry_run; then
|
||||
app_password=$(password "$app_item")
|
||||
fdroid_password=$(password "$fdroid_item")
|
||||
export "${app_variable}_PASSWORD=$app_password"
|
||||
export HALKYON_FDROID_KEYSTORE_PASSWORD="$fdroid_password"
|
||||
unset app_password fdroid_password
|
||||
fi
|
||||
status=0
|
||||
dart run tool/release.dart "$app" "$@" || status=$?
|
||||
exit "$status"
|
||||
|
|
|
|||
Loading…
Reference in a new issue