Developer-Dashboard
view release on metacpan or search on metacpan
The checked-in Windows verification assets follow the same layered approach:
fast forced-Windows unit coverage in `t/`, a real Strawberry Perl host smoke in
`integration/windows/run-strawberry-smoke.ps1`, and a host-side rerun helper in
`integration/windows/run-host-windows-smoke.sh` that delegates to
`integration/windows/run-qemu-windows-smoke.sh` for release-grade Windows
compatibility claims. The supported baseline on Windows is PowerShell plus
Strawberry Perl. Git Bash is optional. Scoop is optional. They are setup
helpers, not runtime requirements for the installed `dashboard` command. In
the Dockur-backed path, the launcher stages the Strawberry Perl MSI from the
Linux host into the OEM bundle and can keep multiple retained Windows guests
alive on configurable host web/RDP ports while it reruns the same smoke.
### Browser Access Model
The browser security model follows the original local-first trust concept:
- requests from loopback with a loopback host, such as `127.0.0.1`, `::1`, or `localhost`, are treated as local admin
- requests from loopback with a hostname listed under `web.ssl_subject_alt_names` are also treated as local admin
- requests from non-loopback IPs are treated as helper access
- outsider requests return `401` without a login page until at least one helper user exists
- after a helper user exists, outsider requests receive the helper login page
lib/Developer/Dashboard.pm view on Meta::CPAN
usable without requiring a Unix shell just to load the dashboard runtime.
The repository-only Windows verification assets follow the same layered
approach: fast forced-Windows unit coverage in C<t/>, a real Strawberry Perl
host smoke in the source checkout, and a host-side rerun helper that delegates
to the QEMU launcher for release-grade Windows compatibility claims. The
supported baseline on Windows is PowerShell plus Strawberry Perl. Git Bash is
optional. Scoop is optional. They are setup helpers, not runtime requirements
for the installed C<dashboard> command. In the Dockur-backed path, the launcher
stages the Strawberry Perl MSI from the Linux host into the OEM bundle and can
keep multiple retained Windows guests alive on configurable host web/RDP ports
while it reruns the same smoke.
=head2 Browser Access Model
The browser security model follows the original local-first trust concept:
=over 4
=item *
lib/Developer/Dashboard/CLI/Progress.pm view on Meta::CPAN
Construct and drive one progress board.
=for comment FULL-POD-DOC START
=head1 PURPOSE
This module turns runtime lifecycle events into a visible task list on the terminal so restart and stop do not leave the user staring at a blank prompt while the runtime waits through managed stability windows.
=head1 WHY IT EXISTS
It exists because the restart and stop flows intentionally wait for collectors and the web service to prove they stayed alive or shut down cleanly. Without a dedicated renderer that delay looks like a hang even when the runtime is behaving exactly as...
=head1 WHEN TO USE
Use this file when changing the terminal progress UX for lifecycle commands, when adding new restart or stop tasks that need to appear in the task list, or when adjusting how task boards redraw in interactive shells versus captured non-interactive ru...
=head1 HOW TO USE
Construct the object with a title and the full ordered task list before work begins, then pass the callback into the runtime lifecycle method. The runtime reports task-id and status updates, and this renderer prints the current state of the whole boa...
=head1 WHAT USES IT
lib/Developer/Dashboard/PageDocument.pm view on Meta::CPAN
if (!window.__dashboardAjaxSingletons) window.__dashboardAjaxSingletons = {};
if (window.__dashboardAjaxSingletons[name]) return;
window.__dashboardAjaxSingletons[name] = true;
window.addEventListener('pagehide', function() {
let url = '/ajax/singleton/stop?singleton=' + encodeURIComponent(name);
if (navigator.sendBeacon) {
navigator.sendBeacon(url, '');
return;
}
if (window.fetch) {
fetch(url, { method: 'POST', keepalive: true, credentials: 'same-origin' }).catch(function () {});
}
});
}
function dashboard_target_nodes(target) {
if (!target) return [];
if (typeof target === 'string') return Array.prototype.slice.call(document.querySelectorAll(target));
if (target instanceof Element) return [target];
if (target.length && typeof target !== 'string') return Array.prototype.slice.call(target);
return [];
}
lib/Developer/Dashboard/RuntimeManager.pm view on Meta::CPAN
}
elsif ($ready_polls) {
return 0;
}
sleep $self->_runtime_poll_interval;
}
return 0;
}
# _collector_runtime_ready($name, $pid)
# Confirms that a newly started collector loop became visible and stayed alive
# long enough to catch an immediate post-ready crash.
# Input: collector name string and process id integer.
# Output: boolean true when the collector loop became visible and survived the
# short confirmation window afterwards.
sub _collector_runtime_ready {
my ( $self, $name, $pid ) = @_;
return 0 if !defined $name || $name eq '';
return 0 if !defined $pid || $pid !~ /^\d+$/ || $pid < 1;
my $ready_polls = 0;
for ( 1 .. $self->_runtime_stability_polls ) {
lib/Developer/Dashboard/Zipper.pm view on Meta::CPAN
=head2 zip, unzip, acmdx, Ajax, __cmdx, _cmdx, _cmdp
Encode and decode token payloads and generate older-style ajax links. Saved
bookmark Ajax file handlers are stored under the dashboards ajax tree as
executable files so the web runtime can run them as real processes.
=for comment FULL-POD-DOC START
=head1 PURPOSE
This module keeps the older bookmark and Ajax helper compatibility surface alive. It builds tokenised URLs, saved Ajax endpoints, and helper snippets such as C<Ajax()> while routing the actual encoding work through the modern codec module.
=head1 WHY IT EXISTS
It exists because older bookmarks still expect the historical helper names and URL-building patterns. Keeping those wrappers in one module preserves compatibility without forcing newer runtime code to keep re-implementing the old API directly.
=head1 WHEN TO USE
Use this file when changing older Ajax helper behavior, saved Ajax file validation, token URL generation, or the compatibility wrappers that older bookmark instructions still reference.
=head1 HOW TO USE
t/09-runtime-manager.t view on Meta::CPAN
return {
pid => $$,
name => 'alpha.collector',
status => 'starting',
};
};
ok(
$manager->_collector_runtime_ready( 'alpha.collector', $$ ),
'_collector_runtime_ready falls back to the persisted loop state while the managed process title is not observable yet',
);
is( $polls, 0, '_collector_runtime_ready trusts the persisted loop-state fallback without consulting running_loops when the pid is already proven alive' );
}
{
no warnings 'redefine';
local *Developer::Dashboard::RuntimeManager::sleep = sub { return 0 };
local *Local::RuntimeRunner::running_loops = sub {
die "running_loops should not be consulted while the persisted loop-state fallback already proves the pid is alive\n";
};
local *Local::RuntimeRunner::loop_state = sub {
return {
pid => $$,
name => 'alpha.collector',
status => 'starting',
};
};
ok(
$manager->_collector_runtime_ready( 'alpha.collector', $$ ),
t/09-runtime-manager.t view on Meta::CPAN
my $calls = 0;
no warnings 'redefine';
local *Developer::Dashboard::RuntimeManager::running_web = sub {
return $calls++ == 0 ? { pid => $listener, port => 7908 } : undef;
};
local *Developer::Dashboard::RuntimeManager::_listener_pids_for_port = sub { return ($listener) };
local *Developer::Dashboard::RuntimeManager::_find_legacy_web_processes = sub { return () };
local *Developer::Dashboard::RuntimeManager::_pkill_perl = sub { return 1 };
is( $manager->stop_web, $listener, 'stop_web returns the recorded pid while it also tracks listener pids on the bound port' );
waitpid( $listener, 0 );
ok( !kill( 0, $listener ), 'stop_web escalates listener-port pids to KILL when they remain alive after TERM' );
}
{
my $late_listener = fork();
die "fork failed: $!" if !defined $late_listener;
if ( !$late_listener ) {
local $SIG{TERM} = 'IGNORE';
sleep 30;
exit 0;
}
t/14-coverage-closure-extra.t view on Meta::CPAN
interval => 0,
job => { command => 'printf scrub', cwd => $home },
name => $loop_name,
schedule_mode => 'interval',
single_tick => 1,
title => $runner->_process_title($loop_name),
);
exit( $ok ? 0 : 1 );
}
waitpid( $child_pid, 0 );
is( $? >> 8, 0, '_run_loop_child keeps a coverage-instrumented child alive long enough to execute one scrubbed tick' );
open my $seen_fh, '<', $seen_file or die "Unable to read $seen_file: $!";
my $seen = json_decode( do { local $/; <$seen_fh> } );
close $seen_fh;
is( $seen->{perl5opt}, '', '_run_loop_child clears PERL5OPT inside managed collector children when coverage instrumentation is active' );
is( $seen->{harness_perl_switches}, '', '_run_loop_child clears HARNESS_PERL_SWITCHES inside managed collector children when coverage instrumentation is active' );
}
{
my $loop_name = 'coverage.loop.error';
my $child_pid = fork();
( run in 1.222 second using v1.01-cache-2.11-cpan-39bf76dae61 )