Chandra
view release on metacpan or search on metacpan
examples/pack_example/pack.pl view on Meta::CPAN
#!/usr/bin/env perl
#
# pack.pl - Pack the example Chandra app into a distributable bundle
#
# Usage:
# cd examples/pack_example
# perl pack.pl # builds for current platform
# perl pack.pl --platform=linux # cross-target
# perl pack.pl --distribute # build + sign/notarize/DMG (macOS) or AppImage (Linux)
#
# For distribution on macOS, configure signing credentials first:
# Chandra::Pack->config(
# identity => 'Developer ID Application: ...',
# apple_id => 'your@email.com',
# team_id => 'TEAM123',
# );
# Or via environment: CHANDRA_IDENTITY, CHANDRA_APPLE_ID, CHANDRA_TEAM_ID
#
use strict;
use warnings;
use FindBin;
lib/Chandra/Pack.pm view on Meta::CPAN
sub _save_config {
my $file = _config_file();
my $dir = file_dirname($file);
file_mkpath($dir) unless file_is_dir($dir);
my $content = "# Chandra::Pack configuration\n";
for my $key (sort keys %CONFIG) {
next unless defined $CONFIG{$key};
$content .= "$key = $CONFIG{$key}\n";
}
file_spew($file, $content);
chmod 0600, $file; # Protect credentials
}
# Load config on module load
_load_config();
sub new {
my ($class, %args) = @_;
Carp::croak("'script' is required") unless $args{script};
Carp::croak("Script '$args{script}' not found") unless file_exists($args{script});
Carp::croak("Script '$args{script}' is not a file") unless file_is_file($args{script});
lib/Chandra/Pack.pm view on Meta::CPAN
=encoding utf8
=head1 NAME
Chandra::Pack - Bundle Chandra apps into distributable packages
=head1 SYNOPSIS
use Chandra::Pack;
# Configure credentials (once, persists to ~/.chandra/pack.conf)
Chandra::Pack->config(
identity => 'Developer ID Application: Your Name',
apple_id => 'you@example.com',
team_id => 'ABCD1234',
save => 1,
);
my $packer = Chandra::Pack->new(
script => 'app.pl',
name => 'My App',
lib/Chandra/Pack.pm view on Meta::CPAN
=item * B<Linux>: AppImage (via appimagetool)
=item * B<Windows>: Directory build (installer support planned)
=back
=head1 CLASS METHODS
=head2 config(%args)
Configure credentials for signing and notarization. Call once before
building. Settings can be persisted to C<~/.chandra/pack.conf>.
Chandra::Pack->config(
# macOS signing/notarization
identity => 'Developer ID Application: ...',
apple_id => 'your@email.com',
team_id => 'ABCD1234',
notary_keychain => 'notary-profile', # from notarytool store-credentials
# Persist to disk
save => 1,
);
Environment variables are used as fallbacks:
CHANDRA_IDENTITY
CHANDRA_APPLE_ID
CHANDRA_TEAM_ID
lib/Chandra/Pack.pm view on Meta::CPAN
=head1 DISTRIBUTION DETAILS
=head2 macOS Code Signing
Uses hardened runtime with entitlements for JIT and unsigned memory
(required for Perl). Ad-hoc signing (C<identity =E<gt> '-'>) skips
notarization but still works locally.
=head2 macOS Notarization
Requires Apple Developer account. Store credentials once with:
xcrun notarytool store-credentials notary-profile \
--apple-id your@email.com \
--team-id ABCD1234 \
--password your-app-specific-password
Then configure:
Chandra::Pack->config(notary_keychain => 'notary-profile');
=head2 Linux AppImage
t/97_pack.t view on Meta::CPAN
my $signed = $dist->build;
ok($signed->{success}, 'an ad hoc signed build with a disk image succeeds') or diag($signed->{error});
ok($signed->{signed} && -f $signed->{dmg_path}, 'signed, with the image written');
like($dist->_codesign_macos("$out/nothing.app", '-')->{error}, qr/codesign failed/, 'signing a missing app fails');
like($dist->_create_dmg_macos("$out/nothing.app")->{error}, qr/DMG creation failed/, 'imaging a missing app fails');
my $note = $dist->_notarize_macos("$out/nothing.app");
like($note->{error}, qr/Failed to create ZIP|Notarization failed/, 'notarising a missing app fails');
Chandra::Pack->config(notary_keychain => 'profile');
$note = $dist->_notarize_macos("$out/DistApp.app");
like($note->{error}, qr/Notarization failed/, 'and notarising without credentials fails after the zip');
Chandra::Pack->config(notary_keychain => undef);
Chandra::Pack->config(identity => 'Not A Real Identity', apple_id => 'a', team_id => 't');
my $bad = Chandra::Pack->new(script => $script, name => 'Bad Sign', output => $out, distribute => 1)->build;
ok(!$bad->{success}, 'a signing identity that does not exist fails the distribution');
Chandra::Pack->config(identity => undef, apple_id => undef, team_id => undef);
my $nocc = Chandra::Pack->new(script => $script, name => 'No Compile', output => "$dir/icon.png");
eval { $nocc->build };
like($@, qr/Failed to compile macOS launcher|cannot|Not a directory|exists/i, 'a launcher that cannot be written dies');
( run in 2.057 seconds using v1.01-cache-2.11-cpan-3f962061493 )