project manager user manual
installation of pjm
to installing this tool open a console window and run the following command:
pip install aedev_project_manager
after the installation the commands project-manager and its shortcut pjm will be available in your OS console.
usage of pjm
pjm is supporting you on all devops (development operations) of your python library, application and web projects.
this covers all actions done on your local machine, on your repository host servers (like gitlab.com
or github.com) and on your web and application deployment servers, like:
creating new projects
maintaining and upgrading existing projects
checking project status and integrity
maintaining, syncing and pushing of your git repositories
creating and maintaining merge requests on your git repository servers
release of your project onto PyPI - the cheese shop (pypi.com and test.pypi.com)
deployment of your app/web project
command line options and action arguments
the pjm command line consist of options, action keywords, action arguments and optional action argument flags:
pjm [options] [action-keywords] [action-arguments] [action-flags]
executing pjm with the –help command line option (short -h) displays a short summary of the available
command line options:
pjm --help
all command line options are available in a long form, preceded with two leading hyphen characters. most of them are also available in a short form, as a single character, preceded with a single hyphen character.
general command line options like e.g. –more_verbose (-v), –debug_level (-D), –path (-p) or –project (-P) can be specified for any action. other options, like e.g. the filter options –filterBranch (-B) and –filterExpression (-F), are only supported for bulk actions.
execute pjm with the show_actions() action to display a brief summary of all
the available/registered actions for a project:
pjm show_actions
the action-keywords argument is composed of several words, separated by either a space character, a hyphen character
or an underscore character. some actions can even be abbreviated by a single word shortcut. therefore the following four
commands are identical/equivalent:
pjm show_actions
pjm show-actions
pjm show actions
pjm actions
add the –more_verbose (-v) and/or –debug_level (-D) command line options to get
a more verbose output. e.g. to include for each listed action also their action-arguments and action-flags,
their supported project types and their action shortcut, simply add these options to command line of the
show_actions() action:
pjm --more_verbose --debug_level=2 show_actions
the equivalent command line using the short option form (with only one leading hyphen character), and the shortcut of
the show_actions() action (which is
actions) would look like:
pjm -v -D 2 actions
some actions are expecting additional action-arguments, e.g. to execute the
release_project() action the
version_tag action argument has to specify
the project version to release.
for some actions you can optionally specify action-flags. each flag has a default value, which will be used
if the flag is not specified on the command line.
the action check_deploy() e.g. is supporting the flag CLEANUP
with a default value of False. specifying this flag on the command line is switching the flag value to True. the
resulting flag value can also be specified on the command line by adding an equal character (‘=’) to the flag name,
directly followed by the flag value. so the following two commands are identical:
pjm check_deploy ... CLEANUP
pjm check_deploy ... CLEANUP=True
bulk actions
most of the pjm actions operate on a single project or repository and should be executed in the root folder of the
project working tree.
some of them are also available as bulk actions, which are affecting multiple projects, e.g. the portions of a namespace, or the projects located under the same parent directory.
bulk actions on portions of a namespace are processed by executing them in the namespace root project root folder.
bulk actions on projects underneath a parent directory are executed in the parent folder.
alternatively they can be executed from any other folder by specifying the namespace root project or the projects parent folder via the –project_path (-p) option.
for example, bulk actions on namespace root project, like e.g.
the ae namespace root project via
--project_path path_to_namespace_root_project/ae_ae or the
the aedev namespace root project via -p=path/to/aedev_aedev.
Hint
bulk actions are recognizable by the additional children keyword in their action name.
repository status check actions
a quick overview over the current project version numbers on (1) your local machine, the (2) origin and (3) upstream
remotes, the project releases on (4) the PyPI and (5) your web server (only for Django projects) can be archived with
the show_versions() action (short: versions):
pjm versions
the check_integrity() action (short: check) is proofing
the integrity of your project on your local machine. this includes linting and style checks (using
flake0 and pylint),
the unit and integration tests (using pytest),
test coverage (using coverage.py) and
if the managed project files, created from templates, are up-to-date:
pjm check
Hint
the check_integrity action is also used on the CI tasks on the Git remote servers, excluding the
integration tests. to simulate the checks done in the CI tasks on your local machine put the OS environment variable
CI_PROJECT_ID=1 in front of the pjm check command line.
the general status overview of your project on the local machine and on the remote Git repository server provides the
action show_status() (short: status). run this action to display the current
branch name, a compact git diff between your working tree against the locally and remotely committed project files
and a recommendation which pjm action should be executed next:
pjm status
Hint
specifying the –more_verbose (-v) option on all these check actions are amending the console output.
e.g. the show_status action displays a complete Git status and diff output.
Note
most of these actions can be executed as a bulk action for namespace portions or sister projects under
the same source project parent directory. for more details see
check_children_integrity(),
show_children_status(), and
show_children_versions().
Git remote investigation actions
to search for repositories on the Git remote servers run the action
search_repos(). a detailed overview over a foreign remote
repository can be displayed with the show_remote() action.
Note
these actions are currently only implemented for GitLab remote servers.
project and repository maintenance actions
useful actions to create, extend or renew a project repository respectively multiple project repositories, are e.g.
new_app(),
new_children(),
new_django(),
new_module(),
new_namespace_root(),
new_package(),
new_playground(),
new_project(),
refresh_managed(),
refresh_children_managed().
actions for your other repository maintenance workflows are e.g.
clone_project(),
clone_children_project(),
fork_project(),
fork_children(),
prepare_commit(),
prepare_children_commit(),
commit_project(),
commit_children(),
push_project(),
push_children(),
request_merge(),
request_children_merge(),
release_project(),
release_children(),
install_editable(), and
install_children_editable().
to manipulate single files in project repositories use the actions
add_file(),
add_children_file(),
delete_file(),
delete_children_file(),
rename_file(),
rename_children_file().
in order to synchronize the local main branch with any changes
done to same branch on the ‘origin’ remote, execute pjm with the
update_project() and
update_children() actions.
the clean_releases() action deletes local+remote release tags and
branches of the specified project that got not published to PYPI.
the execution of bulk command lines for a group of projects can be done with the
run_children_command() action.
web and app deployment server actions
the actions check_deploy() and
deploy_project() are working directly with the
deployment servers of your web/Django or app project.
check_deploy() is comparing the deployed files against any
repository version tag or against the package files in your project work tree.
the deploy_project() action is deploying any new or
changed package files to your web or app deployment server.
filtering children of projects parent or portions of a namespace
which children will get processed in a bulk actions get specified by a children-set-expression action argument, which can combine one or more of the following placeholders via the set operators of python (| for union, & for intersection, - for difference and ^ for symmetric difference):
all: all children projects
editable: projects installed as editable
modified: projects having uncommitted changes
develop: projects having checked-out the main branch
filterBranch: projects having checked-out the branch specified with the –filterBranch (short -B) option
filterExpression: projects matching the expression specified with the –filterExpression (short -F) option
for example to show the project versions of namespace portions with uncommitted changes, execute the following command in the root folder of the namespace root project:
pjm show_children_versions modified
to additionally restrict the last example to projects with uncommitted changes in the
MAIN_BRANCH run:
pjm show_children_versions "modified & develop"
Note
children-set-expression with set-operators have to be included into high-commas.
more flexible filtering can be done with the command line options –filterExpression and –filterBranch. by specifying one of these options the selected/filtered children are then available as a children-set-expression with the same name as the specified option.
for example to only show the versions of projects with uncommitted changes in the branch branch_name run:
pjm --filterBranch=branch_name show_children_versions "modified & filterBranch"
Hint
the name of the branch get specified with the –filterBranch option. and the name of the option can then be used like a python set in the children-set-expression action argument.
in general, any bulk action can be restricted to only process children/portions projects that have the specified
branch name checked-out. e.g. to only process all children that have checked out the branch branch_name run:
pjm --filterBranch=branch_name <any_bulk_action> filterBranch
exactly the same selection result could be achieved via a more complex Python expression, using the –filterExpression option/children-set-expression:
pjm --filterExpression="_git_current_branch(chi_pdv)=='branch_name'" <any_bulk_action> filterExpression
Hint
the filter expression can contain project environment variables and any globals of the project-manager tool. additionally, the variable chi_pdv can be used to additionally access the project environment variables of the other children/portion projects.
Note
filter expressions should be included in high-commas.
the next example is selection all children with a project package version number below or equal to 1.2.3:
pjm --filterExpression "project_version<='1.2.3'" <children_bulk_action> filterExpression
the example underneath is showing the local, remote and PyPI versions of the children projects that have a branch
(checked-out or not) with the name branch_name in their repository:
pjm -F "'branch_name' in _git_branches(chi_pdv)" show_children_versions filterExpression
to bulk-release multiple children projects in a contribution process workflow, the following bulk actions can be executed, e.g. from within the root folder of a namespace root project:
new_children()to increment the versions and refresh managed files from templates:pjm -b=branch_name new_children modified
prepare_children_commit()to prepare the commit message files (after you implemented all changes into the above created branch with the namebranch_name):pjm prepare_children_commit "commit message for branch_name" modified
commit_children()to commit changes to the local git repositories:pjm commit_children modified
push_children()to push the committed changes to the remote repositories:pjm --filterBranch=branch_name push_children filterBranch
request_children_merge()to merge pushed changes to the main branches on the remote host (without a repository forg add the options: -f -u=group_or_user_name):pjm --filterBranch=branch_name request_children_merge filterBranch
release_children()to bulk-release the project packages to PyPI:pjm --filterBranch=branch_name release_children filterBranch
install_children_editable(): updates/updates editable installations of your local projects into your virtual environment:pjm -F "'branch_name' in _git_branches(chi_pdv)" install_children_editable filterExpression
remote server configuration
pjm supports two types of remote servers. remote servers that are hosting the project repository
(e.g. on gitlab.com or github.com), and remote servers that are hosting deployable apps or web sites
(e.g. pythonanywhere.com).
pjm actions with write access to any remote host (web/repository server), like e.g.
deploy_project() or
push_project(), are
requesting the user credentials for the authentication from the remote server configurations.
Note
remote server configurations can be specified in multiple ways.
configuration options specified to pjm via command line arguments have the highest priority, followed
by OS environment variables, pjm config variables, and the remote server configuration files.
OS environment variables are mostly used to store credential secrets like authentication tokens, and can get
declared in various ways. default values for these variables can get specified in .env files (see
load_env_var_defaults()). these defaults getting preceded by the OS environment variable values
declared via a startup shell script (like e.g. .bashrc), and these getting overwritten by variable values
set directly in an open console/shell.
command line config options
the remote server domain address can be specified via command line config-option –repo_domain for Git repository remotes and –web_domain for web servers.
user names and credentials can be specified via the pjm command line options:
–repo_token and –repo_user or –repo_group, respectively –web_token and –web_user.
pjm config variables
user credentials not specified by the command line config options are determined from the
OS environment variables and .env files via a user- and domain-specific lookup
with the help of the get_domain_user_var() function.
to resolve the value of the not specified –repo_token command line option, the lookup first checks if there exists an OS environment variable and if not found then it is looking for an application config variable.
for example the lookup of the default value of the not specified –repo_token command line option,
for an user with the username michael at the domain www.example.com, is done in the
following order:
OS environment variable
AE_OPTIONS_HOST_TOKEN_AT_WWW_EXAMPLE_COM_MICHAELconfig variable
host_token_at_www_example_com_michaelin the config sectionaeOptionsOS environment variable
AE_OPTIONS_HOST_TOKEN_AT_WWW_EXAMPLE_COMconfig variable
host_token_at_www_example_comin the config sectionaeOptions
project development variables
this type of configuration variables are compiled by an instance of the ProjectDevVars
provided by the aedev.project_vars module. the variable values can be configured via the
OS environment variables or the .env files, situated in the root folder of a project working tree (or above).
by providing for example the user name (of your account at your repository host server), you don’t need to specify
it any longer on the pjm command line via the –repo_user option. in the most cases you will want to provide
also the repository group name of the repository owner instead of the –repo_group option. therefore create a
.env file in the project root with the following content:
PDV_repo_user = "UserName"
PDV_repo_group=UserOrGroupName
Hint
the default value of the repository group name, if not specified, gets compiled from the project name followed by a hyphen and the word group.
in order to change the default domain (gitlab.com) of the git repository server/host for
a project to github.com, add also the following two lines have into this dict literal:
PDV_repo_domain=github.com
git credential storage
the git credential storage can be used as the last fallback if your user credentials are neither specified as command line config options nor via the pjm config variables.
the user credentials for actions on git repository hosts (gitlab.com/github.com/…) like
push_project() can alternatively
be set and stored via the git configuration settings
(see https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage
and https://stackoverflow.com/questions/46645843).
Hint
see https://stackoverflow.com/questions/65163081 to disable user/password prompts for fetch and check actions
to git repository hoster that don’t need authentication (and not using the token option), like e.g.
_git_fetch().
pjm example workflows
this section describes some typical development workflows managed with the help of the pjm tool.
create a new project
first make sure you have installed the pjm tool, by running the following command:
pip install aedev-project-manager
to create a new project (in this example a small console app module with the project name con_app),
first change the current working directory of your used shell (e.g. bash) to your
projects source parent folder (e.g. ~/src):
cd ~/src
pjm --project_name=con_app new_module
cd con_app
the above pjm command will create a new root folder with the name con_app and within the project structure
based on the templates from the aedev namespace.
Hint
the pjm action new_module specifies the type of the project as a single module.
for a more complex project (including multiple modules) use instead the new_package action,
for a namespace root project the new_namespace_root action,
for a GUI application the new_app action,
and for a django project the new_django action.
then create, within the new project root folder a .env file to put your username and credentials, like explained
in the above section project development variables.
Hint
the section remote server configuration describes alternative ways on how you can configure default values of your repository server, your user account name and your credentials/tokens.
optionally create and activate a virtual environment for the new project. the following command is
using the tool pyenv to set an existing virtual environment (py_env)
as the default for the new project (stored within the .python-version in the project root folder).
pyenv local py_env
Hint
using pyenv local has the advantage to ensure that the project’s virtual environment gets activated
automatically, as soon as you change the current directory of your shell/console to the project root folder.
now you can start completing the unit and integration tests code by editing the prepared file tests/test_con_app.py.
then the project code can be amended in the generated file con_app.py.
to complete the documentation of your new project, amend the prepared files README.md,
docs/index.rst and docs/features_and_examples.rst accordingly.
Hint
at any time in the implementation process you can run the actions
renew and
check in order to
keep the files created from templates up-to-date, and to test your implementation:
pjm refresh
pjm check
after finishing the implementation, create the commit message file .commit_msg.txt in the project root
folder with the prepare action:
pjm prepare
the content of the commit message file can then be amended with additional notes.
to commit the first implementation of your new project into your local git repository, execute the
commit action:
pjm commit
now the new project can be pushed to your repository host server (gitlab.com by default)
by executing the push
action:
pjm push
change request on an existing project
a typical workflow to change or add code of an already existing project gets processed with
the following pjm actions:
fork- create your fork or update an exiting fork (for already forked projects).
renew- update/refresh/renew the files created from templates, update/bump your project version and create a new feature branch.
prepare- create a commit message after all planned changes/additions are implemented.
commit- create a new commit.
push- push the commit to the origin repository (your fork).
request- create a merge request (respective a push request at github.com).
as a repository maintainer and to complete the workflow, the release and deployment of a project,
you can initiate the following pjm actions:
setup a new Django CMS server project
the following example describes the steps done in the bash shell/console on your computer,
in order to create a new Django project (using Django 4.2 and DjangoCms 4.1), with the project name oaio_server.
Hint
alternative to the previous example we first create the project folder (oaio_server) manually, and prepare the
virtual environment, before we use the pjm tool to create the initial project files from the aedev templates.
after changing your current working directory to the projects source parent folder (e.g. <username>/src), execute the
following commands to create the project root folder oaio_server,
and setup a new virtual environment with the name dj4:
pyenv install 3.12.3 (released on 9 april 2024)
pyenv virtualenv 3.12.3 dj4
mkdir oaio_server
cd oaio_server
pyenv local dj4
pip install --upgrade pip setuptools aedev-project-manager
now, still from within the project root folder and with the new virtual environment activated, you can
install Django and DjangoCms and prepare an initial project structure by executing the following commands.
the djangocms command will prompt you to enter the name, email address and password of the django admin/superuser:
pip install Django==4.2.13 (released on 7 may 2024, 4.2.16 on 12 oct 2024)
pip install django-cms==4.1.1 (released on 1 may 2024, 4.1.3 on 12 oct 2024)
djangocms oaio_server .
Note
don’t miss the final dot in the djangocms command.
to adapt your web project declare the values of the project development variables,
by creating a new .env file with the following content:
PDV_AUTHOR=YourAuthorName
PDV_AUTHOR_EMAIL='your-email-address@somewhere.com'
PDV_repo_user=yourGitRemoteUserName
PDV_repo_token=your-private-secret-token-on-your-git-repository-server
PDV_repo_group='repo-host-owner-user-or-group-id' # e.g. 'ae-group'
PDV_web_domain='web-app-host-domain' # e.g. 'eu.pythonanywhere.com'
PDV_web_user='web-server-user-name'
PDV_web_token=your-password-or-token-on-your-web-server
Hint
to prevent the release of your web project onto the PyPI cheese shop, set the value of the PDV_pip_name variable to an empty string.
now execute the following commands in order to adapt the new project to be managed by pjm and to use the
template files provided by the projects in the
aedev namespace
mv requirements.in requirements.txt
rm LICENSE
pjm -b new-project-branch-name new_django
now your web project is ready to be implemented. after you wrote your unit tests and the django apps and views,
you prepare your first push by running the following pjm actions/commands:
pjm prepare # prepare the commit message
pjm commit # commit to git repository
pjm push # push the commit to your Git repository server
additional information to setup Django/CMS
install Django development version (finally NOT used for this project/venv): https://docs.djangoproject.com/en/4.2/topics/install/#installing-the-development-version
install DjangoCms by hand (not using docker): https://docs.django-cms.org/en/latest/introduction/01-install.html#installing-django-cms-by-hand
Django/Cms software versions: https://docs.djangoproject.com/en/4.2/faq/install/#faq-python-version-support and https://docs.django-cms.org/en/latest/index.html#software-version-requirements-and-release-notes
more pjm example workflows
pjm workflow examples for aedev namespace portion projects can be found in the
contribution documentation of a project,
and for web projects in the programmer manual
of the kairos web project.