Specify the issue tracker
"home directory" to administer
-
-u
+
-uuser[:password]
-
The user and password to use
+
The user and password to use
for commands (partial implemention, see Security Notes
below).
-
+
-h
-
-
+
+
-
Print help text.
+
Print help text.
+
+
-
+
-
-d
-
-
+
-d
+
+
-
Print full designators (e.g. issue1) not just id numbers
-(1).
+
Print full designators (e.g.
+issue1) not just id numbers (1).
+
+
-
+
-
-c
-
-
+
-c
+
+
-
When outputting lists of data, comma-separate them. Same
-as -S ",".
+
When outputting lists of data,
+comma-separate them. Same as -S ",".
+
+
-
-Sstring
+
-Sstring
-
When outputting lists of data,
+
When outputting lists of data,
separate items with given string.
-
+
-s
-
-
+
+
When outputting lists of data, space-separate them. Same
-as -S " ".
+as -S " ".
+
+
-
-P pragma=value
+
-P pragma=value
-
Set a pragma on the command
+
Set a pragma on the command
line. Multiple -P options can be specified to set
multiple pragmas.
-
+
-V
-
-
+
+
Be verbose when importing data.
-
+
-
+
-
-v
-
-
+
-v
+
+
-
Report Roundup and Python versions and quit.
-
+
Report Roundup and Python
+versions and quit.
+
-
Only one of
+
Only one of
-s, -c or -S can be specified.
COMMANDS
@@ -175,209 +185,200 @@
COMMANDS
-
If no command
-is provided on the command line, roundup-admin will enter an
+
If no command is
+provided on the command line, roundup-admin will enter an
interactive mode. More details about these commands are
available using the help command.
-
A designator is
+
A designator is
a classname and a nodeid concatenated, eg. bug1, user10,
....
-
Roundup-admin
+
Roundup-admin
takes a number of commands:
-
-
+
+
help
-
-
+
+
prints help (same as
-h)
-
+
-
help
+
help<subcommand>
-
Print command-specific help
+
Print command-specific help
-
help all
+
help all
-
Print available help for all
+
Print available help for all
commands.
-
-
-
-
-
-
-
commit
-
-
+
commit
+
Commit changes made to the
+database during an interactive session.
-
Commit changes made to the database during an
-interactive session.
-
-
-
The changes
+
The changes
made during an interactive session are not automatically
written to the database - they must be committed using this
command.
-
One-off
+
One-off
commands on the command-line are automatically committed if
they are successful. See also rollback.
-
createclassname
+
createclassname
property=value ...
-
This creates a new entry of the
+
This creates a new entry of the
given class using the property name=value arguments provided
on the command line after the "create"
command.
-
display
+
displaydesignator[,designator]*
-
This lists the properties and
+
This lists the properties and
their associated values for the given node. The pragma
display_header can be used to add a header between
designators that includes the active/retired status of the
item.
-
export
+
export[[-]class[,class]] export_dir
-
Export the database to
+
Export the database to
colon-separated-value files. To exclude the files (e.g. for
the msg or file class), use the exporttables command.
-
Optionally
+
Optionally
limit the export to just the named classes or exclude the
named classes, if the 1st argument starts with
’-’.
-
This action
+
This action
exports the current data from the database into
colon-separated-value files that are placed in the nominated
destination directory.
-
exporttables
+
exporttables[[-]class[,class]] export_dir
-
Export the database to
+
Export the database to
colon-separated-value files, excluding the files below
$TRACKER_HOME/db/files/ (which can be archived separately).
To include the files, use the export command.
-
filterclassname
+
filterclassname
propname=value ...
-
Find the nodes of the given
+
Find the nodes of the given
class with a given property value. Multiple values can be
specified by separating them with commas. If property is a
-string, all values must match. I.E. it’s an matches.
-I.E. an ’or’ operation.
+string, all values must match. I.E. it’s an
+’and’ operation. If the property is a
+link/multilink any value matches. I.E. an ’or’
+operation.
-
findclassname
+
findclassname
propname=value ...
-
Find the nodes of the given
+
Find the nodes of the given
class with a given link property value.
-
genconfig
+
genconfig<filename>
-
Generate a new tracker config
+
Generate a new tracker config
file (ini style) with default values in
<filename>. Note that this does not preserve
any settings from the current tracker. Use updateconfig for
that.
-
getproperty
+
getproperty
designator[,designator]*
-
Get the given property of one
+
Get the given property of one
or more designator(s).
-
Retrieves the
+
Retrieves the
property value of the nodes specified by the
designators.
-
historydesignator
+
historydesignator
[skipquiet] [raw]
-
Lists the journal entries
+
Lists the journal entries
viewable by the user for the node identified by the
designator. If skipquiet is added, journal entries for quiet
properties are not shown. Without the raw option a more
human readable output format is used.
-
import
+
importimport_dir
-
Import a database from the
+
Import a database from the
directory containing CSV files, two per class to import.
-
The imported
+
The imported
nodes will have the same nodeid as defined in the import
file, thus replacing any existing content.
-
The new nodes
+
The new nodes
are added to the existing database - if you want to create a
new database using the imported data, then create a new
database (or, tediously, retire all the old data). See also
export.
-
importtables
+
importtablesimport_dir
-
Import a database from the
+
Import a database from the
directory containing CSV files, two per class to import.
-
The imported
+
The imported
nodes will have the same nodeid as defined in the import
file, thus replacing any existing content.
-
This only
+
This only
imports database tables. It does not import files/message
content. It is used to import data exported by exporttables.
See also exporttables.
-
initialise
+
initialise[adminpw]
-
Initialise a new Roundup
+
Initialise a new Roundup
tracker.
-
The
+
The
administrator details will be set at this step.
-
install[template
+
install[template
[backend [key=val[,key=val]]]]
-
Install a new roundup
+
Install a new roundup
tracker.
-
The command
+
The command
will prompt for the tracker home directory (if not supplied
through TRACKER_HOME or the -i option). The template and
backend may be specified on the command-line as arguments,
in that order.
-
Command line
+
Command line
arguments following the backend allows you to pass initial
values for config options. For example, passing
"web_http_auth=no,rdbms_user=dinsdale" will
@@ -386,189 +387,189 @@
COMMANDS
in this argument! (Enclose whole argument in quotes if you
need spaces in option value).
-
The initialise
+
The initialise
command must be called after this command in order to
initialise the tracker’s database. You may edit the
tracker’s initial database contents before running
that command by editing the tracker’s dbinit.py module
init() function.
-
See also
+
See also
initopts help.
-
listclassname
+
listclassname
[property]
-
Lists all instances of the
+
Lists all instances of the
given class. If the property is not specified, the
"label" property is used. The label property is
tried in order: the key, "name", "title"
and then the first property, alphabetically.
-
With -c,
+
With -c,
-S or -s print a list of item id’s if no
property specified. If property specified, print list of
that property for every class instance.
-
The pragma
+
The pragma
show_retired can be used to print only retired items
or to print retired and active items. The default is to
print only active items.
-
migrate
+
migrate
-
Update a tracker’s
+
Update a tracker’s
database to be compatible with the Roundup codebase.
-
You should run
+
You should run
the "migrate" command for your tracker once
you’ve installed the latest codebase.
-
Do this before
+
Do this before
you use the web, command-line or mail interface and before
any users access the tracker.
-
This command
+
This command
will respond with either "Tracker updated" (if
you’ve not previously run it on an RDBMS backend) or
"No migration action required" (if you have run
it, or have used another interface to the tracker, or
possibly because you are using anydbm).
-
It’s safe
+
It’s safe
to run this even if it’s not required, so just get
into the habit.
-
packperiod |
+
packperiod |
date
-
Remove journal entries older
+
Remove journal entries older
than a period of time specified or before a certain
date.
-
perftest[mode]
+
perftest[mode]
[arguments]*
-
Run performance test. For
+
Run performance test. For
example test the effect of changing password hashing
parameters.
will show all
settings and their current values. If verbose is enabled
hidden settings and descriptions will be shown.
-
reindex
+
reindex[classname|classname:#-#|designator]* This will
-
re-generate the search indexes
+
re-generate the search indexes
for a tracker. You can specify a specific item (or items)
(e.g. issue23), range(s) of items (e.g. issue:1-1000),
class(es) (e.g. issue) or reindex all items in the database
if no arguments are supplied.
-
restore
+
restoredesignator[,designator]*
-
Restore the retired node
+
Restore the retired node
specified by designator.
-
The given nodes
+
The given nodes
will become available for users again.
-
retire
+
retiredesignator[,designator]*
-
This action indicates that a
+
This action indicates that a
particular node is not to be retrieved by the list or find
commands, and its key value may be re-used. See also
restore.
-
rollback
+
rollback
-
Undo all changes that are
+
Undo all changes that are
pending commit to the database.
-
The changes
+
The changes
made during an interactive session are not automatically
written to the database - they must be committed manually.
This command undoes all those changes, so a commit
immediately after would make no changes to the database.
-
security[Role
+
security[Role
name]
-
Display the Permissions
+
Display the Permissions
available to one or all Roles.
-
setitems
+
setitems
property=value property=value ...
-
Set the given properties of one
+
Set the given properties of one
or more items(s).
-
The items are
+
The items are
specified as a class or as a comma-separated list of item
designators (ie
"designator[,designator,...]").
-
This command
+
This command
sets the properties to the values for all designators given.
If the value is missing (ie. "property=") then the
property is un-set. If the property is a multilink, you
specify the linked ids for the multilink as comma-separated
numbers (ie "1,2,3").
-
specification
+
specificationclassname
-
Show the properties for a
+
Show the properties for a
classname.
-
templates
+
templates[trace_search]]
-
Lists the names, location and
+
Lists the names, location and
description of all known templates.
-
tableclassname
+
tableclassname
[property[,property]*]
-
Lists all instances of the
+
Lists all instances of the
given class. If the properties are not specified, all
properties are displayed. By default, the column widths are
the width of the largest value.
-
The pragma
+
The pragma
show_retired can be used to print only retired items
or to print retired and active items. The default is to
print only active items.
-
updateconfig
+
updateconfig<filename>
-
This is used when updating
+
This is used when updating
software. It merges the config.ini from the tracker
with new settings from the new software. The merged/updated
config file is written to <filename>.
-
Commands may be
+
Commands may be
abbreviated as long as the abbreviation matches only one
command, e.g. l == li == lis == list.
@@ -577,15 +578,15 @@
READLINE SUPPORT
-
You can edit
-the command line and interact with history in
+
You can edit the
+command line and interact with history in
roundup-admin’s interactive mode. On Linux like
systems, GNU Readline is required. On Mac’s libedit
can be used as well. On Windows pyreadline3 is required.
See: https://docs.python.org/3/library/readline.html for
details on readline.
-
Roundup-admin
+
Roundup-admin
will save the history between roundup-admin sessions. The
commands are saved to the .roundup_admin_history file
in the user’s home directory. You can set the pragma
@@ -593,17 +594,17 @@
READLINE SUPPORT
change the amount of available and stored history for the
session.
-
If you are
-using GNU readline, you can persistently change the history
-size by adding: set history-size 100 to the init file
+
If you are using
+GNU readline, you can persistently change the history size
+by adding: set history-size 100 to the init file
.roundup_admin_rlrc located in the user’s home
directory.
-
Mac users using
+
Mac users using
libedit should be able to persistently save history and set
the history size by adding history size 100.
-
Users of
+
Users of
pyreadline3 can use: history_length(100).
SECURITY NOTES
@@ -611,14 +612,14 @@
SECURITY NOTES
-
The -u
+
The -u
user setting does not currently operate like a user
logging in via the web. The user running roundup-admin must
have read access to the tracker home directory. As a result
the user has access to the files and the database info
contained in config.ini.
-
Using -u
+
Using -u
user sets the actor/user parameter in the journal.
Changes that are made are attributed to that user. The
password is ignored if provided. Any existing username has
@@ -633,9 +634,9 @@
ENVIRONMENT VARIABLES
-
ROUNDUP_LOGIN
+
ROUNDUP_LOGIN
-
Provides an alternate way to
+
Provides an alternate way to
set the user.
FURTHER HELP
@@ -643,8 +644,8 @@
FURTHER HELP
-
roundup-admin
--h
+
roundup-admin -h
+
roundup-admin help -- this help
roundup-admin help <command> -- command-specific help
@@ -656,7 +657,7 @@
Create a fresh
+demo tracker (deleting the existing one if any). E.G.
+roundup-demo -b sqlite -t classic ./mytracker nuke
will remove an existing tracker (if present) from the
directory ./mytracker. Then it will create and serve
a new empty classic tracker using the sqlite backend.
-
-h, --help
+
-h, --help
-
Show the help
+
Show the help
message and exit
-
-BBIND_ADDRESS,
+
-BBIND_ADDRESS,--bind_addressBIND_ADDRESS
-
Choose address
+
Choose address
for server to listen at. Use 0.0.0.0 to bind to all
addreses. Default: 127.0.0.1.
Set the
hostname used in the URL. This does not make the server
listen at the hostname. Use the hostname with -B to
listen on that IP address.
-
-pPORT,
+
-pPORT,
--portPORT
-
Listen at this
+
Listen at this
port. Default: search for open port starting at 8917.
-
-PURLPORT,
+
-PURLPORT,
--urlportURLPORT
-
When using
+
When using
docker this option passes the docker external port to the
demo instance. If using docker ... -p 9090:8917 ...
this should be set to -P 9090. Default: as selected
by --port.
-
-V, --version
+
-V, --version
-
Show
+
Show
program’s version number and exit
-
If items marked
+
If items marked
with (*) are missing, they will be asked for interactively
when setting up the tracker.
@@ -159,7 +158,7 @@
DESCRIPTION
-
This command
+
This command
creates a fresh demo tracker for you to experiment with. The
email features of Roundup will be turned off (so the nosy
feature won’t send email). It does this by removing
@@ -170,12 +169,12 @@
DESCRIPTION
templates directory. The templates command from
roundup-admin(1) can help you locate a replacement.
-
If you wish,
-you may modify the demo tracker by editing its configuration
+
If you wish, you
+may modify the demo tracker by editing its configuration
files and HTML templates. See the customisation
manual for information about how to do that.
-
Once
+
Once
you’ve fiddled with the demo tracker, you may use it
as a template for creating your real, live tracker. Simply
run the roundup-admin command to install the tracker
@@ -189,7 +188,7 @@
specify the values to set on
the class specified as prefix using the same format as the
Subject line property manipulations. If the class prefix is
left out it defaults to msg. Can also be specified
with --set-value (and abbreviated to
--set).
-
-O --oauth-directory
+
-O --oauth-directorydirectory
-
Only with OAuth authentication
+
Only with OAuth authentication
specify the directory containing additional OAuth
credentials.
-
-T
---oauth-token-endpointurl
+
-T --oauth-token-endpoint
+url
-
Token endpoint URL of your
+
Token endpoint URL of your
cloud provider, only used with OAuth.
DESCRIPTION
@@ -100,67 +101,67 @@
DESCRIPTION
-
The roundup
-mail gateway may be called in one of four ways:
+
The roundup mail
+gateway may be called in one of four ways:
-
-
+
+
•
-
-
+
+
without arguments which will use the env var
ROUNDUP_INSTANCE,
-
-
+
+
-
•
-
-
+
•
+
+
-
with an instance_home as the only argument,
+
with an instance_home as
+the only argument,
-
-
+
+
-
•
-
-
+
•
+
+
-
with both an instance_home and a mail spool file,
-or
+
with both an
+instance_home and a mail spool file, or
-
-
+
+
-
•
-
-
+
•
+
+
-
with both an instance home and a mail source type and
-its specification.
+
with both an instance home and a
+mail source type and its specification.
-
PIPE
-
+
PIPE
If there is no mail source specified, the mail gateway reads
a single message from the standard input and submits the
message to the roundup.mailgw module.
-
UNIX
+
UNIX
mailbox
In this case, the gateway reads all messages from the UNIX
mail spool file and submits each in turn to the
@@ -169,16 +170,16 @@
DESCRIPTION
mailbox/path/to/mailbox
-
In all of the
+
In all of the
following mail source types, the username and password can
-be stored in a ~/.netrc file. If done so, only the server
+be stored in a ˜/.netrc file. If done so, only the server
name needs to be specified on the command-line.
-
The username
+
The username
and/or password will be prompted for if not supplied on the
-command-line or in ~/.netrc.
+command-line or in ˜/.netrc.
-
POP
+
POP
For the mail source "pop", the gateway reads all
messages from the POP server specified and submits each in
turn to the roundup.mailgw module. The server is specified
@@ -191,19 +192,16 @@
DESCRIPTION
pop server
are both valid.
-
POPS
-
+
POPS
Connect to the POP server over ssl/tls. This supports the
same notation as POP.
-
APOP
-
+
APOP
Same as POP, but using Authenticated POP:
apopusername:password@server
-
IMAP
-
+
IMAP
Connect to an IMAP server. This supports the same notation
as that of POP mail.
imap
@@ -215,7 +213,7 @@
DESCRIPTION
username:password@server
mailbox
-
IMAPS
+
IMAPS
Connect to an IMAP server over ssl/tls. This supports the
same notation as IMAP.
@@ -224,7 +222,7 @@
DESCRIPTION
[mailbox]
-
IMAPS_CRAM
+
IMAPS_CRAM
Connect to an IMAP server over ssl/tls using CRAM-MD5
authentication. This supports the same notation as IMAP.
@@ -234,7 +232,7 @@
DESCRIPTION
[mailbox]
-
IMAPS_OAUTH
+
IMAPS_OAUTH
Connect to an IMAP server over ssl/tls using OAUTH
authentication. Note that this does not support a password
@@ -262,7 +260,7 @@
ENVIRONMENT VARIABLES
-
ROUNDUP_INSTANCE
+
ROUNDUP_INSTANCE
This can be used to set the instance directory. If it is
set, the instance_home argument is optional.
@@ -272,17 +270,17 @@
EXAMPLE
-
If your msg
+
If your msg
class has a messsagetype property you can set up aliases to
receive the different types of messages. Setting up an alias
in your MTA Using:
-
tracker:
+
tracker:
|/tools/roundup/bin/roundup-mailgw
-S "msg.messagetype=reply - to all"
/var/roundup/sysadmin
-
(the lines are
+
(the lines are
split for readability. In the alias file they will be on the
same line). Replace /tools/roundup/bin/roundup-mailgw by
your path to the roundup-mailgw. This creates the email
@@ -291,39 +289,39 @@
EXAMPLE
all". The roundup tracker instance is located at
/var/roundup/sysadmin.
-
A comment alias
+
A comment alias
would receive emails at tracker_comment with:
which would be
-a technical message. These messages can trigger different
+
which would be a
+technical message. These messages can trigger different
workflows based on the messagetype.
-
Both examples
+
Both examples
use the default class specified in the tracker’s
config.ini (usually the issue class).
-
You can also
-set properties directly on the issue class. If your
+
You can also set
+properties directly on the issue class. If your
tracker’s issue has a "private" property
that limits who can view an issue and its messages:
Use options read from the
configuration file (see below).
-
-nhostname
+
-nhostname
-
Sets the host name or IP
+
Sets the host name or IP
address to listen on. Default is localhost (127.0.0.1). Use
0.0.0.0 to listen on all interfaces on the system.
-
-pport
+
-pport
-
Sets the port to listen on
+
Sets the port to listen on
(default: 8080).
-
-dPIDfile
+
-dPIDfile
-
Run the server in the
+
Run the server in the
background and write the server’s PID to the file
indicated by PIDfile. The -l (or -L) option must be
specified if -d is used.
@@ -81,49 +82,51 @@
OPTIONS
-
+
-D
-
-
+
+
-
Run the server in the foreground even if -d is used.
+
Run the server in the foreground even if -d is used.
+
+
-
-t
+
-t
fork|thread|debug|none
-
Control multi-process mode.
+
Control multi-process mode.
debug and none are always available. If an
invalid mode is specified the server starts in none
(also called single) mode. Default fork.
-
-m
+
-mmax_children
-
Set the maximum number of child
+
Set the maximum number of child
processes (servers). This value may need to be increased on
a heavily loaded site. Default 40.
-
-lfile
+
-lfile
-
Sets a filename to log to
+
Sets a filename to log to
(instead of stdout). This is required if the -d option is
used.
-
+
-P
-
-
+
+
If a reverse proxy is used in front of the
@@ -139,22 +142,22 @@
OPTIONS
for details and warnings about using the X-Forwarded-For
header.
-
+
-
-L
-
-
+
-L
+
+
-
Have the server log using the Python logger with key
-roundup.http.
+
Have the server log using the
+Python logger with key roundup.http.
-
-ifile
+
-ifile
-
Sets a filename to use as a
+
Sets a filename to use as a
template for generating the tracker index page. The variable
"trackers" is available to the template and is a
dict of all configured trackers. If you connect to the root
@@ -162,10 +165,10 @@
OPTIONS
page is shown. Using -i allows you to customize the
index page.
-
-I
+
-Iheader1[,header2,...]
-
Pass the header(s) and their
+
Pass the header(s) and their
values to the backend. This allow-list of header variables
can be used by custom code in the tracker or with a
tracker’s http_auth_header configuration option
@@ -175,13 +178,13 @@
OPTIONS
-
+
-s
-
-
+
+
Enables use of SSL. In most cases, you will want to run
@@ -190,91 +193,73 @@
OPTIONS
filter/rate limit/firewall requests to roundup-server.
-
-efile
+
-efile
-
Sets a filename containing the
+
Sets a filename containing the
PEM file to use for SSL. The PEM file must include both the
private key and certificate with appropriate header/trailer
markers:
If no file is
specified, a temporary self-signed certificate will be
used.
-
+
-N
-
-
+
+
Log client machine names instead of IP addresses (much
-slower).
+slower).
+
+
-
-VHTTPVER
+
-VHTTPVER
-
By default roundup-server uses
+
By default roundup-server uses
HTTP/1.1 to enable keepalives for faster response. HTTPVER
can be set to HTTP/1.0 to disable keepalives.
-
-
-
-
-
-
-
-uUID
-
-
+
-uUID
+
Runs the Roundup web server as
+this UID.
-
Runs the Roundup web server as this UID.
-
-
-
-
-
-
-
-
-gGID
-
-
+
-gGID
+
Runs the Roundup web server as
+this GID.
-
Runs the Roundup web server as this GID.
-
-
-
-
-
-v or
+
-v or
--version
-
Print version and exit.
+
Print version and exit.
-
-h or --help
+
-h or --help
-
Print help and exit.
+
Print help and exit.
-
--save-config
+
--save-config
-
Create configuration file and
+
Create configuration file and
exit. The old config.ini will be saved to config.bak. Note
that this command doesn’t attempt to load or verify an
existing config.ini. Running this in a tracker home
@@ -283,10 +268,10 @@
OPTIONS
This will make the tracker in the directory fail to start
until the original config.ini is restored.
-
name=tracker
+
name=tracker
home
-
Sets the tracker home(s) to
+
Sets the tracker home(s) to
use. The name variable is how the tracker is
identified in the URL (it’s the first part of the URL
path). The tracker home variable is the directory
@@ -298,7 +283,7 @@
OPTIONS
characters like spaces, as these confuse the cookie handling
in browsers like IE.
-
If you connect
+
If you connect
to the root directory (I.E. you do not include the
name component in the URL, the server will display an
index page of trackers served by roundup-server if more than
@@ -311,14 +296,14 @@
This manpage
-was written by Bastian Kleineidam <calvin@debian.org>
-for the Debian distribution of roundup.
+
This manpage was
+written by Bastian Kleineidam <calvin@debian.org> for
+the Debian distribution of roundup.
-
The main author
+
The main author
of roundup is Richard Jones
<richard@users.sourceforge.net>.
diff --git a/share/man/man1/roundup-admin.1 b/share/man/man1/roundup-admin.1
index fc819963b..7ce7046f0 100644
--- a/share/man/man1/roundup-admin.1
+++ b/share/man/man1/roundup-admin.1
@@ -99,9 +99,9 @@ To include the files, use the export command.
.TP
\fBfilter\fP \fIclassname propname=value ...\fP
Find the nodes of the given class with a given property value.
-Multiple values can be specified by separating them with commas.
-If property is a string, all values must match. I.E. it's an
-'and' operation. If the property is a link/multilink any value
+Multiple values can be specified by separating them with commas. If
+property is a string, all values must match. I.E. it's an 'and'
+operation. If the property is a link/multilink any value
matches. I.E. an 'or' operation.
.TP
\fBfind\fP \fIclassname propname=value ...\fP
diff --git a/share/man/man1/roundup-demo.1 b/share/man/man1/roundup-demo.1
index 6dfb5e8a5..3275e8085 100644
--- a/share/man/man1/roundup-demo.1
+++ b/share/man/man1/roundup-demo.1
@@ -4,7 +4,7 @@ roundup-demo \- create a roundup "demo" tracker and launch its web interface
.SH SYNOPSIS
\fBroundup_demo\fP [\fB\-h\fP] [\fB-b\fP \fIBIND_ADDRESS\fP]
[\fB-b\fP {\fBanydbm\fP,\fBmysql\fP,\fBsqlite\fP,\fBpostgresql\fP}]
-[\fB-t\fb
+[\fB-t\fP
{\fBminimal\fP,\fBjinja2\fP,\fBclassic\fP,\fBresponsive\fP,\fBdevel\fP}]
[\fB-p\fP \fIPORT\fP] [\fB-P\fP \fIURLPORT\fP] [\fB-V\fP]
[\fIdirectory\fP] [\fIbackend\fP] [\fBnuke\fP]
@@ -33,7 +33,7 @@ tracker using the sqlite backend.
Show the help message and exit
.TP
-\fB-B\fp \fIBIND_ADDRESS\fI, \fB--bind_address\fP \fIBIND_ADDRESS\fP
+\fB-B\fP \fIBIND_ADDRESS\fI, \fB--bind_address\fP \fIBIND_ADDRESS\fP
Choose address for server to listen at. Use 0.0.0.0 to bind to all addreses.
Default: 127.0.0.1.
From 8d8c6bb76eebf800a5f91de2adeca57fca5ee164 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Mon, 13 Jul 2026 00:01:30 -0400
Subject: [PATCH 535/562] chore(release): v2.6.0 changes.
date/version label updates.
CHANGES.txt - add rst formatting to prevent strings ending with _ from
being interpreted as links.
COPYING.txt - add note that vendored cgi.py is not under MIT license
CVE.txt - comment out CVE references allow upgrading.txt references
to be active.
announcement.txt - clarify supported python versions (3.10+).
security.txt, roundup-2.6.0b1.tar.gz.asc - add gpg detatched signature
and reference
upgrading.txt, upgrading-history.txt - mobe release 1.5.1 to history.
upgrading.txt - make CVE references live
setup.py - development status production, remove license classifiers,
remove license metadata add license-expression metadata, space
formatting fixups, python_requires now >=3.10
index.txt - add entry for PATHC not being CSRF protected
typo and wording fixups.
---
CHANGES.txt | 14 ++---
COPYING.txt | 3 +-
doc/CVE.txt | 8 +--
doc/acknowledgements.txt | 2 +-
doc/announcement.txt | 11 ++--
doc/security.txt | 2 +-
doc/upgrading-history.txt | 51 ++++++++++++++++++
doc/upgrading.txt | 54 +------------------
scripts/Docker/Dockerfile | 2 +-
setup.py | 21 +++-----
website/www/index.txt | 24 ++++++---
.../www/signatures/roundup-2.6.0.tar.gz.asc | 16 ++++++
12 files changed, 114 insertions(+), 94 deletions(-)
create mode 100644 website/www/signatures/roundup-2.6.0.tar.gz.asc
diff --git a/CHANGES.txt b/CHANGES.txt
index d7ace1680..833178217 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -6,14 +6,10 @@ and template changes not listed here.
Each entry has the developer who committed the change in brackets.
Many entries without name were done by Richard Jones.
-**IMPORTANT** The v1.5.x releases of Roundup were the last to support
-Python v2.5 and v2.6. Starting with the v1.6 releases of Roundup
-v2.7.2 or later are required to run newer releases of Roundup.
-Roundup 2.0 supports Python 3.4 and later. Roundup 2.1.0 supports
-python 3.6 or newer (3.4/3.5 might work, but they are not tested).
-Roundup 2.4.0 is the last release to support Python 2.
+**IMPORTANT** Roundup 2.6 supports Python 3.10 or newer.
+Roundup 2.4.0 was the last release to support Python 2.
-2026-XX-XX 2.6.0
+2026-07-13 2.6.0
Fixed:
@@ -81,7 +77,7 @@ Fixed:
if requested property is set to None. This should fix missing text
indexing for the anydbm backend. (John Rouillard)
- ruff driven cleanups/refactor of indexer* files. (John Rouillard)
-- remove roundup.anypy.scandir_ which was needed for python 2 support.
+- remove ``roundup.anypy.scandir_`` which was needed for python 2 support.
(John Rouillard)
- roundup-server no longer logs connection aborted when a client
disconnects and is using HTTP 1.1 or newer. (John Rouillard)
@@ -173,7 +169,7 @@ Features:
althttpd web server. (John Rouillard)
- add support for tokenless/nonceless CSRF prevention following
https://words.filippo.io/csrf/. (John Rouillard)
-- standardize use of roundup.anypy.urllib_. Replace urlparse() with
+- standardize use of ``roundup.anypy.urllib_``. Replace urlparse() with
urlsplit() (recommended) for some speedup. (John Rouillard)
- issue2551368 - version 2.0.0 of the pgp module was published by
Bernhard Reiter. Updated documentation and tests. (Bernhard Reiter,
diff --git a/COPYING.txt b/COPYING.txt
index 82beebecd..a123e0f4d 100644
--- a/COPYING.txt
+++ b/COPYING.txt
@@ -1,4 +1,5 @@
-Roundup, exclusive of the Zope page templates, is `MIT licensed`_.
+Roundup, exclusive of the Zope page templates and vendored cgi.py, is
+`MIT licensed`_.
.. _MIT licensed: https://opensource.org/license/mit
diff --git a/doc/CVE.txt b/doc/CVE.txt
index ec9c890fd..f7dc08fcd 100644
--- a/doc/CVE.txt
+++ b/doc/CVE.txt
@@ -92,7 +92,7 @@ upgrading doc `_ for these details.
:local:
:depth: 2
-.. _CVE-2026-csrfL:
+.. comment: _CVE-2026-csrfL:
.. note::
@@ -101,11 +101,11 @@ upgrading doc `_ for these details.
2.6 fixes this issue. If you are running 2.6.0 you don't have to do
anything.
-.. include:: upgrading.txt
+.. comment: include:: upgrading.txt
:start-after: .. comment: _CVE-2026-csrfL:
:end-before: .. comment:
-.. _CVE-2026-history_propL:
+.. comment: _CVE-2026-history_propL:
.. note::
@@ -114,7 +114,7 @@ upgrading doc `_ for these details.
protected by a check function. Release 2.6.0 fixes this. If you are
running 2.6.0, you don't have to do anything.
-.. include:: upgrading.txt
+.. comment: include:: upgrading.txt
:start-after: .. comment: _CVE-2026-history_prop:
:end-before: .. comment:
diff --git a/doc/acknowledgements.txt b/doc/acknowledgements.txt
index 7b672e8ab..f495b08c6 100644
--- a/doc/acknowledgements.txt
+++ b/doc/acknowledgements.txt
@@ -28,7 +28,7 @@ Release Manager: John Rouillard
Developer activity by changesets::
- rouilj@ieee.org 258
+ rouilj@ieee.org 288
*****************************************************
Other contributers:
diff --git a/doc/announcement.txt b/doc/announcement.txt
index d1f6a0c84..31c12274b 100644
--- a/doc/announcement.txt
+++ b/doc/announcement.txt
@@ -1,14 +1,13 @@
-I'm proud to release version 2.6.0b1 of the Roundup issue
+I'm proud to release version 2.6.0 of the Roundup issue
tracker. This release is a bugfix and feature release, so
make sure to read `docs/upgrading.txt
`_ to
bring your tracker up to date.
-The 48 changes, as usual, include some new features and many
+The 49 changes, as usual, include some new features and many
bug fixes.
-Version 2.6.0 does not support Python 2. The minimum Python
-version is 3.10.
+Version 2.6.0 requires Python version 3.10 or newer.
Note that you should run ``roundup-admin ... migrate`` to
update the database schema version. Do this before you use
@@ -19,10 +18,14 @@ You can install it with::
pip install roundup
+.. comment: add roundup==2.6.0b1 or install --pre for beta releases
+
(preferably in a virtual environment). To download it, use::
pip download roundup
+.. comment: add roundup==2.6.0b1 or install --pre for beta releases
+
then unpack and test/install from the tarball.
Among the significant enhancements in version 2.6.0 compared to
diff --git a/doc/security.txt b/doc/security.txt
index e46a65443..678ca3b38 100644
--- a/doc/security.txt
+++ b/doc/security.txt
@@ -154,7 +154,7 @@ with 1.6.0 have been moved and are linked below:
.. rst-class:: multicol
-* `2.6.0b1 <../signatures/roundup-2.6.0b1.tar.gz.asc>`_
+* `2.6.0 <../signatures/roundup-2.6.0.tar.gz.asc>`_
* `2.5.0 <../signatures/roundup-2.5.0.tar.gz.asc>`_
* `2.4.0 <../signatures/roundup-2.4.0.tar.gz.asc>`_
* `2.4.0b2 <../signatures/roundup-2.4.0b2.tar.gz.asc>`_
diff --git a/doc/upgrading-history.txt b/doc/upgrading-history.txt
index 20188a597..5e460a288 100644
--- a/doc/upgrading-history.txt
+++ b/doc/upgrading-history.txt
@@ -45,6 +45,57 @@ Contents:
.. contents::
:local:
+.. index:: Upgrading; 1.5.0 to 1.5.1
+
+Migrating from 1.5.0 to 1.5.1
+=============================
+
+User data visibility
+--------------------
+
+For security reasons you should change the permissions on the user
+class. We previously shipped a configuration that allowed users to see
+too many of other users details, including hashed passwords under
+certain circumstances. In schema.py in your tracker, replace the line::
+
+ db.security.addPermissionToRole('User', 'View', 'user')
+
+with::
+
+ p = db.security.addPermission(name='View', klass='user',
+ properties=('id', 'organisation', 'phone', 'realname',
+ 'timezone', 'username'))
+ db.security.addPermissionToRole('User', p)
+
+Note that this removes visibility of user emails, if you want emails to
+be visible you can add 'address' and 'alternate_addresses' to the list
+above.
+
+XSS protection for custom actions
+---------------------------------
+
+If you have defined your own cgi actions in your tracker instance
+(e.g. in a custom ``extensions/spambayes.py`` file) you need to modify
+all cases where client.error_message or client.ok_message are modified
+directly. Instead of::
+
+ self.client.ok_message.append(...)
+
+you need to call::
+
+ self.client.add_ok_message(...)
+
+and the same for::
+
+ self.client.error_message.append(...)
+
+vs.::
+
+ self.client.add_error_message(...)
+
+The new calls escape the passed string by default and avoid XSS security
+issues.
+
.. index:: Upgrading; 1.4.20 to 1.4.21
Migrating from 1.4.20 to 1.4.21
diff --git a/doc/upgrading.txt b/doc/upgrading.txt
index 99f6c5d81..a5ed78c82 100644
--- a/doc/upgrading.txt
+++ b/doc/upgrading.txt
@@ -126,7 +126,7 @@ This release also returns a 405 Method not allowed error for all
methods except GET, HEAD, and POST when querying the main (HTML)
interface. Previously, other methods acted like GET was specified.
-.. comment: _CVE-2026-csrfL:
+.. _CVE-2026-csrfL:
Remediating missing PATCH CSRF protections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -203,7 +203,7 @@ If you are running versions 1.6.0 to version 2.5 the filtering of
history/journal items does not work correctly if the property is
protected by a check function.
-.. comment: _CVE-2026-history_prop:
+.. _CVE-2026-history_propL:
Remediating incomplete property permission check
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -4116,56 +4116,6 @@ your tracker if you wish. It will create a new file in the
current working directory called 'httpd.log' and will rotate
the log file at 500K and keep two old copies of the file.
-.. index:: Upgrading; 1.5.0 to 1.5.1
-
-Migrating from 1.5.0 to 1.5.1
-=============================
-
-User data visibility
---------------------
-
-For security reasons you should change the permissions on the user
-class. We previously shipped a configuration that allowed users to see
-too many of other users details, including hashed passwords under
-certain circumstances. In schema.py in your tracker, replace the line::
-
- db.security.addPermissionToRole('User', 'View', 'user')
-
-with::
-
- p = db.security.addPermission(name='View', klass='user',
- properties=('id', 'organisation', 'phone', 'realname',
- 'timezone', 'username'))
- db.security.addPermissionToRole('User', p)
-
-Note that this removes visibility of user emails, if you want emails to
-be visible you can add 'address' and 'alternate_addresses' to the list
-above.
-
-XSS protection for custom actions
----------------------------------
-
-If you have defined your own cgi actions in your tracker instance
-(e.g. in a custom ``extensions/spambayes.py`` file) you need to modify
-all cases where client.error_message or client.ok_message are modified
-directly. Instead of::
-
- self.client.ok_message.append(...)
-
-you need to call::
-
- self.client.add_ok_message(...)
-
-and the same for::
-
- self.client.error_message.append(...)
-
-vs.::
-
- self.client.add_error_message(...)
-
-The new calls escape the passed string by default and avoid XSS security
-issues.
Migrating from older versions
diff --git a/scripts/Docker/Dockerfile b/scripts/Docker/Dockerfile
index 91de523ba..61fda2333 100644
--- a/scripts/Docker/Dockerfile
+++ b/scripts/Docker/Dockerfile
@@ -233,7 +233,7 @@ ARG pip_mod
LABEL "org.opencontainers.image.vendor"="Roundup Issue Tracker Team" \
"org.opencontainers.image.title"="Roundup Issue Tracker" \
"org.opencontainers.image.description"="Roundup Issue Tracker with multi-backend support installed via $source with python version $pythonversion" \
- "org.opencontainers.image.version"="2.6.0x" \
+ "org.opencontainers.image.version"="2.6.0" \
"org.opencontainers.image.authors"="roundup-devel@lists.sourceforge.net" \
"org.opencontainers.image.licenses"="MIT AND ZPL-2.0 AND Python-2.0" \
"org.opencontainers.image.documentation"="https://www.roundup-tracker.org/docs/installation.html" \
diff --git a/setup.py b/setup.py
index b482215ce..45034bd54 100755
--- a/setup.py
+++ b/setup.py
@@ -210,8 +210,8 @@ def main():
setup(name='roundup',
author="Richard Jones",
author_email="richard@users.sourceforge.net",
- classifiers=[#'Development Status :: 5 - Production/Stable',
- 'Development Status :: 4 - Beta',
+ classifiers=['Development Status :: 5 - Production/Stable',
+ #'Development Status :: 4 - Beta',
#'Development Status :: 3 - Alpha',
'Environment :: Console',
'Environment :: Web Environment',
@@ -220,10 +220,6 @@ def main():
'Intended Audience :: End Users/Desktop',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
- 'License :: OSI Approved',
- 'License :: OSI Approved :: MIT License',
- 'License :: OSI Approved :: Zope Public License',
- 'License :: OSI Approved :: Python Software Foundation License',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
@@ -243,10 +239,10 @@ def main():
],
# Override certain command classes with our own ones
cmdclass={'build_doc': build_doc,
- 'build': build,
- 'bdist_rpm': bdist_rpm,
- 'install_lib': install_lib,
- },
+ 'build': build,
+ 'bdist_rpm': bdist_rpm,
+ 'install_lib': install_lib,
+ },
data_files=data_files,
description="A simple-to-use and -install issue-tracking system"
" with command-line, web and e-mail interfaces. Highly"
@@ -261,8 +257,7 @@ def main():
"extras": ['brotli', 'pytz'],
"test": ['pytest > 7.0.0'],
},
- license="OSI Approved: MIT License, Zope Public License,"
- " Python Software Foundation License",
+ license_expression="MIT AND ZPL-2.0 AND PSF-2.0",
long_description=long_description,
long_description_content_type='text/x-rst',
maintainer="Ralf Schlatterbeck",
@@ -277,7 +272,7 @@ def main():
"Licenses": "https://roundup-tracker.org/docs/license.html",
"Wiki": "https://wiki.roundup-tracker.org/",
},
- python_requires=">=3.7",
+ python_requires=">=3.10",
url='https://www.roundup-tracker.org',
version=__version__,
)
diff --git a/website/www/index.txt b/website/www/index.txt
index d958fc05b..fd5b2e558 100644
--- a/website/www/index.txt
+++ b/website/www/index.txt
@@ -96,15 +96,23 @@ Release Highlights
Some improvements from the 2.6.0 release are:
-* **Filter history entries where permissions are handled by check function**
+ .. comment: `XXXFIXME`: docs/upgrading.html#cve-2026-csrfl
+ CVE hasn't been assigned as of date of release for either
+ of the first two improvements.
+
+* **Fix for missing CSRF protection for PATCH method**
- When a property's permission uses a check command, the history
- of changes for that property were shown. The permissions are now
- properly checked using the check function.
+ The REST interface does not apply CSRF checks when using the PATCH
+ command. See request still in progress at time of release.
+
+* **Filter history entries where permissions are handled by check function**
- .. _`XXXFIXME`: docs/upgrading.html#cve-2025-53865
+ The history of a property change was always shown if the property
+ permissions included a check function. The permissions are now
+ properly checked using the check function. CVE request still in
+ progress at time of release.
-* **Modern CSRF prevention method available**
+* **Modern CSRF prevention method without CSRF tokens available**
This release implements CSRF protection using `Cross-Site Request
Forgery by Filippo Valsorda `_. This
@@ -115,7 +123,7 @@ Some improvements from the 2.6.0 release are:
* **Require reauthentication when making changes to sensitive fields**
You can trigger a reauthentication when the user changes particular
- fields. For example you can rquire a password be entered before the
+ fields. For example you can require a password be entered before the
user changes their password.
* **Classic UI interface modernization.**
@@ -141,7 +149,7 @@ Some improvements from the 2.6.0 release are:
The jinja2 template got an updated copy of bootstrap.
-More info on the 48 changes can be found in the `change notes`_.
+More info on the 49 changes can be found in the `change notes`_.
Roundup Use Cases
=================
diff --git a/website/www/signatures/roundup-2.6.0.tar.gz.asc b/website/www/signatures/roundup-2.6.0.tar.gz.asc
new file mode 100644
index 000000000..da6e4006f
--- /dev/null
+++ b/website/www/signatures/roundup-2.6.0.tar.gz.asc
@@ -0,0 +1,16 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAABCgAdFiEEQR41S10a8mEl1iEiHy3Qy3VqdtgFAmpUYJwACgkQHy3Qy3Vq
+dthrDA//S1SP7mRMxWGGFlzRjtThMLVg2/h7EDhalvo+OH+sQ3JCDoBRZBHItZYC
+X7i/RDVSOVK595FagAnDly7WjHLwzjSYKHuijRvkW1XBL8KroxNQyao0YN5d+PWQ
+6ahbVNwDWOC+/1xzOUDnxjez4MLErxqr5kZnKnPtnJkmXsiLvnTiVX4aX57+buOY
+NF31pHa9GiP65PIRNpk0oeh/TKvzYcnAeO4xkuVvcxkPOlYe0JvUzjhjkfc2caHk
+sN6n+6O9CrZlEYVZA96/O9p2KU3nJzc0bJzAP22T3qESEwaYuq+2GidXq/cYW+jb
+Gr+Nf/nE386zQsNt5we93BwnWwOSNGoPBZlj7uluEnIeY/brYNJ0dl9SKfJ91PQQ
+zNxq5kWUMdYBd7NE6lrVRQ1N0Gwj8YcRWdC2YAyY9xlZKpnrpi1X3yAUUlNlT/q0
+YuJzlHTZtKKTd/LiU8CBWo4u8LvjO53sfUyidiMZbdkOB3r7ofrmNamghBV790Jb
+HfDHnyUZG2ttZ+Ua4upaMl5wog6YNVaR94T2P66wLiSdCmwTBNOUmN/fpSHPu3iF
+OgRcJNc9ZLoUtFGknnUA0cPqAnqgtqPJjFLZT4qQ66sxi23LmZ9DLFamRaa3fK3S
+QGL1FRGOL7X/iNFTVLTpE7UnqtZl7oqoAXydJBNfCi7013ooQ14=
+=03Fl
+-----END PGP SIGNATURE-----
From 6ed1864af1bc63c1a51c068eb2f1321ac962af91 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Mon, 13 Jul 2026 00:29:17 -0400
Subject: [PATCH 536/562] Added tag 2.6.0 for changeset d7abd2cf2be5
---
.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/.hgtags b/.hgtags
index dc3db13d2..4a5f11fac 100644
--- a/.hgtags
+++ b/.hgtags
@@ -157,3 +157,4 @@ c10df5dfed95dc37e8092861886bf66614b77062 2.4.0b1
3bf6ad421347c87ae3a6bebe288f8f1dfa7bd6ba 2.5.0b1
c7a2e01793cdb5228d44df085e3b2f8a73e51c28 2.5.0
174e6163e178598edd2c33c8c051aa03bd3dbf04 2.6.0b1
+d7abd2cf2be584e4869770dfc616c31d249d8b9e 2.6.0
From cc7d0ff4f7d37ac4d3e0073dbb09787c1babb994 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Mon, 13 Jul 2026 08:17:37 -0400
Subject: [PATCH 537/562] test: change header to use normalized encoding.
per: https://github.com/python/cpython/issues/153633
an encoded request for codec iso8859-1 should return a header with
the normalized codec name: iso-8859-1.
---
test/test_mailer.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/test_mailer.py b/test/test_mailer.py
index dadfc362b..c80746a59 100644
--- a/test/test_mailer.py
+++ b/test/test_mailer.py
@@ -9,7 +9,7 @@ def testEncoding(self):
a, c), o)
a('ascii', 'ascii@test.com', 'iso8859-1', 'ascii ')
a(u'café', 'ascii@test.com', 'iso8859-1',
- '=?iso8859-1?q?caf=E9?= ')
+ '=?iso-8859-1?q?caf=E9?= ')
a(u'café', 'ascii@test.com', 'utf-8',
'=?utf-8?b?Y2Fmw6k=?= ')
a('as"ii', 'ascii@test.com', 'iso8859-1', '"as\\"ii" ')
From b23ba18191b62981a2645ac842363257537e365b Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Mon, 13 Jul 2026 09:18:32 -0400
Subject: [PATCH 538/562] test: change header to use normalized encoding. - py
version issue
Add conditional code to handle all Roundup supported python versions.
ref: https://github.com/python/cpython/issues/153633
---
test/test_mailer.py | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/test/test_mailer.py b/test/test_mailer.py
index c80746a59..82f4f2678 100644
--- a/test/test_mailer.py
+++ b/test/test_mailer.py
@@ -1,4 +1,5 @@
#-*- encoding: utf-8 -*-
+import sys
import unittest
from roundup import mailer
@@ -8,8 +9,13 @@ def testEncoding(self):
a = lambda n, a, c, o: self.assertEqual(mailer.nice_sender_header(n,
a, c), o)
a('ascii', 'ascii@test.com', 'iso8859-1', 'ascii ')
- a(u'café', 'ascii@test.com', 'iso8859-1',
- '=?iso-8859-1?q?caf=E9?= ')
+ # FIXME 3.15 remove else case as it will not be needed anymore.
+ if sys.version_info >= (3, 15, 0):
+ a(u'café', 'ascii@test.com', 'iso8859-1',
+ '=?iso-8859-1?q?caf=E9?= ')
+ else:
+ a(u'café', 'ascii@test.com', 'iso8859-1',
+ '=?iso8859-1?q?caf=E9?= ')
a(u'café', 'ascii@test.com', 'utf-8',
'=?utf-8?b?Y2Fmw6k=?= ')
a('as"ii', 'ascii@test.com', 'iso8859-1', '"as\\"ii" ')
From ce3c13611e0b87c13662aa10b2204e5956f8af32 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Mon, 13 Jul 2026 09:20:33 -0400
Subject: [PATCH 539/562] doc: clarify testing requirements
use the test/requirements.txt file.
Old requirements were out of date. Maybe I should reference testing
section of developer docs??
---
doc/installation.txt | 49 +++++++++++++++++++++-----------------------
1 file changed, 23 insertions(+), 26 deletions(-)
diff --git a/doc/installation.txt b/doc/installation.txt
index ed7bdb218..a5cd56b41 100644
--- a/doc/installation.txt
+++ b/doc/installation.txt
@@ -2438,32 +2438,29 @@ Make sure you read the instructions under `UNIX environment steps`_.
Problems? Testing your Python...
================================
-.. note::
- The ``run_tests.py`` script is not packaged in Roundup's source
- distribution anymore. You should install:
-
- * pytest,
- * requests, and
- * mock
-
- using your distributions package manger or using pip/pip2/pip3 to
- install pytest etc. for your Python version. See the
- `administration guide`_ for details.
-
- Remember to have a database user 'rounduptest' prepared (with
- password 'rounduptest'). This user
- must have at least the rights to create and drop databases.
- Documentation: details on `adding MySQL users`_,
- for PostgreSQL you want to call the ``createuser`` command with the
- ``-d`` option to allow database creation.
-
-This can only be done if you `install the source`_ distribution
-(steps 1-3) or from a `mercurial checkout
-<../code.html#get-sources>`_. It will not work if you used `pip
-install` as the test suite is not installed. Once you've unpacked
-roundup's source, if you have pytest installed, run ``python -m
-pytest test`` in the Roundup source directory and make sure there
-are no errors. If there are errors, please let us know!
+This can only be done if you `install the source`_ distribution (steps
+1-3) or from a `mercurial checkout <../code.html#get-sources>`_. It
+will not work if you used `pip install` as the test suite is not
+installed. Once you've unpacked roundup's source, you need to install
+the testing requirements. You probably want to do this in an activated
+virtual environment. This can be done with::
+
+ python -m pip install -r test/requirements.txt
+
+or you can install all the packages listed in requirements.txt using
+your distribution's package manager.
+
+If you are testing postgresql or mysql/mariadb you must have a
+database user 'rounduptest' (with password 'rounduptest'). This user
+must have at least the rights to create and drop databases.
+Documentation: details on `adding MySQL users`_, for PostgreSQL you
+want to call the ``createuser`` command with the ``-d`` option to
+allow database creation. The test suite will skip tests where the
+database driver software is missing.
+
+Then run ``python -m pytest test`` in the Roundup source directory and
+make sure there are no errors. If there are errors, please let us
+know!
Note that redis tests uses database 15 of the redis server running on
localhost.The tests verify that the database is empty before the redis
From 24a56ff54c7852232c168ec8c2f52e880dd07b5e Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Mon, 13 Jul 2026 10:15:04 -0400
Subject: [PATCH 540/562] doc: update some unused badges.
---
website/www/index.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/website/www/index.txt b/website/www/index.txt
index fd5b2e558..636eae006 100644
--- a/website/www/index.txt
+++ b/website/www/index.txt
@@ -32,10 +32,10 @@ Roundup Issue Tracker
-
+
-
+
From 5506a88d3bc2764fee5979dacda00d2da0b7f4b4 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Mon, 13 Jul 2026 11:08:19 -0400
Subject: [PATCH 541/562] doc: fix typo.
---
RELEASE.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/RELEASE.txt b/RELEASE.txt
index be4e8c396..4cfedf93f 100644
--- a/RELEASE.txt
+++ b/RELEASE.txt
@@ -297,8 +297,8 @@ Roundup release checklist:
first and user must be member of rounduptracker org with ability
to publish). Replace -N with the release number (e.g. -1, -2, -3...)
- docker tag rounduptracker/roundup:2.4.0 roundup-tracker/roundup:latest
- docker tag rounduptracker/roundup:2.4.0 roundup-tracker/roundup:2.4.0-N
+ docker tag rounduptracker/roundup:2.4.0 rounduptracker/roundup:latest
+ docker tag rounduptracker/roundup:2.4.0 rounduptracker/roundup:2.4.0-N
docker push rounduptracker/roundup:2.4.0
docker push rounduptracker/roundup:2.4.0-N
docker push rounduptracker/roundup # update roundup:latest
From c43ba79ce129e944c6bce35674429fa804fe89ae Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Tue, 14 Jul 2026 21:03:27 -0400
Subject: [PATCH 542/562] build: update targets for sync/pull to/from
sourceforge
Add make targets that use rsync/sftp do:
sourceforge_dev_sync sync html directory to sourceforce /dev_docs
subdir
sourceforge_prod_sync sync html directory to sourceforce production
website
sourceforge_prod_pull sync sourceforce production website to local
web_html
sourceforge_home_sync sync html directory to
sourceforge:~/roundup_docs
---
website/www/Makefile | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/website/www/Makefile b/website/www/Makefile
index ce282adb6..3b203cd09 100644
--- a/website/www/Makefile
+++ b/website/www/Makefile
@@ -63,23 +63,36 @@ sourceforge_dev_sync: ## sync html directory to sourceforce /dev_docs subdir
# --delete-exclude
# IS NOT (and must not be) SET
read -p "sync to dev_docs y/N? " resp; echo "$$resp" | grep -i "^y"
- rsync -av --no-times --delete --exclude 'docs_backup*' \
- --exclude '.buildinfo' \
- --backup --backup-dir docs_backup-`date --iso-8601=seconds` \
+ # --mkpath doesn't work for rsync on sourceforge so use scripted sftp
+ # if it fails (directory exists), that's ok it still exits with 0
+ printf 'cd /home/project-web/roundup/htdocs\nmkdir dev_docs' | \
+ sftp rouilj@web.sourceforge.net
+ rsync -avz --no-times --delete \
+ --exclude 'docs_backup*' --exclude '.buildinfo' --backup \
+ --backup-dir docs_backup-`date --iso-8601=seconds` \
html/. \
web.sourceforge.net:/home/project-web/roundup/htdocs/dev_docs/.
sourceforge_prod_sync: ## sync html directory to sourceforce production website
read -p "sync to production y/N? " resp; echo "$$resp" | grep -i "^y"
- rsync -av --no-times --delete --exclude 'docs_backup*' \
- --backup --backup-dir docs_backup-`date --iso-8601=seconds` \
- html/. \
+ rsync -avz --no-times --delete --exclude 'docs_backup*' \
+ --exclude 'ahrefs_*' --backup \
+ --backup-dir docs_backup-`date --iso-8601=seconds` \
+ --checksum html/. \
web.sourceforge.net:/home/project-web/roundup/htdocs/.
+sourceforge_prod_pull: ## sync sourceforce production website to local web_html
+ read -p "pull from production y/N? " resp; echo "$$resp" | grep -i "^y"
+ test -d web_html || mkdir web_html
+ rsync -avz --no-times --delete \
+ --checksum \
+ web.sourceforge.net:/home/project-web/roundup/htdocs/. \
+ web_html/.
+
sourceforge_home_sync: ## sync html directory to sourceforge:~/roundup_docs
read -p "sync to home y/N? " resp; echo "$$resp" | grep -i "^y"
- rsync -av --no-times --delete --exclude 'docs_backup*' \
+ rsync -avz --no-times --delete --exclude 'docs_backup*' \
--backup --backup-dir docs_backup-`date --iso-8601=seconds` \
html/. \
web.sourceforge.net:roundup_docs/.
From b62380763213a757d53a62082eb2c9eeb2c9ce88 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 15 Jul 2026 11:08:44 -0400
Subject: [PATCH 543/562] docs: add link to psf license to COPYING.txt and thus
docs/license.html
---
COPYING.txt | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/COPYING.txt b/COPYING.txt
index a123e0f4d..5df83e10a 100644
--- a/COPYING.txt
+++ b/COPYING.txt
@@ -118,8 +118,12 @@ Note link for http://www.zope.com/Marks is dead.
Vendored cgi.py module
----------------------
-This module is licensed under the Python Software Foundation License
-Version 2 as it was extracted from the 3.12 Python distribution.
+This module is licensed under the `Python Software Foundation License
+Version 2`_ as it was extracted from the 3.12 Python distribution.
+
+.. _Python Software Foundation License Version 2:
+ https://opensource.org/license/Python-2.0
+
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
--------------------------------------------
From 7e155367a2126223eec1e34733fb11fb7569c204 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 15 Jul 2026 12:07:47 -0400
Subject: [PATCH 544/562] doc: update website readme with changes to
sourceforge, psf ...
Document Makefile based process for deploying to sourceforge.
Sphinx 8.0 required for building docs.
Update contact info for psf.
Update dns info.
---
website/README.txt | 132 ++++++++++++++++++++++-----------------------
1 file changed, 63 insertions(+), 69 deletions(-)
diff --git a/website/README.txt b/website/README.txt
index 328496c94..4bc90feba 100644
--- a/website/README.txt
+++ b/website/README.txt
@@ -7,102 +7,95 @@ Roundup has three web sites:
www is hosted on SourceForge, issues is hosted on a python software
foundation host and wiki is hosted at waldman-edv.
-updating services hosted on sf.net (www)
+Updating services hosted on sf.net (www)
=================================================
+
Generic SF instructions for web service recommend
uploading files through SFTP, described here:
http://sourceforge.net/p/forge/documentation/Project%20Web%20Services/
-However, SFTP is ugly to script in non-interactive
-mode, so we use SSH access to fetch everything and
-build from server side.
+Since SFTP is ugly to script in non-interactive mode, we used to use
+SSH access to fetch everything and build from server side.
-Working with sf.net
--------------------
-Current docs are taken down with SourceForge Trac,
-so working instructions are available from here:
-http://web.archive.org/web/20140618231150/http://sourceforge.net/apps/trac/sourceforge/wiki/Shell%20service
+As of June 30, 2026, soureforce no longer allows interactive shell
+sessions. So you need to build locally and transfer the built files.
- # log in, replace with your account
- ssh -t ,roundup@shell.sourceforge.net create
+I added some scripted rsync commands to www/Makefile to
+automate install of the html subdir to sourceforge.
- # set project_home
- project_home=/home/project-web/roundup
+ sourceforge_dev_sync sync html directory to sourceforce htdocs/dev_docs
+ subdir
- # pull latest Roundup source with www and wiki
- hg pull -u --cwd ${project_home}/src/roundup
- # see below if this fails with: not trusting file
- # /home/project-web/roundup/src/roundup/.hg/hgrc from untrusted
- # user 110231, group 48
+ sourceforge_prod_sync sync html directory to sourceforce production
+ website
- # read up on other people changes and add yours
- cd ${project_home}
- vim logbuch.txt
+ sourceforge_prod_pull sync sourceforce production website to local
+ web_html
-[ Note: all the files in the project home except htdocs that make up
- the website were gone. I created a new logbuch.txt file. We need to
- build the docs outside the sourceforge envirnment and rsync them in
- as there is no longer a working sphinx environment. ]
+ sourceforge_home_sync sync html directory to
+ sourceforge:~/roundup_docs
-If you get a "not trusting" error the problem is that the .hg files in
-use are not owned by you and hg won't use them. Add this to your
-~/.hgrc file (create file if needed)
+These commands should preserve the file htdocs/ahref*. If you move the
+current htdocs/ directory using sftp (and then create a new empty
+htdocs), you need to copy the ahref* file from the current production
+tree to the new directory so we keep some level of analytics.
-[trusted]
-groups=48
-users=110231
+Note that sourceforge_prod_sync should create a backup for each
+original file in a dated docs_backup-. So should be able to
+recover the website by:
-if the uid/gid changes you may have to change the values.
-See: https://www.mercurial-scm.org/wiki/Trust for details
+ * run `make sourceforge_prod_pull`
+ * in the web_html subdirectory, move the files from the
+ docs_backup-.... subdir to ther place in web_html
+ * replace the www/html directory with www/web_html
+ * run make sourceforge_prod_sync
-When done working in the sf shell, you can destroy it early
-to free resources:
+Reverting a sync over SFTP is painful, hence the workflow to copy it
+back to your local host.
- shutdown
+If you need to do the changes on the sourceforge site, I suggest using
+the lftp program with the 'sftp://yourUsername@web.sourceforge.net'
+rather than the sftp program as lftp supports recursive directory
+removal and other useful features.
-updating www.roundup-tracker.org
----------------------------------
-Note that sourceforge still only has python2 available on it's
-systems. Doc updates probably need to be done by building on local
-machine using modern Sphinx (7.x or greater) and the generated files
-pushed to the website.
+Updating the Documentation
+--------------------------
-Also the files htdocs/ahref* and htdocs/google* have to be copied from
-the current production tree to the new directory so we keep some level
-of analytics.
+Site update requires rebuilding HTML files. For that `sphinx` version
+8 or newer is required. You can use the website/www/requirements.pip
+file to set up sphinx: `python -m pip install -r requirements.pip` in
+a venv. If you install sphinx into a virtual environment, use:
------
+ PATH=/path/to/venv/bin/sphinx-build:$PATH make
-Site update requires rebuilding HTML files. For that
-`sphinx` is required/
-Hopefully, it is already installed into virtualenv, so
-the whole procedure looks like so:
+when `make` is used below. Also you should run make in the doc
+directory beforehand to generate html pages used by the website build
+(e.g. man pages, config.ini documentation...).
+
+The whole procedure starting from the root of a current checked out
+source tree looks like so:
- # activate the virtualenv
- . ${project_home}/docbuilder/bin/activate
- # cd to website source and build it
- cd ${project_home}/src/roundup/website/www
hg up # make sure you are using the released code
+ cd doc
+ make clean
+ make
+ # cd to website source and build it
+ cd ../website/www
make clean
make html
# you can check which files updated (the date will change with many files)
- #diff -ur --brief ${project_home}/htdocs/ ./html/
+ #make sourceforge_prod_pull
+ #diff -ur --brief web_html ./html/
# copy to website dir
- cp -r -p ./html/* ${project_home}/htdocs/
- # copy legacy html doc to website docs/ dir
- # (in main doc/conf.py this is done automatically)
- cp -r -p ../../doc/html_extra/* ${project_home}/htdocs/docs/
- # or try it with rsync (skip --dry-run when ready)
- #rsync --dry-run -v --checksum --recursive ./html/* ${project_home}/htdocs/
-
+ make sourceforge_prod_sync
-If you are releasing an alpha/beta release, don't update:
+If you are generating the docs for an alpha/beta release, use
- ${project_home}/htdocs/docs/
+ make sourceforge_dev_sync
-instead update:
+instead of `make sourceforge_prod_sync` to update:
- ${project_home}/htdocs/dev-docs/
+ htdocs/dev-docs/
and the URL will be: https://www.roundup-tracker.org/dev-docs/docs.html
@@ -111,7 +104,7 @@ need to use:
https://www.roundup-tracker.org/dev-docs/docs.html?foo=1
-to cache bust.
+to cache bust if you do multiple deploys and are seeing an older version.
Updating issues.roundup-tracker.org
===================================
@@ -145,7 +138,8 @@ The one used by PSF infrastrcuture is:
https://github.com/psf/bpo-tracker-roundup
-Contact ee-durbin (or psf infra) for an invite to their repo.
+Contact psf infra https://infra.psf.io/overview.html (email:
+infrastructure-staff at python dot org) for an invite to their repo.
Usually testing is done with: the "website/issues" section
of Roundup's Mercurical SCM repository and copied manually to the live
@@ -217,5 +211,5 @@ Thomas Waldman is also our DNS manager. All changes should go to him
at email: info AT waldmann-edv DOT de.
Richard Jones still owns/pays for the roundup-tracker.org domain.
-It expires on: 2026-01-06T10:49:58Z.
+It expires on: 2027-01-06T10:49:58Z.
From 4203ef7f1657ff776af5371223ce5d74cad8aefe Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 15 Jul 2026 12:57:55 -0400
Subject: [PATCH 545/562] build: verify new enough setuptools used
I updated setup.py to to use the newer License-expression, but my env
still had an older setuptools that didn't support making a PKG-INFO
using it.
So the 2.6.0 release is missing some metadata. It's not critical
enough since I have a licensing link that allows users to find it.
It's just that automatic tools may not see it.
---
setup.py | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/setup.py b/setup.py
index 45034bd54..6de0390b1 100755
--- a/setup.py
+++ b/setup.py
@@ -19,11 +19,12 @@
#
import os
+import setuptools
import sys
-from glob import glob
-from sysconfig import get_path
+from glob import glob
from setuptools import setup
+from sysconfig import get_path
from roundup.dist.command.bdist_rpm import bdist_rpm
from roundup.dist.command.build import build, list_message_files
@@ -31,6 +32,12 @@
from roundup.dist.command.install_lib import install_lib
+# verify we have a version of setuptools that implnts version 2.4 of metadata
+if not tuple(int(x) for x in setuptools.__version__.split('.')) > (77, 0, 0):
+ raise Exception('Install a version of setuptools > 77.0.0 that supports '
+ 'metadata\n version 2.4 or newer. Installed version is: %s' %
+ setuptools.__version__ )
+
def include(d, e):
"""Generate a pair of (directory, file-list) for installation.
From 61192588901e5f2d2a2e8f727e2dd8ad7668364a Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 15 Jul 2026 22:00:10 -0400
Subject: [PATCH 546/562] fix: cgi failures on null path; config changes;
handle exception
Handle case where request.path is ""
(https://tracker.example.com):(path is = "" not missing). Make it the
same as "/". Also refactored to remove redundant os.environ.get().
fix handling of exceptions from Cient to use http default exception
message and generate useful 400 HTML responses rather than tracebacks
or "something went wrong" messages.
Generate proper HTML with content-length header for 403 unauthorized
and 404 not found. Provide fallback except Exception handler for other
exceptions.
Set up single commentable lines for configuring timing and move below
tracker setup stanza.
ruff fixes - sort imports, whitespace, moved 3 import os to top of file.
---
frontends/roundup.cgi | 64 ++++++++++++++++++++++++++++++-------------
1 file changed, 45 insertions(+), 19 deletions(-)
diff --git a/frontends/roundup.cgi b/frontends/roundup.cgi
index 89fe1061d..7655a7cdc 100755
--- a/frontends/roundup.cgi
+++ b/frontends/roundup.cgi
@@ -16,12 +16,14 @@
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+import os
import sys
import time
# If roundup is not on your normal path, add it here.
# sys.path.append('/home/username/develop/roundup_dev')
from roundup import version_check # noqa: F401
+from roundup.anypy import http_
from roundup.anypy.html import html_escape
from roundup.anypy.strings import StringIO, s2b
from roundup.i18n import _
@@ -49,18 +51,18 @@ from roundup.i18n import _
# stderr) or to the web client (via cgitb).
DEBUG_TO_CLIENT = False
-# Return timing information to the client.
-# Set TIMING to:
-# "" - Do not sent timing info to client. (Default)
-# "COMMENT" - Hide timing in html comment, view source to see it.
-# "INLINE" - Display timing at bottom of web page
-TIMING = ""
-
# This indicates where the Roundup tracker lives
TRACKER_HOMES = {
# 'example': '/path/to/example',
}
+# print timing at bottom of web page
+#TIMING = "INLINE"
+# print timing inside web page comments
+#TIMING = "COMMENT"
+# disable timing
+TIMING = ""
+
# Where to log debugging information to. Use an instance of DevNull if you
# don't want to log anywhere.
@@ -82,6 +84,7 @@ LOG = DevNull()
## end configuration
#
+DEFAULT_ERROR_MESSAGE = http_.server.DEFAULT_ERROR_MESSAGE
#
# Set up the error handler
@@ -102,7 +105,6 @@ except ImportError:
# Check environment for config items
#
def checkconfig():
- import os
global TRACKER_HOMES, LOG
# see if there's an environment var. ROUNDUP_INSTANCE_HOMES is the
@@ -138,6 +140,7 @@ class RequestWrapper:
def __init__(self, wfile):
self.rfile = sys.stdin
self.wfile = wfile
+ self.headers = {}
def write(self, data):
self.wfile.write(data)
@@ -162,8 +165,6 @@ class RequestWrapper:
# Main CGI handler
#
def main(out, err):
- import os
-
import roundup.cgi.client
import roundup.instance
@@ -195,8 +196,10 @@ def main(out, err):
out.write(s2b(error_body))
return
- path = os.environ.get('PATH_INFO', '/').split('/')
request.path = os.environ.get('PATH_INFO', '/')
+ if not request.path: # missing trailing /
+ request.path = "/"
+ path = request.path.split('/')
tracker = path[1]
os.environ['TRACKER_NAME'] = tracker
os.environ['PATH_INFO'] = '/'.join(path[2:])
@@ -217,22 +220,46 @@ def main(out, err):
else:
tracker_home = TRACKER_HOMES[tracker]
tracker = roundup.instance.open(tracker_home)
- if hasattr(tracker, 'Client'):
- client = tracker.Client(tracker, request, os.environ)
- else:
- client = roundup.cgi.client.Client(tracker, request, os.environ)
+ try:
+ if hasattr(tracker, 'Client'):
+ client = tracker.Client(tracker, request, os.environ)
+ else:
+ client = roundup.cgi.client.Client(tracker,
+ request, os.environ)
+ except ValueError as e:
+ code = 400
+ message = str(e)
+ explain = "The value for the header is unacceptable"
+ body = DEFAULT_ERROR_MESSAGE % locals()
+ request.send_response(code)
+ request.send_header('Content-Type', 'text/html')
+ request.send_header('Content-Length', '%s' % len(body))
+ request.end_headers()
+ out.write(s2b(body))
+
try:
client.main()
except roundup.cgi.client.Unauthorised:
+ body = b'Unauthorised'
request.send_response(403)
request.send_header('Content-Type', 'text/html')
+ request.send_header('Content-Length', '%s' % len(body))
request.end_headers()
- out.write(b'Unauthorised')
+ out.write(body)
except roundup.cgi.client.NotFound:
+ body = s2b('Not found: %s' % html_escape(client.path))
request.send_response(404)
request.send_header('Content-Type', 'text/html')
+ request.send_header('Content-Length', '%s' % len(body))
+ request.end_headers()
+ out.write(body)
+ except Exception as e:
+ body = s2b('Error: %s' % html_escape(e))
+ request.send_response(400)
+ request.send_header('Content-Type', 'text/html')
+ request.send_header('Content-Length', '%s' % len(body))
request.end_headers()
- out.write(s2b('Not found: %s' % html_escape(client.path)))
+ out.write(body)
else:
from roundup.anypy import urllib_
@@ -259,7 +286,6 @@ try:
# force input/output to binary (important for file up/downloads)
if sys.platform == "win32":
import msvcrt
- import os
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
checkconfig()
@@ -271,7 +297,7 @@ try:
main(out_buf, err)
except SystemExit:
pass
-except:
+except Exception as e:
sys.stdout, sys.stderr = out, err
out.write('Content-Type: text/html\n\n')
if DEBUG_TO_CLIENT:
From e4b7d8e1c245816035dc6fa714eeeb5b9e33d6d5 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 15 Jul 2026 22:25:31 -0400
Subject: [PATCH 547/562] chore(ruff): mark zip w/o strict ok; remove unused
noqa references.
The use of zip here without strict is ok.
---
roundup/anypy/cmp_.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/roundup/anypy/cmp_.py b/roundup/anypy/cmp_.py
index 5c4f4a679..f88ecfee1 100644
--- a/roundup/anypy/cmp_.py
+++ b/roundup/anypy/cmp_.py
@@ -12,7 +12,7 @@ class NoneAndDictComparable(object): # noqa: PLW1641
def __init__(self, value):
self.value = value
- def __cmp__(self, other): # noqa: PLW3201, PLR0911
+ def __cmp__(self, other): # noqa: PLR0911
if not isinstance(other, self.__class__):
raise TypeError('not comparable')
@@ -26,7 +26,7 @@ def __cmp__(self, other): # noqa: PLW3201, PLR0911
return 1
elif type(self.value) is tuple and type(other.value) is tuple:
- for lhs, rhs in zip(self.value, other.value):
+ for lhs, rhs in zip(self.value, other.value): # noqa: B905
lhsCmp = NoneAndDictComparable(lhs)
rhsCmp = NoneAndDictComparable(rhs)
result = lhsCmp.__cmp__(rhsCmp)
@@ -72,7 +72,7 @@ def __gt__(self, other):
def _test():
- # ruff: noqa: S101, B011, PLC0415, PLR2004
+ # ruff: noqa: S101, B011, PLC0415
import sys
_py3 = sys.version_info[0] > 2
From 507693e2cf760e459b1038e368d70cad9445a561 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 15 Jul 2026 22:43:53 -0400
Subject: [PATCH 548/562] refactor: add strict=true to zip()
The zip should never have an unequal number of list_vars and matched
groups. Code that runs before this should produce a 404 error
for something like rest/data/*/1.
---
roundup/rest.py | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/roundup/rest.py b/roundup/rest.py
index 74e6189d2..c9d0b0df0 100644
--- a/roundup/rest.py
+++ b/roundup/rest.py
@@ -421,10 +421,15 @@ def execute(cls, instance, path, method, input_payload):
func = func_obj['func']
# zip the varlist into a dictionary, and pass it to the caller
- # FIXME: 3.10 is min version- add strict=True to zip
- # also wrap with try/except ValueError if different number of
- # items (which should never happen).
- args = dict(zip(list_vars, match_obj.groups()))
+ try:
+ args = dict(zip(list_vars, match_obj.groups(), strict=True))
+ except ValueError:
+ # Match was unable to make sense out of the path
+ # This should never happen as a 404 should be reported
+ # before we get here.
+ raise Reject(
+ _("Internal error: Unable to understand URL: %s") % path)
+
args['input_payload'] = input_payload
return func(instance, **args)
raise NotFound('Nothing matches the given URI')
From 9e3331de1ae5164e0b86d845b61be26ccc623777 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 15 Jul 2026 22:50:23 -0400
Subject: [PATCH 549/562] refactor: set strict=True for zip()
AFAICT the zipped elements should be equal in all cases.
---
roundup/hyperdb.py | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/roundup/hyperdb.py b/roundup/hyperdb.py
index de8645a67..068a31f39 100644
--- a/roundup/hyperdb.py
+++ b/roundup/hyperdb.py
@@ -892,10 +892,8 @@ def _sort(self, val):
curdir = sa.sort_direction
idx += 1
sortattr.append(val)
- # FIXME 3.10 add strict=True parameter to zip()
- sortattr = zip(*sortattr)
- # FIXME 3.10 add strict=True parameter to zip()
- for direction, i in reversed(list(zip(directions, dir_idx))):
+ sortattr = zip(*sortattr, strict=True)
+ for direction, i in reversed(list(zip(directions, dir_idx, strict=True))):
rev = direction == '-'
sortattr = sorted(sortattr,
key=lambda x: NoneAndDictComparable(x[i:idx]),
From 807729dd07f8ea69d5f9d1a3a7fcaa34cac0f468 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 15 Jul 2026 22:53:30 -0400
Subject: [PATCH 550/562] refactor: set strict=True for zip()
AFAICT the zipped elements (hmac digests) should have equal lengths.
---
roundup/password.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/roundup/password.py b/roundup/password.py
index ebfc1520c..ae2a67f41 100644
--- a/roundup/password.py
+++ b/roundup/password.py
@@ -101,7 +101,7 @@ def _pbkdf2_sha512(password, salt, rounds, keylen):
def xor_bytes(left, right):
"perform bitwise-xor of two byte-strings"
return _bjoin(bchr(bord(l) ^ bord(r))
- for l, r in zip(left, right)) # noqa: E741
+ for l, r in zip(left, right, strict=True)) # noqa: E741
def _pbkdf2(password, salt, rounds, keylen, sha=sha1):
if sha not in [sha1, sha512]:
From cf86771468cd5fe85e7f2a48fd68d104f3496f46 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 15 Jul 2026 22:55:42 -0400
Subject: [PATCH 551/562] doc: add comment about zip and strict condition.
---
roundup/anypy/cmp_.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/roundup/anypy/cmp_.py b/roundup/anypy/cmp_.py
index f88ecfee1..bcf4d22d7 100644
--- a/roundup/anypy/cmp_.py
+++ b/roundup/anypy/cmp_.py
@@ -26,6 +26,8 @@ def __cmp__(self, other): # noqa: PLR0911
return 1
elif type(self.value) is tuple and type(other.value) is tuple:
+ # this zip should not have strict=true; length comparison
+ # used at end handles the unequal value case.
for lhs, rhs in zip(self.value, other.value): # noqa: B905
lhsCmp = NoneAndDictComparable(lhs)
rhsCmp = NoneAndDictComparable(rhs)
From cd279d76e5cadddbe858f908ad9e5a7ead880780 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 15 Jul 2026 22:58:23 -0400
Subject: [PATCH 552/562] refactor: add strict=True to zip.
length of both items is same. Checked 8 lines above.
---
roundup/cgi/actions.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/roundup/cgi/actions.py b/roundup/cgi/actions.py
index d5a88312f..0243772c8 100644
--- a/roundup/cgi/actions.py
+++ b/roundup/cgi/actions.py
@@ -564,7 +564,7 @@ def handle(self):
# extract the new values
d = {}
- for name, value in zip(props_without_id, values):
+ for name, value in zip(props_without_id, values, strict=True):
# check permission to edit this property on this item
if exists and not self.hasPermission('Edit', itemid=itemid,
classname=self.classname,
From 1af55802b42fcdb8719cb3aa4c98f8ca31d4fc85 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 15 Jul 2026 23:01:01 -0400
Subject: [PATCH 553/562] refactor: add strict=True to zip.
length of both Interval.get_tuple() is same.
---
roundup/date.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/roundup/date.py b/roundup/date.py
index 89e339702..eda57407f 100644
--- a/roundup/date.py
+++ b/roundup/date.py
@@ -964,7 +964,7 @@ def __add__(self, other):
asgn = a[0]
b = other.get_tuple()
bsgn = b[0]
- i = [asgn*x + bsgn*y for x, y in zip(a[1:], b[1:])]
+ i = [asgn*x + bsgn*y for x, y in zip(a[1:], b[1:], strict=True)]
i.insert(0, 1)
i = fixTimeOverflow(i)
return Interval(i, translator=self.translator)
@@ -984,7 +984,7 @@ def __sub__(self, other):
asgn = a[0]
b = other.get_tuple()
bsgn = b[0]
- i = [asgn*x - bsgn*y for x, y in zip(a[1:], b[1:])]
+ i = [asgn*x - bsgn*y for x, y in zip(a[1:], b[1:], strict=True)]
i.insert(0, 1)
i = fixTimeOverflow(i)
return Interval(i, translator=self.translator)
From 39120d179c3b417c1758ec672fc03511287dd7a2 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Thu, 16 Jul 2026 18:27:38 -0400
Subject: [PATCH 554/562] chore(ruff): whitespace fixes.
---
frontends/wsgi.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/frontends/wsgi.py b/frontends/wsgi.py
index ffc0e72d6..79caf8eaa 100644
--- a/frontends/wsgi.py
+++ b/frontends/wsgi.py
@@ -15,8 +15,8 @@
# Enable the feature flag to speed up wsgi response by caching the
# Roundup tracker instance on startup. See upgrading.txt for
# more info.
-feature_flags = { "cache_tracker": "" }
+feature_flags = {"cache_tracker": ""}
# Definition signature for app: app(environ, start_response):
# If using apache mod_wsgi change app to application.
-app = RequestDispatcher(tracker_home, feature_flags=feature_flags)
+app = RequestDispatcher(tracker_home, feature_flags=feature_flags)
From cc5773b79a32f44c9ce8027242a5a54136c443f6 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Thu, 16 Jul 2026 18:30:26 -0400
Subject: [PATCH 555/562] chore(ruff): whitespace fixes; elide else: where
possible.
---
frontends/ZRoundup/ZRoundup.py | 76 +++++++++++++++++++++-------------
1 file changed, 47 insertions(+), 29 deletions(-)
diff --git a/frontends/ZRoundup/ZRoundup.py b/frontends/ZRoundup/ZRoundup.py
index 27b35b296..6d90550e1 100644
--- a/frontends/ZRoundup/ZRoundup.py
+++ b/frontends/ZRoundup/ZRoundup.py
@@ -13,7 +13,7 @@
# FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-#
+#
''' ZRoundup module - exposes the roundup web interface to Zope
This frontend works by providing a thin layer that sits between Zope and the
@@ -26,15 +26,15 @@
advantages over regular CGI :)
'''
-from roundup.anypy import urllib_
-
-from Globals import InitializeClass, HTMLFile
-from OFS.SimpleItem import Item
+from AccessControl import ClassSecurityInfo, ModuleSecurityInfo
+from Acquisition import Implicit
+from Globals import HTMLFile, InitializeClass
from OFS.PropertyManager import PropertyManager
-from Acquisition import Explicit, Implicit
+from OFS.SimpleItem import Item
from Persistence import Persistent
-from AccessControl import ClassSecurityInfo
-from AccessControl import ModuleSecurityInfo
+
+from roundup.anypy import urllib_
+
modulesecurity = ModuleSecurityInfo()
import roundup.instance
@@ -45,6 +45,8 @@
manage_addZRoundupForm = HTMLFile('dtml/manage_addZRoundupForm', globals())
modulesecurity.declareProtected('Add Z Roundups', 'manage_addZRoundup')
+
+
def manage_addZRoundup(self, id, instance_home, REQUEST):
"""Add a ZRoundup product """
# validate the instance_home
@@ -52,25 +54,31 @@ def manage_addZRoundup(self, id, instance_home, REQUEST):
self._setObject(id, ZRoundup(id, instance_home))
return self.manage_main(self, REQUEST)
+
class RequestWrapper:
'''Make the Zope RESPONSE look like a BaseHTTPServer
'''
def __init__(self, RESPONSE):
self.RESPONSE = RESPONSE
self.wfile = self.RESPONSE
+
def send_response(self, status):
self.RESPONSE.setStatus(status)
+
def send_header(self, header, value):
self.RESPONSE.addHeader(header, value)
+
def end_headers(self):
# not needed - the RESPONSE object handles this internally on write()
pass
+
def start_response(self, headers, response):
self.send_response(response)
for key, value in headers:
self.send_header(key, value)
self.end_headers()
+
class FormItem:
'''Make a Zope form item look like a cgi.py one
'''
@@ -80,11 +88,13 @@ def __init__(self, value):
self.filename = self.value.filename
self.value = self.value.read()
+
class FormWrapper:
'''Make a Zope form dict look like a cgi.py one
'''
def __init__(self, form):
self.__form = form
+
def __getitem__(self, item):
entry = self.__form[item]
if isinstance(entry, type([])):
@@ -92,26 +102,30 @@ def __getitem__(self, item):
else:
entry = FormItem(entry)
return entry
+
def __iter__(self):
return iter(self.__form)
+
def getvalue(self, key, default=None):
if key in self.__form:
return self.__form[key]
- else:
- return default
+ return default
+
def has_key(self, item):
return item in self.__form
+
def keys(self):
return list(self.__form.keys())
def __repr__(self):
- return ''%self.__form
+ return '' % self.__form
+
class ZRoundup(Item, PropertyManager, Implicit, Persistent):
'''An instance of this class provides an interface between Zope and
roundup for one roundup instance
'''
- meta_type = 'Z Roundup'
+ meta_type = 'Z Roundup'
security = ClassSecurityInfo()
def __init__(self, id, instance_home):
@@ -120,19 +134,20 @@ def __init__(self, id, instance_home):
# define the properties that define this object
_properties = (
- {'id':'id', 'type': 'string', 'mode': 'w'},
- {'id':'instance_home', 'type': 'string', 'mode': 'w'},
+ {'id': 'id', 'type': 'string', 'mode': 'w'},
+ {'id': 'instance_home', 'type': 'string', 'mode': 'w'},
)
property_extensible_schema__ = 0
# define the tabs for the management interface
- manage_options= PropertyManager.manage_options + (
- {'label': 'View', 'action':'index_html'},
+ manage_options = PropertyManager.manage_options + (
+ {'label': 'View', 'action': 'index_html'},
) + Item.manage_options
icon = "misc_/ZRoundup/icon"
security.declarePrivate('roundup_opendb')
+
def roundup_opendb(self):
'''Open the roundup instance database for a transaction.
'''
@@ -141,17 +156,17 @@ def roundup_opendb(self):
env = self.REQUEST.environ
# figure out the path components to set
- url = urllib_.urlparse( self.absolute_url() )
+ url = urllib_.urlparse(self.absolute_url())
path = url[2]
- path_components = path.split( '/' )
+ path_components = path.split('/')
# special case when roundup is '/' in this virtual host,
- if path == "/" :
+ if path == "/":
env['SCRIPT_NAME'] = "/"
env['TRACKER_NAME'] = ''
- else :
+ else:
# all but the last element is the path
- env['SCRIPT_NAME'] = '/'.join( path_components[:-1] )
+ env['SCRIPT_NAME'] = '/'.join(path_components[:-1])
# the last element is the name
env['TRACKER_NAME'] = path_components[-1]
@@ -161,20 +176,21 @@ def roundup_opendb(self):
return client.Client(tracker, request, env, form)
security.declareProtected('View', 'index_html')
+
def index_html(self):
'''Alias index_html to roundup's index
'''
# Redirect misdirected requests -- bugs 558867 , 565992
# PATH_INFO, as defined by the CGI spec, has the *real* request path
orig_path = self.REQUEST.environ['PATH_INFO']
- if orig_path[-1] != '/' :
- url = urllib_.urlparse( self.absolute_url() )
- url = list( url ) # make mutable
- url[2] = url[2]+'/' # patch
- url = urllib_.urlunparse( url ) # reassemble
+ if orig_path[-1] != '/':
+ url = urllib_.urlparse(self.absolute_url())
+ url = list(url) # make mutable
+ url[2] = url[2] + '/' # patch
+ url = urllib_.urlunparse(url) # reassemble
RESPONSE = self.REQUEST.RESPONSE
- RESPONSE.setStatus( "MovedPermanently" ) # 301
- RESPONSE.setHeader( "Location" , url )
+ RESPONSE.setStatus("MovedPermanently") # 301
+ RESPONSE.setHeader("Location", url)
return RESPONSE
client = self.roundup_opendb()
@@ -187,6 +203,7 @@ def __getitem__(self, item):
'''
return PathElement(self, item).__of__(self)
+
class PathElement(Item, Implicit):
def __init__(self, zr, path):
self.zr = zr
@@ -204,7 +221,7 @@ def index_html(self, REQUEST=None):
client = self.zr.roundup_opendb()
# fake the path that roundup should use
client.path = self.path
- # and call roundup to do something
+ # and call roundup to do something
client.main()
return ''
except client.NotFound:
@@ -216,6 +233,7 @@ def index_html(self, REQUEST=None):
# all other exceptions in roundup are valid
raise
+
InitializeClass(ZRoundup)
modulesecurity.apply(globals())
From d71062f6a1658f492286de05aa7a25802b032bba Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Thu, 16 Jul 2026 18:31:58 -0400
Subject: [PATCH 556/562] chore(ruff): whitespace fixes
---
frontends/ZRoundup/__init__.py | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/frontends/ZRoundup/__init__.py b/frontends/ZRoundup/__init__.py
index 29c64d411..c56b91c12 100644
--- a/frontends/ZRoundup/__init__.py
+++ b/frontends/ZRoundup/__init__.py
@@ -13,10 +13,11 @@
# FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-#
-__version__='1.1'
+#
+__version__ = '1.1'
import os
+
# figure where ZRoundup is installed
here = None
if 'INSTANCE_HOME' in os.environ:
@@ -35,20 +36,24 @@
raise ValueError("Can't determine where ZRoundup is installed")
# product initialisation
-from .ZRoundup import ZRoundup, manage_addZRoundupForm, manage_addZRoundup
+from .ZRoundup import ZRoundup, manage_addZRoundup, manage_addZRoundupForm
+
+
def initialize(context):
context.registerClass(
ZRoundup,
- meta_type = 'Z Roundup',
- constructors = (
+ meta_type='Z Roundup',
+ constructors=(
manage_addZRoundupForm, manage_addZRoundup
)
)
+
# set up the icon
from ImageFile import ImageFile
+
misc_ = {
- 'icon': ImageFile('icons/tick_symbol.gif', path),
+ 'icon': ImageFile('icons/tick_symbol.gif', path),
}
From 4e62e228b1b18ac932a5925b12b405e7395adc62 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Thu, 16 Jul 2026 18:36:31 -0400
Subject: [PATCH 557/562] chore(ruff): whitespace fixes; sort import; "a
string".split() to list
---
setup.py | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/setup.py b/setup.py
index 6de0390b1..bf5062789 100755
--- a/setup.py
+++ b/setup.py
@@ -19,24 +19,24 @@
#
import os
-import setuptools
import sys
-
from glob import glob
-from setuptools import setup
from sysconfig import get_path
+import setuptools
+from setuptools import setup
+
from roundup.dist.command.bdist_rpm import bdist_rpm
from roundup.dist.command.build import build, list_message_files
from roundup.dist.command.build_doc import build_doc
from roundup.dist.command.install_lib import install_lib
-
# verify we have a version of setuptools that implnts version 2.4 of metadata
if not tuple(int(x) for x in setuptools.__version__.split('.')) > (77, 0, 0):
raise Exception('Install a version of setuptools > 77.0.0 that supports '
'metadata\n version 2.4 or newer. Installed version is: %s' %
- setuptools.__version__ )
+ setuptools.__version__)
+
def include(d, e):
"""Generate a pair of (directory, file-list) for installation.
@@ -66,8 +66,8 @@ def make_data_files_absolute(data_files, prefix, enable=False):
like: /usr/local/share/man, docs in /usr/local/share/doc/roundup,
templates in /usr/local/share/roundup/templates.
"""
- new_data_files = [ (os.path.join(prefix,df[0]),df[1])
- for df in data_files ]
+ new_data_files = [(os.path.join(prefix, df[0]), df[1])
+ for df in data_files]
if enable:
return new_data_files
return data_files
@@ -166,7 +166,7 @@ def main():
templates = [t['path']
for t in listTemplates('share/roundup/templates').values()]
for tdir in templates:
- for idir in '. detectors extensions html html/layout static'.split():
+ for idir in ['.', 'detectors', 'extensions', 'html', 'html/layout', 'static']:
data_files.append(include(os.path.join(tdir, idir), '*'))
# add message files
From bd8c9c30f4fb73973eec3434e0fc6f2bb3c55daf Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Thu, 16 Jul 2026 18:40:46 -0400
Subject: [PATCH 558/562] chore(ruff): remove unused import.
---
demo.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/demo.py b/demo.py
index 861b504e3..13aba73e2 100755
--- a/demo.py
+++ b/demo.py
@@ -1,6 +1,5 @@
#!/usr/bin/env python3
import sys
-import roundup
from roundup.demo import main
From 7fe4016edff25908edc5410a01c9bc1f8dfef5ec Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 22 Jul 2026 01:37:05 -0400
Subject: [PATCH 559/562] chore(build): bump github/codeql-action/upload-sarif
from 4.36.3 to 4.37.0 (pull #90)
---
.github/workflows/anchore.yml | 2 +-
.github/workflows/ossf-scorecard.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/anchore.yml b/.github/workflows/anchore.yml
index fcf3fea90..7f62ff8d8 100644
--- a/.github/workflows/anchore.yml
+++ b/.github/workflows/anchore.yml
@@ -52,7 +52,7 @@ jobs:
fail-build: true
- name: Upload Anchore Scan Report
if: always()
- uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
+ uses: github/codeql-action/upload-sarif@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
sarif_file: ${{ steps.scan.outputs.sarif }}
- name: Inspect action SARIF report
diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml
index cbe91b2fb..fcd4b7926 100644
--- a/.github/workflows/ossf-scorecard.yml
+++ b/.github/workflows/ossf-scorecard.yml
@@ -70,6 +70,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
+ uses: github/codeql-action/upload-sarif@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
sarif_file: results.sarif
From 10d6ebfb8a948e98a64a9139dcc979148d0795c6 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 22 Jul 2026 01:37:49 -0400
Subject: [PATCH 560/562] chore(build): bump github/codeql-action/analyze from
4.36.3 to 4.37.0bump github/codeql-action/upload-sarif from 4.36.3 to 4.37.0
(pull #91)
---
.github/workflows/codeql-analysis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 1e268c992..1e27a2114 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -80,4 +80,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
+ uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
From 19d5f311dc2b1ec481a2bdbd9484ecb2db1fe768 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 22 Jul 2026 01:39:06 -0400
Subject: [PATCH 561/562] chore(build): bump github/codeql-action/autobuild
from 4.36.3 to 4.37.0 (pull #92)
---
.github/workflows/codeql-analysis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 1e27a2114..984578a9e 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -66,7 +66,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
+ uses: github/codeql-action/autobuild@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
From 90a69a21ef8b38b64d92c42c295b687dca5f8899 Mon Sep 17 00:00:00 2001
From: John Rouillard
Date: Wed, 22 Jul 2026 01:39:45 -0400
Subject: [PATCH 562/562] chore(build): bump github/codeql-action/init from
4.36.3 to 4.37.0 (pull #93)
---
.github/workflows/codeql-analysis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 984578a9e..918184dc3 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -55,7 +55,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
+ uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.