SlideShare a Scribd company logo
Using Buildout,
GenericSetup and a Policy
Package to Rule the World
    Clayton Parker | Senior Developer
        PLONE SYMPOSIUM EAST 2012
Who Am I
What will we learn?                        PLONE SYMPOSIUM EAST 2012




• Policy Package
• GenericSetup
• Plone Site Buildout Recipe

             http://github.com/sixfeetup
Demo
Using Buildout, GenericSetup and a Policy Package to Rule the World
Using Buildout, GenericSetup and a Policy Package to Rule the World
Realization
• Repeatable environments
• Fewer commands
• Repeatable product installation
PLONE SYMPOSIUM EAST 2012
Human Err0r                                 PLONE SYMPOSIUM EAST 2012




  “Hey Bob, did you run the fizzbang.widget profile
  on production”

  “I think so, Doug”

  “Do you know why the client is yelling at me
  right now?”

  “Maybe I didn’t, let me fix that real quick”
Policy Package
Create the package*                            PLONE SYMPOSIUM EAST 2012




          $ cd path/to/buildout/src
          $ zopeskel sfu_policy pse12.policy
          $ cd pse12.policy
          .. git init / add / etc ...




* This example uses sixieskel for brevity,
   you might use the “plone” template
Package layout                         PLONE SYMPOSIUM EAST 2012



    !"" setup.py
    #"" src
        #"" pse12
            !"" __init__.py
            #"" policy
                 !"" __init__.py
                 !"" configure.zcml
                 !"" profiles
                 %   !"" default
                 %   %   #"" metadata.xml
                 %   #"" initial
                 %       #"" metadata.xml
                 !"" setuphandlers.py
                 !"" upgrades.py
                 #"" upgrades.zcml
Add to buildout                     PLONE SYMPOSIUM EAST 2012




    [buildout]
    extensions = mr.developer
    auto-checkout = True
    parts = instance

    [sources]
    pse12.policy = git <git url here>

    [instance]
    eggs = pse12.policy
Dependencies                  PLONE SYMPOSIUM EAST 2012




   # pse12.policy/setup.py
   install_requires=[
       'setuptools',
       'Plone',
       'Pillow',
       'plone.app.caching',
   ],
ZCML                                   PLONE SYMPOSIUM EAST 2012



       # pse12.policy setup.py
       entry_points="""
       [z3c.autoinclude.plugin]
       target = plone
       """,



<!-- pse12.policy configure.zcml -->
<includePlugins package="." />
<includeDependencies package="." />
Generic Setup
Default profile                                 PLONE SYMPOSIUM EAST 2012




 <!-- pse12.policy configure.zcml -->
 <genericsetup:registerProfile
     name="default"
     title="pse12.policy (default)"
     directory="profiles/default"
     description="Installation profile for pse12.policy"
     provides="Products.GenericSetup.interfaces.EXTENSION"
     />
Initial profile                                 PLONE SYMPOSIUM EAST 2012




 <!-- pse12.policy configure.zcml -->
 <genericsetup:registerProfile
     name="initial"
     title="pse12.policy (initial)"
     directory="profiles/initial"
     description="Initial profile for pse12.policy"
     provides="Products.GenericSetup.interfaces.EXTENSION"
     />
Metadata                            PLONE SYMPOSIUM EAST 2012




   <?xml version="1.0"?>
   <metadata>
       <version>001</version>
       <dependencies>...</dependencies>
   </metadata>
Add-ons
Package                            PLONE SYMPOSIUM EAST 2012




    # Inside setup.py
    install_requires=[
        ...
        ‘plonetheme.transition’,
    ],
Package                                                 PLONE SYMPOSIUM EAST 2012




 <?xml version="1.0"?>

 <!-- pse12.policy metadata.xml -->
 <metadata>
     <version>001</version>
     <dependencies>
         <dependency>profile-plone.app.theming:default</dependency>
     </dependencies>
 </metadata>
Package   PLONE SYMPOSIUM EAST 2012
Package                                                                                PLONE SYMPOSIUM EAST 2012


   # profiles/default/registry.xml
   <registry>
     <record field="enabled" interface="plone.app.theming.interfaces.IThemeSettings"
              name="plone.app.theming.interfaces.IThemeSettings.enabled">
       <field type="plone.registry.field.Bool">
         <default>False</default>
         <description>enable_theme_globally</description>
         <title>enabled</title>
       </field>
       <value>True</value>
     </record>
     <record field="absolutePrefix" interface="plone.app.theming.interfaces.IThemeSettings"
              name="plone.app.theming.interfaces.IThemeSettings.absolutePrefix">
       <field type="plone.registry.field.TextLine">
         <description>convert_relative_url</description>
         <required>False</required>
         <title>absolute_url_prefix</title>
       </field>
       <value>/++theme++plonetheme.transition</value>
     </record>
     <record field="currentTheme" interface="plone.app.theming.interfaces.IThemeSettings"
              name="plone.app.theming.interfaces.IThemeSettings.currentTheme">
       <field type="plone.registry.field.TextLine">
         <description>current_theme_description</description>
         <title>current_theme</title>
       </field>
       <value>plonetheme.transition</value>
     </record>
     <record field="rules" interface="plone.app.theming.interfaces.IThemeSettings"
              name="plone.app.theming.interfaces.IThemeSettings.rules">
       <field type="plone.registry.field.TextLine">
         <description>rules_file_path</description>
         <required>False</required>
         <title>rules_file</title>
       </field>
       <value>/++theme++plonetheme.transition/rules.xml</value>
     </record>
   </registry>
Blog                                    PLONE SYMPOSIUM EAST 2012




       # Inside pse12.policy setup.py
       install_requires=[
           ...
           ‘collective.blog.star’,
       ],
Blog                                                      PLONE SYMPOSIUM EAST 2012




 <?xml version="1.0"?>

 <!-- pse12.policy metadata.xml -->
 <metadata>
     <version>001</version>
     <dependencies>
         ...
         <dependency>profile-collective.blog.star:default</dependency>
     </dependencies>
 </metadata>
Content
Package                                     PLONE SYMPOSIUM EAST 2012




    $ zopeskel plone pse12.initialcontent
Package                             PLONE SYMPOSIUM EAST 2012




   # Inside pse12.initialcontent setup.py
   install_requires=[
       ‘quintagroup.transmogrifier’,
   ],
Package                                       PLONE SYMPOSIUM EAST 2012




<!-- pse12.initialcontent configure.zcml -->
<genericsetup:registerProfile
    name="default"
    title="pse12.initialcontent (default)"
    directory="profiles/default"
    description="Content generation package"
    provides="Products.GenericSetup.interfaces.EXTENSION"
    />
Package                                         PLONE SYMPOSIUM EAST 2012




<?xml version="1.0"?>

<!-- pse12.initialcontent metadata.xml -->
<metadata>
    <version>001</version>
    <dependencies>
        <dependency>profile-pse12.policy:default</dependency>
    </dependencies>
</metadata>
!""   __init__.py
!""   configure.zcml                                  PLONE SYMPOSIUM EAST 2012
!""   profiles
#     %"" default
#         !"" metadata.xml
#         !"" pse12_initialcontent-default.txt
#         !"" quintagroup.transmogrifier-import.txt
#         %"" structure
#              !"" .objects.xml
#              !"" .portlets.xml
#              !"" .properties.xml
#              !"" about
#              #   !"" .marshall.xml
#              #   !"" .objects.xml
#              #   !"" .portlets.xml
#              #   !"" .properties.xml
#              #   !"" about-us
#              #   #   !"" .marshall.xml
#              #   #   %"" .portlets.xml
#              #   %"" meet-the-team
#              #        !"" .marshall.xml
#              #        %"" .portlets.xml
#              !"" files
#              #   !"" .marshall.xml
#              #   %"" .portlets.xml
#              !"" front-page
#              #   !"" .marshall.xml
#              #   %"" .portlets.xml
#              %"" images
#                   !"" .marshall.xml
#                   !"" .objects.xml
#                   %"" .portlets.xml
!""   setuphandlers.py
!""   upgrades.py
%""   upgrades.zcml
Upgrades and Setuphandlers
Setuphandlers                                           PLONE SYMPOSIUM EAST 2012



  from sixfeetup.utils import helpers as sfutils


  def importVariousInitial(context):
      """Run the setup handlers for the initial profile"""
      if context.readDataFile('pse12_policy-initial.txt') is None:
          return
      members = [
          {'id': 'staff',
            'password': 'staff',
            'roles': ['Manager', 'Member'],
            'properties': {
                'email': 'changeme@example.com',
                'fullname': 'Site Staff',
                'username': 'staff'
            }
          }
      ]
      sfutils.addUserAccounts(members)
Setuphandlers                                          PLONE SYMPOSIUM EAST 2012




  <genericsetup:importStep
      name="pse12.policy: initial"
      title="pse12.policy: Various Initial steps"
      description="Initial Setup handlers for pse12.policy"
      handler="pse12.policy.setuphandlers.importVariousInitial">
    <depends name="content"/>
  </genericsetup:importStep>
Setuphandlers                                           PLONE SYMPOSIUM EAST 2012




  from sixfeetup.utils import helpers as sfutils


  def importVarious(context):
      """Run the setup handlers for the default profile"""
      if context.readDataFile('pse12_policy-default.txt') is None:
          return
      # automagically run a plone migration if needed
      sfutils.runPortalMigration()
      # automagically run the upgrade steps for this package
      sfutils.runUpgradeSteps(u'pse12.policy:default')
Setuphandlers                                             PLONE SYMPOSIUM EAST 2012




from sixfeetup.utils import helpers as sfutils


def importVarious(context):
    """Run the setup handlers for the default profile"""
    if context.readDataFile('pse12_initialcontent-default.txt') is None:
        return
    # automagically run the upgrade steps for this package
    sfutils.runUpgradeSteps(u'pse12.initialcontent:default')
Upgrades                                             PLONE SYMPOSIUM EAST 2012


   <!-- pse12.initialcontent upgrades.zcml -->
   <genericsetup:upgradeStep
       title="Set up intranet section"
       description=""
       source="001"
       destination="002"
       handler="pse12.initialcontent.upgrades.intranet_setup"
       sortkey="10"
       profile="pse12.initialcontent:default"
       />

   <genericsetup:upgradeStep
       title="Set up the default pages"
       description=""
       source="001"
       destination="002"
       handler="pse12.initialcontent.upgrades.default_pages"
       sortkey="20"
       profile="pse12.initialcontent:default"
       />
from zope.app.component.hooks import getSite
                                                           PLONE SYMPOSIUM EAST 2012
from Products.CMFCore.utils import getToolByName
from sixfeetup.utils import helpers as sfutils


def intranet_setup(context):
    """Set up the placeful workflow for the intranet
    """
    portal = getSite()
    # If the intranet doesn't exist, bail out
    if 'intranet' not in portal.objectIds():
        return
    intranet = portal['intranet']
    # If the placeful workflow is already in place, bail out
    if '.wf_policy_config' in intranet.objectIds():
        return
    placeful_workflow = getToolByName(portal, 'portal_placeful_workflow')
    product = 'CMFPlacefulWorkflow'
    intranet.manage_addProduct[product].manage_addWorkflowPolicyConfig()
    config = placeful_workflow.getWorkflowPolicyConfig(intranet)
    policy = 'intranet'
    config.setPolicyBelow(policy=policy)
    config.setPolicyIn(policy=policy)
    # Make everything in the intranet `private`
    path = '/'.join(intranet.getPhysicalPath())
    sfutils.publishEverything(context, path, 'hide')
from zope.app.component.hooks import getSite
                                                                          PLONE SYMPOSIUM EAST 2012

def default_pages(context):
    """There is a bug in quintagroup.transmogrifier that prevents
    the default page from being set. We will handle it here
    instead.
    """
    portal = getSite()
    items = {
        'about': dict(
             id='default_page',
             type='string',
             value='about-us'),
        'blog': dict(
             id='layout',
             type='string',
             value='blog_view'),
    }
    for path, prop in items.items():
        obj = portal.unrestrictedTraverse(path, None)
        # If the object doesn't exist, bail out
        if obj is None:
             continue
        target_obj = None
        if prop['id'] == 'default_page':
             target_obj = obj.unrestrictedTraverse(prop['value'], None)
             # Bail out if the default page target does not exist
             if target_obj is None:
                 continue
        obj._setProperty(prop['id'], prop['value'], prop['value'])
        if target_obj is not None:
             # ensure that it doesn't show in the navigation
             target_obj.reindexObject()
Plone Site Recipe
What is it?             PLONE SYMPOSIUM EAST 2012




• Create a Plone site
• Run profiles
• Re-create a site
Add it to buildout                   PLONE SYMPOSIUM EAST 2012




    [buildout]
    parts = plonesite

    [plonesite]
    recipe = collective.recipe.plonesite
    instance = instance
    zeoserver = zeoserver
    site-id = Plone
    admin-user = admin
Add profiles                         PLONE SYMPOSIUM EAST 2012




  [plonesite]
  ...
  profiles-initial = pse12.policy:initial
  profiles = pse12.policy:default
Buildout run                                PLONE SYMPOSIUM EAST 2012




    $ bin/buildout install plonesite
    Installing plonesite.
    Retrieved the admin user
    Added Plone Site
    Quick installing: []
    Running profiles: ['pse12.policy:initial']
    Finished
    Running profiles: ['pse12.policy:default',
    'sixfeetup.customfolderalert:default',
    'plone.app.debugtoolbar:default']
Dynamic options                             PLONE SYMPOSIUM EAST 2012




   $ bin/buildout plonesite:enabled=false




   $ bin/buildout plonesite:site-replace=true
Upgrade Demo
Links                                                                         PLONE SYMPOSIUM EAST 2012




•   sixieskel (http://github.com/sixfeetup/sixieskel)

•   pse12-example-buildout (http://github.com/sixfeetup/pse12-example-buildout)

•   pse12.policy (http://github.com/sixfeetup/pse12.policy)

•   pse12.initialcontent (http://github.com/sixfeetup/pse12.initialcontent)

•   quintagroup.transmogrifier (http://pypi.python.org/pypi/quintagroup.transmogrifier)

•   collective.blog.star (http://pypi.python.org/pypi/collective.blog.star)

•   plonetheme.transition (http://pypi.python.org/pypi/plonetheme.transition/)
Photo Credits                                                                 PLONE SYMPOSIUM EAST 2012




•   http://www.flickr.com/photos/naturegeak/5642083189/ (who)

•   https://secure.flickr.com/photos/campuspartymexico/5965708420/ (demo)

•   https://secure.flickr.com/photos/aon/2171253511/ (realization)

•   https://secure.flickr.com/photos/walkingsf/6930636483/ (policy)

•   https://secure.flickr.com/photos/myklroventine/3261364899/ (GS)

•   https://secure.flickr.com/photos/oskay/2157686638/ (add-ons)

•   https://secure.flickr.com/photos/simonpholzman/5132795241/ (plone site)

•   https://secure.flickr.com/photos/bitterjug/488731963// (upgrades)

•   https://secure.flickr.com/photos/campuspartymexico/5965153009/ (upgrade)

•   https://secure.flickr.com/photos/friarsbalsam/4609212148/ (content)




    Thanks to
Questions?




   heck out     /demos
 C
        tup .com
si xfee

More Related Content

What's hot (20)

PDF
淺談 Geb 網站自動化測試(JCConf 2014)
Kyle Lin
 
KEY
SproutCore is Awesome - HTML5 Summer DevFest
tomdale
 
PPTX
Grails Plugins(Console, DB Migration, Asset Pipeline and Remote pagination)
NexThoughts Technologies
 
ODP
Django for Beginners
Jason Davies
 
ODP
Pyramid Lighter/Faster/Better web apps
Dylan Jay
 
PDF
Implement rich snippets in your webshop
Arjen Miedema
 
KEY
关于 Html5 那点事
Sofish Lin
 
PDF
Intro to Selenium UI Tests with pytest & some useful pytest plugins
Asif Mohaimen
 
KEY
You've Got Plugins in Your Plugins: Bundling Plugin Dependencies - Atlassian ...
Atlassian
 
KEY
ZopeSkel: The past, present and future
Cristopher Ewing
 
PDF
Intro to WordPress Plugin Development
Brad Williams
 
PDF
Jumping Into WordPress Plugin Programming
Dougal Campbell
 
PPT
jQuery For Developers Stack Overflow Dev Days Toronto
Ralph Whitbeck
 
PDF
Phing for power users - frOSCon8
Stephan Hochdörfer
 
PPTX
BitSensor - How and when to start a business
IT Talent College
 
PDF
Best Practices in Plugin Development (WordCamp Seattle)
andrewnacin
 
KEY
Rails Antipatterns | Open Session with Chad Pytel
Engine Yard
 
KEY
You're Doing It Wrong
bostonrb
 
PDF
11 tools for your PHP devops stack
Kris Buytaert
 
PDF
Automatisation in development and testing - within budget
David Lukac
 
淺談 Geb 網站自動化測試(JCConf 2014)
Kyle Lin
 
SproutCore is Awesome - HTML5 Summer DevFest
tomdale
 
Grails Plugins(Console, DB Migration, Asset Pipeline and Remote pagination)
NexThoughts Technologies
 
Django for Beginners
Jason Davies
 
Pyramid Lighter/Faster/Better web apps
Dylan Jay
 
Implement rich snippets in your webshop
Arjen Miedema
 
关于 Html5 那点事
Sofish Lin
 
Intro to Selenium UI Tests with pytest & some useful pytest plugins
Asif Mohaimen
 
You've Got Plugins in Your Plugins: Bundling Plugin Dependencies - Atlassian ...
Atlassian
 
ZopeSkel: The past, present and future
Cristopher Ewing
 
Intro to WordPress Plugin Development
Brad Williams
 
Jumping Into WordPress Plugin Programming
Dougal Campbell
 
jQuery For Developers Stack Overflow Dev Days Toronto
Ralph Whitbeck
 
Phing for power users - frOSCon8
Stephan Hochdörfer
 
BitSensor - How and when to start a business
IT Talent College
 
Best Practices in Plugin Development (WordCamp Seattle)
andrewnacin
 
Rails Antipatterns | Open Session with Chad Pytel
Engine Yard
 
You're Doing It Wrong
bostonrb
 
11 tools for your PHP devops stack
Kris Buytaert
 
Automatisation in development and testing - within budget
David Lukac
 

Similar to Using Buildout, GenericSetup and a Policy Package to Rule the World (20)

PDF
Plone Theming in a Nutshell
cdw9
 
PDF
Building Content Types with Dexterity
David Glick
 
PPTX
Pragmatische Plone Projekte
Andreas Jung
 
PPTX
Pragmatic plone projects
Andreas Jung
 
KEY
Plone api
Nejc Zupan
 
PDF
Pragmatic plone projects
Andreas Jung
 
PDF
George Thiruvathukal, User Experiences with Plone Content Management
webcontent2007
 
PDF
How to Get Started Theming Plone
cdw9
 
PDF
Martin Aspeli Extending And Customising Plone 3
Vincenzo Barone
 
PPT
Where's the source, Luke? : How to find and debug the code behind Plone
Vincenzo Barone
 
KEY
Jumpstart Your Development with ZopeSkel
Cristopher Ewing
 
PDF
Introduction to clarity
Dharshana Kasun Warusavitharana
 
PDF
Plone 5.2 migration at University Ghent, Belgium
Andreas Jung
 
PDF
Using Buildout to Develop and Deploy Python Projects
Clayton Parker
 
PDF
Frequently asked questions answered frequently - but now for the last time
Andreas Jung
 
PDF
Building instant features with advanced Plone themes
Asko Soukka
 
PDF
Introduction to Plone (November 2003)
Kiran Jonnalagadda
 
PDF
Groovy Domain Specific Languages - SpringOne2GX 2012
Guillaume Laforge
 
PDF
delivering applications with zc.buildout and a distributed model - Plone Conf...
Tarek Ziadé De Turcey
 
PDF
Buildout: Fostering Repeatability
Clayton Parker
 
Plone Theming in a Nutshell
cdw9
 
Building Content Types with Dexterity
David Glick
 
Pragmatische Plone Projekte
Andreas Jung
 
Pragmatic plone projects
Andreas Jung
 
Plone api
Nejc Zupan
 
Pragmatic plone projects
Andreas Jung
 
George Thiruvathukal, User Experiences with Plone Content Management
webcontent2007
 
How to Get Started Theming Plone
cdw9
 
Martin Aspeli Extending And Customising Plone 3
Vincenzo Barone
 
Where's the source, Luke? : How to find and debug the code behind Plone
Vincenzo Barone
 
Jumpstart Your Development with ZopeSkel
Cristopher Ewing
 
Introduction to clarity
Dharshana Kasun Warusavitharana
 
Plone 5.2 migration at University Ghent, Belgium
Andreas Jung
 
Using Buildout to Develop and Deploy Python Projects
Clayton Parker
 
Frequently asked questions answered frequently - but now for the last time
Andreas Jung
 
Building instant features with advanced Plone themes
Asko Soukka
 
Introduction to Plone (November 2003)
Kiran Jonnalagadda
 
Groovy Domain Specific Languages - SpringOne2GX 2012
Guillaume Laforge
 
delivering applications with zc.buildout and a distributed model - Plone Conf...
Tarek Ziadé De Turcey
 
Buildout: Fostering Repeatability
Clayton Parker
 
Ad

More from Clayton Parker (17)

PDF
Customizing Your Shell With Dotfiles
Clayton Parker
 
PDF
Vim for Mere Mortals
Clayton Parker
 
PDF
Fuzzy Feelings for Fuzzy Matching
Clayton Parker
 
PDF
Exploring Code with Pry!
Clayton Parker
 
PDF
Zen and the Art of Python
Clayton Parker
 
PDF
So you think you can pdb?
Clayton Parker
 
PDF
Current State of Python Packaging
Clayton Parker
 
PDF
Notre Dame Seamless Syndication with Lineage
Clayton Parker
 
PDF
Make Plone Search Act Like Google Using Solr
Clayton Parker
 
PDF
Migrating from drupal to plone with transmogrifier
Clayton Parker
 
PDF
Buildout for the Future
Clayton Parker
 
PDF
Laying Pipe with Transmogrifier
Clayton Parker
 
PDF
LDAP and Active Directory Authentication in Plone
Clayton Parker
 
PDF
Code with Style - PyOhio
Clayton Parker
 
PDF
Code with style
Clayton Parker
 
PDF
Generic Setup De-Mystified
Clayton Parker
 
PDF
Getting Plone Ready For The Prom
Clayton Parker
 
Customizing Your Shell With Dotfiles
Clayton Parker
 
Vim for Mere Mortals
Clayton Parker
 
Fuzzy Feelings for Fuzzy Matching
Clayton Parker
 
Exploring Code with Pry!
Clayton Parker
 
Zen and the Art of Python
Clayton Parker
 
So you think you can pdb?
Clayton Parker
 
Current State of Python Packaging
Clayton Parker
 
Notre Dame Seamless Syndication with Lineage
Clayton Parker
 
Make Plone Search Act Like Google Using Solr
Clayton Parker
 
Migrating from drupal to plone with transmogrifier
Clayton Parker
 
Buildout for the Future
Clayton Parker
 
Laying Pipe with Transmogrifier
Clayton Parker
 
LDAP and Active Directory Authentication in Plone
Clayton Parker
 
Code with Style - PyOhio
Clayton Parker
 
Code with style
Clayton Parker
 
Generic Setup De-Mystified
Clayton Parker
 
Getting Plone Ready For The Prom
Clayton Parker
 
Ad

Recently uploaded (20)

PDF
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
PDF
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
PDF
Timothy Rottach - Ramp up on AI Use Cases, from Vector Search to AI Agents wi...
AWS Chicago
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PDF
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
PDF
SWEBOK Guide and Software Services Engineering Education
Hironori Washizaki
 
PPTX
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
PDF
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
PDF
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
PPTX
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
PDF
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
PDF
LLMs.txt: Easily Control How AI Crawls Your Site
Keploy
 
PDF
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PPTX
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
PDF
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
PDF
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
PPTX
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
Timothy Rottach - Ramp up on AI Use Cases, from Vector Search to AI Agents wi...
AWS Chicago
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
SWEBOK Guide and Software Services Engineering Education
Hironori Washizaki
 
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
LLMs.txt: Easily Control How AI Crawls Your Site
Keploy
 
Transcript: New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 

Using Buildout, GenericSetup and a Policy Package to Rule the World

  • 1. Using Buildout, GenericSetup and a Policy Package to Rule the World Clayton Parker | Senior Developer PLONE SYMPOSIUM EAST 2012
  • 3. What will we learn? PLONE SYMPOSIUM EAST 2012 • Policy Package • GenericSetup • Plone Site Buildout Recipe http://github.com/sixfeetup
  • 7. Realization • Repeatable environments • Fewer commands • Repeatable product installation
  • 9. Human Err0r PLONE SYMPOSIUM EAST 2012 “Hey Bob, did you run the fizzbang.widget profile on production” “I think so, Doug” “Do you know why the client is yelling at me right now?” “Maybe I didn’t, let me fix that real quick”
  • 11. Create the package* PLONE SYMPOSIUM EAST 2012 $ cd path/to/buildout/src $ zopeskel sfu_policy pse12.policy $ cd pse12.policy .. git init / add / etc ... * This example uses sixieskel for brevity, you might use the “plone” template
  • 12. Package layout PLONE SYMPOSIUM EAST 2012 !"" setup.py #"" src #"" pse12    !"" __init__.py    #"" policy    !"" __init__.py    !"" configure.zcml    !"" profiles    %   !"" default    %   %   #"" metadata.xml    %   #"" initial    %   #"" metadata.xml    !"" setuphandlers.py    !"" upgrades.py    #"" upgrades.zcml
  • 13. Add to buildout PLONE SYMPOSIUM EAST 2012 [buildout] extensions = mr.developer auto-checkout = True parts = instance [sources] pse12.policy = git <git url here> [instance] eggs = pse12.policy
  • 14. Dependencies PLONE SYMPOSIUM EAST 2012 # pse12.policy/setup.py install_requires=[ 'setuptools', 'Plone', 'Pillow', 'plone.app.caching', ],
  • 15. ZCML PLONE SYMPOSIUM EAST 2012 # pse12.policy setup.py entry_points=""" [z3c.autoinclude.plugin] target = plone """, <!-- pse12.policy configure.zcml --> <includePlugins package="." /> <includeDependencies package="." />
  • 17. Default profile PLONE SYMPOSIUM EAST 2012 <!-- pse12.policy configure.zcml --> <genericsetup:registerProfile name="default" title="pse12.policy (default)" directory="profiles/default" description="Installation profile for pse12.policy" provides="Products.GenericSetup.interfaces.EXTENSION" />
  • 18. Initial profile PLONE SYMPOSIUM EAST 2012 <!-- pse12.policy configure.zcml --> <genericsetup:registerProfile name="initial" title="pse12.policy (initial)" directory="profiles/initial" description="Initial profile for pse12.policy" provides="Products.GenericSetup.interfaces.EXTENSION" />
  • 19. Metadata PLONE SYMPOSIUM EAST 2012 <?xml version="1.0"?> <metadata> <version>001</version> <dependencies>...</dependencies> </metadata>
  • 21. Package PLONE SYMPOSIUM EAST 2012 # Inside setup.py install_requires=[ ... ‘plonetheme.transition’, ],
  • 22. Package PLONE SYMPOSIUM EAST 2012 <?xml version="1.0"?> <!-- pse12.policy metadata.xml --> <metadata> <version>001</version> <dependencies> <dependency>profile-plone.app.theming:default</dependency> </dependencies> </metadata>
  • 23. Package PLONE SYMPOSIUM EAST 2012
  • 24. Package PLONE SYMPOSIUM EAST 2012 # profiles/default/registry.xml <registry> <record field="enabled" interface="plone.app.theming.interfaces.IThemeSettings" name="plone.app.theming.interfaces.IThemeSettings.enabled"> <field type="plone.registry.field.Bool"> <default>False</default> <description>enable_theme_globally</description> <title>enabled</title> </field> <value>True</value> </record> <record field="absolutePrefix" interface="plone.app.theming.interfaces.IThemeSettings" name="plone.app.theming.interfaces.IThemeSettings.absolutePrefix"> <field type="plone.registry.field.TextLine"> <description>convert_relative_url</description> <required>False</required> <title>absolute_url_prefix</title> </field> <value>/++theme++plonetheme.transition</value> </record> <record field="currentTheme" interface="plone.app.theming.interfaces.IThemeSettings" name="plone.app.theming.interfaces.IThemeSettings.currentTheme"> <field type="plone.registry.field.TextLine"> <description>current_theme_description</description> <title>current_theme</title> </field> <value>plonetheme.transition</value> </record> <record field="rules" interface="plone.app.theming.interfaces.IThemeSettings" name="plone.app.theming.interfaces.IThemeSettings.rules"> <field type="plone.registry.field.TextLine"> <description>rules_file_path</description> <required>False</required> <title>rules_file</title> </field> <value>/++theme++plonetheme.transition/rules.xml</value> </record> </registry>
  • 25. Blog PLONE SYMPOSIUM EAST 2012 # Inside pse12.policy setup.py install_requires=[ ... ‘collective.blog.star’, ],
  • 26. Blog PLONE SYMPOSIUM EAST 2012 <?xml version="1.0"?> <!-- pse12.policy metadata.xml --> <metadata> <version>001</version> <dependencies> ... <dependency>profile-collective.blog.star:default</dependency> </dependencies> </metadata>
  • 28. Package PLONE SYMPOSIUM EAST 2012 $ zopeskel plone pse12.initialcontent
  • 29. Package PLONE SYMPOSIUM EAST 2012 # Inside pse12.initialcontent setup.py install_requires=[ ‘quintagroup.transmogrifier’, ],
  • 30. Package PLONE SYMPOSIUM EAST 2012 <!-- pse12.initialcontent configure.zcml --> <genericsetup:registerProfile name="default" title="pse12.initialcontent (default)" directory="profiles/default" description="Content generation package" provides="Products.GenericSetup.interfaces.EXTENSION" />
  • 31. Package PLONE SYMPOSIUM EAST 2012 <?xml version="1.0"?> <!-- pse12.initialcontent metadata.xml --> <metadata> <version>001</version> <dependencies> <dependency>profile-pse12.policy:default</dependency> </dependencies> </metadata>
  • 32. !"" __init__.py !"" configure.zcml PLONE SYMPOSIUM EAST 2012 !"" profiles #   %"" default #   !"" metadata.xml #   !"" pse12_initialcontent-default.txt #   !"" quintagroup.transmogrifier-import.txt #   %"" structure #   !"" .objects.xml #   !"" .portlets.xml #   !"" .properties.xml #   !"" about #   #   !"" .marshall.xml #   #   !"" .objects.xml #   #   !"" .portlets.xml #   #   !"" .properties.xml #   #   !"" about-us #   #   #   !"" .marshall.xml #   #   #   %"" .portlets.xml #   #   %"" meet-the-team #   #   !"" .marshall.xml #   #   %"" .portlets.xml #   !"" files #   #   !"" .marshall.xml #   #   %"" .portlets.xml #   !"" front-page #   #   !"" .marshall.xml #   #   %"" .portlets.xml #   %"" images #      !"" .marshall.xml #      !"" .objects.xml #     %"" .portlets.xml !"" setuphandlers.py !"" upgrades.py %"" upgrades.zcml
  • 34. Setuphandlers PLONE SYMPOSIUM EAST 2012 from sixfeetup.utils import helpers as sfutils def importVariousInitial(context): """Run the setup handlers for the initial profile""" if context.readDataFile('pse12_policy-initial.txt') is None: return members = [ {'id': 'staff', 'password': 'staff', 'roles': ['Manager', 'Member'], 'properties': { 'email': '[email protected]', 'fullname': 'Site Staff', 'username': 'staff' } } ] sfutils.addUserAccounts(members)
  • 35. Setuphandlers PLONE SYMPOSIUM EAST 2012 <genericsetup:importStep name="pse12.policy: initial" title="pse12.policy: Various Initial steps" description="Initial Setup handlers for pse12.policy" handler="pse12.policy.setuphandlers.importVariousInitial"> <depends name="content"/> </genericsetup:importStep>
  • 36. Setuphandlers PLONE SYMPOSIUM EAST 2012 from sixfeetup.utils import helpers as sfutils def importVarious(context): """Run the setup handlers for the default profile""" if context.readDataFile('pse12_policy-default.txt') is None: return # automagically run a plone migration if needed sfutils.runPortalMigration() # automagically run the upgrade steps for this package sfutils.runUpgradeSteps(u'pse12.policy:default')
  • 37. Setuphandlers PLONE SYMPOSIUM EAST 2012 from sixfeetup.utils import helpers as sfutils def importVarious(context): """Run the setup handlers for the default profile""" if context.readDataFile('pse12_initialcontent-default.txt') is None: return # automagically run the upgrade steps for this package sfutils.runUpgradeSteps(u'pse12.initialcontent:default')
  • 38. Upgrades PLONE SYMPOSIUM EAST 2012 <!-- pse12.initialcontent upgrades.zcml --> <genericsetup:upgradeStep title="Set up intranet section" description="" source="001" destination="002" handler="pse12.initialcontent.upgrades.intranet_setup" sortkey="10" profile="pse12.initialcontent:default" /> <genericsetup:upgradeStep title="Set up the default pages" description="" source="001" destination="002" handler="pse12.initialcontent.upgrades.default_pages" sortkey="20" profile="pse12.initialcontent:default" />
  • 39. from zope.app.component.hooks import getSite PLONE SYMPOSIUM EAST 2012 from Products.CMFCore.utils import getToolByName from sixfeetup.utils import helpers as sfutils def intranet_setup(context): """Set up the placeful workflow for the intranet """ portal = getSite() # If the intranet doesn't exist, bail out if 'intranet' not in portal.objectIds(): return intranet = portal['intranet'] # If the placeful workflow is already in place, bail out if '.wf_policy_config' in intranet.objectIds(): return placeful_workflow = getToolByName(portal, 'portal_placeful_workflow') product = 'CMFPlacefulWorkflow' intranet.manage_addProduct[product].manage_addWorkflowPolicyConfig() config = placeful_workflow.getWorkflowPolicyConfig(intranet) policy = 'intranet' config.setPolicyBelow(policy=policy) config.setPolicyIn(policy=policy) # Make everything in the intranet `private` path = '/'.join(intranet.getPhysicalPath()) sfutils.publishEverything(context, path, 'hide')
  • 40. from zope.app.component.hooks import getSite PLONE SYMPOSIUM EAST 2012 def default_pages(context): """There is a bug in quintagroup.transmogrifier that prevents the default page from being set. We will handle it here instead. """ portal = getSite() items = { 'about': dict( id='default_page', type='string', value='about-us'), 'blog': dict( id='layout', type='string', value='blog_view'), } for path, prop in items.items(): obj = portal.unrestrictedTraverse(path, None) # If the object doesn't exist, bail out if obj is None: continue target_obj = None if prop['id'] == 'default_page': target_obj = obj.unrestrictedTraverse(prop['value'], None) # Bail out if the default page target does not exist if target_obj is None: continue obj._setProperty(prop['id'], prop['value'], prop['value']) if target_obj is not None: # ensure that it doesn't show in the navigation target_obj.reindexObject()
  • 42. What is it? PLONE SYMPOSIUM EAST 2012 • Create a Plone site • Run profiles • Re-create a site
  • 43. Add it to buildout PLONE SYMPOSIUM EAST 2012 [buildout] parts = plonesite [plonesite] recipe = collective.recipe.plonesite instance = instance zeoserver = zeoserver site-id = Plone admin-user = admin
  • 44. Add profiles PLONE SYMPOSIUM EAST 2012 [plonesite] ... profiles-initial = pse12.policy:initial profiles = pse12.policy:default
  • 45. Buildout run PLONE SYMPOSIUM EAST 2012 $ bin/buildout install plonesite Installing plonesite. Retrieved the admin user Added Plone Site Quick installing: [] Running profiles: ['pse12.policy:initial'] Finished Running profiles: ['pse12.policy:default', 'sixfeetup.customfolderalert:default', 'plone.app.debugtoolbar:default']
  • 46. Dynamic options PLONE SYMPOSIUM EAST 2012 $ bin/buildout plonesite:enabled=false $ bin/buildout plonesite:site-replace=true
  • 48. Links PLONE SYMPOSIUM EAST 2012 • sixieskel (http://github.com/sixfeetup/sixieskel) • pse12-example-buildout (http://github.com/sixfeetup/pse12-example-buildout) • pse12.policy (http://github.com/sixfeetup/pse12.policy) • pse12.initialcontent (http://github.com/sixfeetup/pse12.initialcontent) • quintagroup.transmogrifier (http://pypi.python.org/pypi/quintagroup.transmogrifier) • collective.blog.star (http://pypi.python.org/pypi/collective.blog.star) • plonetheme.transition (http://pypi.python.org/pypi/plonetheme.transition/)
  • 49. Photo Credits PLONE SYMPOSIUM EAST 2012 • http://www.flickr.com/photos/naturegeak/5642083189/ (who) • https://secure.flickr.com/photos/campuspartymexico/5965708420/ (demo) • https://secure.flickr.com/photos/aon/2171253511/ (realization) • https://secure.flickr.com/photos/walkingsf/6930636483/ (policy) • https://secure.flickr.com/photos/myklroventine/3261364899/ (GS) • https://secure.flickr.com/photos/oskay/2157686638/ (add-ons) • https://secure.flickr.com/photos/simonpholzman/5132795241/ (plone site) • https://secure.flickr.com/photos/bitterjug/488731963// (upgrades) • https://secure.flickr.com/photos/campuspartymexico/5965153009/ (upgrade) • https://secure.flickr.com/photos/friarsbalsam/4609212148/ (content) Thanks to
  • 50. Questions? heck out /demos C tup .com si xfee