def testBranchFlags():
    yaml_contents = dedent('''
        branch-master:build_shell_commands:
        - "master.sh"

        branch-milky_way:build_batch_commands:
        - "milky_way.bat"

        branch-with-hyphens-in-name:build_batch_commands:
        - "crazy.bat"
        ''')

    jd_file = JobsDoneJob.CreateFromYAML(yaml_contents,
                                         repository=Repository(
                                             url='https://space.git',
                                             branch='milky_way'))[0]
    assert jd_file.build_shell_commands is None
    assert jd_file.build_batch_commands == ['milky_way.bat']

    jd_file = JobsDoneJob.CreateFromYAML(yaml_contents,
                                         repository=Repository(
                                             url='https://space.git',
                                             branch='master'))[0]
    assert jd_file.build_shell_commands == ['master.sh']
    assert jd_file.build_batch_commands is None
def testUnmatchableSubCondition():
    contents = dedent('''
        git:
            planet-pluto:shallow: true

        matrix:
            planet:
            - earth
        ''')
    with pytest.raises(UnmatchableConditionError) as e:
        JobsDoneJob.CreateFromYAML(contents, repository=_REPOSITORY)
    assert e.value.option == 'planet-pluto:shallow'

    contents = dedent('''
        additional_repositories:
        - git:
            planet-pluto:shallow: true

        matrix:
            planet:
            - earth
        ''')
    with pytest.raises(UnmatchableConditionError) as e:
        JobsDoneJob.CreateFromYAML(contents, repository=_REPOSITORY)
    assert e.value.option == 'planet-pluto:shallow'
def testBranchPatterns():
    base_contents = dedent('''
        matrix:
            planet:
            - mars
            - earth
            - venus

        ''')
    # Using a pattern that does not match our branch will prevent jobs from being generated
    jd_file_contents = base_contents + dedent('''
        branch_patterns:
        - feature-.*
        ''')
    jobs = JobsDoneJob.CreateFromYAML(jd_file_contents, repository=_REPOSITORY)
    assert len(jobs) == 0

    # Matching patterns work as usual
    jd_file_contents = base_contents + dedent('''
        branch_patterns:
        - milky_way
        ''')
    jobs = JobsDoneJob.CreateFromYAML(jd_file_contents, repository=_REPOSITORY)
    assert len(jobs) == 3

    # Also works with several patterns and regexes
    jd_file_contents = base_contents + dedent('''
        branch_patterns:
        - master
        - milky.*
        ''')
    jobs = JobsDoneJob.CreateFromYAML(jd_file_contents, repository=_REPOSITORY)
    assert len(jobs) == 3

    # Branch patterns can also be filtered using matrix
    # e.g., mars only has jobs in master
    jd_file_contents = base_contents + dedent('''
        planet-mars:branch_patterns:
        - "master"

        planet-earth:branch_patterns:
        - ".*"

        planet-venus:branch_patterns:
        - ".*"
        ''')
    jobs = JobsDoneJob.CreateFromYAML(jd_file_contents, repository=_REPOSITORY)
    assert len(jobs) == 2
def testAllowOverridingConditions():
    '''
    ..see: `testRaiseWithAmbiguousConditionsAndDifferentValues` for more details
    '''
    yaml_contents = dedent('''
        matrix:
            platform:
            - linux
            - windows

            slave:
            - slave1
            - slave2

        display_name: "Generic job"
        platform-linux:display_name: "Linux job"
        platform-linux:slave-slave2:display_name: "slave2 job"
        ''')
    for jd_file in JobsDoneJob.CreateFromYAML(yaml_contents,
                                              repository=_REPOSITORY):
        if jd_file.matrix_row['platform'] == 'linux':
            if jd_file.matrix_row['slave'] == 'slave1':
                assert jd_file.display_name == 'Linux job'
            else:
                assert jd_file.display_name == 'slave2 job'
        else:
            assert jd_file.display_name == 'Generic job'
def testIgnoreAmbiguousConditionsWithEqualValues():
    '''
    ..see: `testRaiseWithAmbiguousConditionsAndDifferentValues` for more details

    Even though we should raise when there are multiple matched lines with ambiguous conditions, we
    should ignore when the value does not change. This is very useful when you have a large matrix
    and need to set the same value for a lot of them.
    '''
    yaml_contents = dedent('''
        matrix:
            platform:
            - linux
            - windows

            slave:
            - slave1
            - slave2

        platform-linux:display_name: "Foo job"
        slave-slave2:display_name: "Foo job"
        ''')
    for jd_file in JobsDoneJob.CreateFromYAML(yaml_contents,
                                              repository=_REPOSITORY):
        if jd_file.matrix_row['platform'] == 'linux' or jd_file.matrix_row[
                'slave'] == 'slave2':
            assert jd_file.display_name == 'Foo job'
        else:
            assert jd_file.display_name is None
def testMatrixAndFlagsForSubDicts():
    yaml_contents = dedent('''
        git:
          platform-windows:shallow: true
          platform-linux:shallow: false

        additional_repositories:
        - git:
              platform-windows:shallow: true
              platform-linux:shallow: false

        matrix:
            platform:
            - linux
            - windows
        ''')
    for jd_file in JobsDoneJob.CreateFromYAML(yaml_contents,
                                              repository=_REPOSITORY):
        if jd_file.matrix_row['platform'] == 'linux':
            assert jd_file.git == {'shallow': 'false'}
            assert jd_file.additional_repositories == [{
                'git': {
                    'shallow': 'false'
                }
            }]
        else:
            assert jd_file.git == {'shallow': 'true'}
            assert jd_file.additional_repositories == [{
                'git': {
                    'shallow': 'true'
                }
            }]
def testMatrixAndExtraFlags():
    yaml_contents = dedent('''
        platform-windows:junit_patterns:
        - "junit*.xml"

        platform-linux:build_shell_commands:
        - "linux command: {platform}"

        platform-windows:build_batch_commands:
        - "windows command: {platform}"

        matrix:
            platform:
            - win32,windows
            - win64,windows
            - linux64,linux
        ''')
    for jd_file in JobsDoneJob.CreateFromYAML(yaml_contents,
                                              repository=_REPOSITORY):
        if jd_file.matrix_row['platform'] == 'linux64':
            assert jd_file.junit_patterns is None
            assert jd_file.build_batch_commands is None
            assert jd_file.build_shell_commands == ['linux command: linux64']
        if jd_file.matrix_row['platform'] == 'win32':
            assert jd_file.junit_patterns == ['junit*.xml']
            assert jd_file.build_batch_commands == ['windows command: win32']
            assert jd_file.build_shell_commands is None
def testMatrixAndFlags():
    yaml_contents = dedent('''
        platform-windows:junit_patterns:
        - "junit*.xml"

        platform-linux:build_shell_commands:
        - "{platform} command"

        platform-windows:build_batch_commands:
        - "{platform} command"

        matrix:
            platform:
            - linux
            - windows
        ''')
    for jd_file in JobsDoneJob.CreateFromYAML(yaml_contents,
                                              repository=_REPOSITORY):
        if jd_file.matrix_row['platform'] == 'linux':
            assert jd_file.junit_patterns is None
            assert jd_file.build_batch_commands is None
            assert jd_file.build_shell_commands == ['linux command']
        else:
            assert jd_file.junit_patterns == ['junit*.xml']
            assert jd_file.build_batch_commands == ['windows command']
            assert jd_file.build_shell_commands is None
Beispiel #9
0
def GetJobsFromFile(repository, jobs_done_file_contents):
    '''
    Creates jobs from repository information and a jobs_done file.

    :param Repository repository:
        .. seealso:: Repository

    :param unicode|None jobs_done_file_contents:
        .. seealso:: JobsDoneJob.CreateFromYAML

    :return set(JenkinsJob)
    '''
    from jobs_done10.job_generator import JobGeneratorConfigurator
    from jobs_done10.jobs_done_job import JobsDoneJob

    jenkins_generator = JenkinsXmlJobGenerator()

    jobs = []
    jobs_done_jobs = JobsDoneJob.CreateFromYAML(jobs_done_file_contents,
                                                repository)
    for jobs_done_job in jobs_done_jobs:
        JobGeneratorConfigurator.Configure(jenkins_generator, jobs_done_job)
        jobs.append(jenkins_generator.GetJob())

    return jobs
Beispiel #10
0
def testUnknownOption():
    # Unknown options should fail
    yaml_contents = dedent('''
        bad_option: value
        ''')
    with pytest.raises(UnknownJobsDoneFileOption) as e:
        JobsDoneJob.CreateFromYAML(yaml_contents, repository=_REPOSITORY)

    assert e.value.option_name == 'bad_option'
Beispiel #11
0
def testStripFile():
    '''
    Asserts that we can handle empty spaces and tabs in .yaml files, without having parse errors
    '''
    contents = dedent('''
        junit_patterns:
            - 1
        ''')
    contents += '\t'
    JobsDoneJob.CreateFromYAML(contents, repository=_REPOSITORY)
Beispiel #12
0
def testStringConversion():
    '''
    Asserts that our YAML parser converts all basic values to strings (non unicode)
    '''
    contents = dedent('''
        junit_patterns:
            - 1
        ''')
    jobs = JobsDoneJob.CreateFromYAML(contents, repository=_REPOSITORY)

    assert jobs[0].junit_patterns != [1]
    assert jobs[0].junit_patterns == ['1']
Beispiel #13
0
def testTypeChecking():
    # List is the correct type for build_batch_commands
    yaml_contents = dedent('''
        build_batch_commands:
        - "list item 1"
        ''')
    JobsDoneJob.CreateFromYAML(yaml_contents, repository=_REPOSITORY)

    # Trying to set a different value, should raise an error
    yaml_contents = dedent('''
        build_batch_commands: "string item"
        ''')
    with pytest.raises(JobsDoneFileTypeError) as e:
        JobsDoneJob.CreateFromYAML(yaml_contents, repository=_REPOSITORY)

    assert e.value.option_name == 'build_batch_commands'
    assert e.value.accepted_types == [
        JobsDoneJob.PARSEABLE_OPTIONS['build_batch_commands']
    ]
    assert e.value.obtained_type == str
    assert e.value.option_value == 'string item'
Beispiel #14
0
def testCreateFromFile(tmpdir):
    contents = dedent('''
        matrix:
            planet:
            - mars
            - earth
            - venus

        ''')
    f = tmpdir / '.jobs_done.yaml'
    f.write(contents)

    jobs = JobsDoneJob.CreateFromFile(str(f), repository=_REPOSITORY)

    assert len(jobs) == 3
Beispiel #15
0
def testRaiseWithAmbiguousConditionsAndDifferentValues():
    '''
    When we match more than one line for the same key, we need to choose only one of them
    consistently regardless of the order in which they appear.
    To do that the conditions present on one line should be a superset of other one. In the end
    the largest superset will be chosen.

    For example, for "platform=linux" and "slave=slave2" the following lines would be ambiguous:

        platform-linux:display_name: "Linux job"
        slave-slave2:display_name: "slave2 job"

    In this case, there are some matrix combinations that will match both lines and there is no
    obvious rule we can apply to choose one of them. Which one has priority: platform or slave?

    For the above example to work we need to make one line a superset of the other:

        platform-linux:display_name: "Linux job"
        platform-linux:slave-slave2:display_name: "slave2 job"

    And the second line would be chosen.


    NOTE:

    These rules are only relevant when multiple lines match. For example, if we have two
    exclusive lines like:

        platform-linux:display_name: "Linux job"
        platform-windows:display_name: "slave2 job"

    They are not ambiguous as only one will match for every matrix combination.
    '''
    yaml_contents = dedent('''
        matrix:
            platform:
            - linux
            - windows

            slave:
            - slave1
            - slave2

        platform-linux:display_name: "Linux job"
        slave-slave2:display_name: "slave2 job"
        ''')
    with pytest.raises(ValueError):
        JobsDoneJob.CreateFromYAML(yaml_contents, repository=_REPOSITORY)
Beispiel #16
0
def testUnmatchableCondition():
    '''
    Asserts that using a condition that can never be matched will raise an error.
    '''
    contents = dedent('''
        planet-pluto:junit_patterns:
            - '*.xml'

        matrix:
            planet:
            - earth
        ''')
    with pytest.raises(UnmatchableConditionError) as e:
        JobsDoneJob.CreateFromYAML(contents, repository=_REPOSITORY)

    assert e.value.option == 'planet-pluto:junit_patterns'
Beispiel #17
0
def testIgnoreUnmatchable():
    '''
    Asserts that using a condition that can never be matched will not raise an error if
    'ignore_unmatchable' is enabled.
    '''
    contents = dedent('''
        ignore_unmatchable: true

        planet-pluto:junit_patterns:
            - '*.xml'

        matrix:
            planet:
            - earth
        ''')
    JobsDoneJob.CreateFromYAML(contents, repository=_REPOSITORY)
Beispiel #18
0
def testJobGeneratorConfigurator():
    class MyGenerator(object):
        def SetRepository(self, repository):
            assert repository.url == 'http://repo.git'

        def SetMatrix(self, matrix, matrix_row):
            assert matrix == {'id': [1, 2, 3]}
            assert matrix_row == {'id': 1}

        def SetBuildBatchCommands(self, commands):
            assert commands == ['command']

        def Reset(self):
            pass

    jobs_done_job = JobsDoneJob()
    jobs_done_job.matrix = {'id': [1, 2, 3]}
    jobs_done_job.matrix_row = {'id': 1}
    jobs_done_job.repository = Repository(url='http://repo.git')

    generator = MyGenerator()

    # Test basic calls
    with ExpectedCalls(generator,
                       Reset=1,
                       SetRepository=1,
                       SetMatrix=1,
                       SetBuildBatchCommands=0):
        JobGeneratorConfigurator.Configure(generator, jobs_done_job)

    # Set some more values to jobs_done_job, and make sure it is called
    jobs_done_job.build_batch_commands = ['command']
    with ExpectedCalls(generator,
                       Reset=1,
                       SetRepository=1,
                       SetMatrix=1,
                       SetBuildBatchCommands=1):
        JobGeneratorConfigurator.Configure(generator, jobs_done_job)

    # Try calling a missing option
    jobs_done_job.boosttest_patterns = 'patterns'
    with pytest.raises(JobGeneratorAttributeError):
        JobGeneratorConfigurator.Configure(generator, jobs_done_job)
def testJobGeneratorConfigurator():
    class MyGenerator(object):
        ImplementsInterface(IJobGenerator)

        def SetRepository(self, repository):
            assert repository.url == 'http://repo.git'

        def SetMatrix(self, matrix, matrix_row):
            assert matrix == {'id':[1,2,3]}
            assert matrix_row == {'id':1}

        def SetBuildBatchCommands(self, commands):
            assert commands == ['command']

        def Reset(self):
            pass

    jobs_done_job = JobsDoneJob()
    jobs_done_job.matrix = {'id':[1,2,3]}
    jobs_done_job.matrix_row = {'id':1}
    jobs_done_job.repository = Repository(url='http://repo.git')

    generator = MyGenerator()

    # Test basic calls
    with ExpectedCalls(generator, Reset=1, SetRepository=1, SetMatrix=1, SetBuildBatchCommands=0):
        JobGeneratorConfigurator.Configure(generator, jobs_done_job)

    # Set some more values to jobs_done_job, and make sure it is called
    jobs_done_job.build_batch_commands = ['command']
    with ExpectedCalls(generator, Reset=1, SetRepository=1, SetMatrix=1, SetBuildBatchCommands=1):
        JobGeneratorConfigurator.Configure(generator, jobs_done_job)

    # Try calling a missing option
    jobs_done_job.boosttest_patterns = 'patterns'
    with pytest.raises(JobGeneratorAttributeError):
        JobGeneratorConfigurator.Configure(generator, jobs_done_job)
Beispiel #20
0
def testExclude():
    key = lambda job: ':'.join(j + '-' + job.matrix_row[j]
                               for j in sorted(job.matrix_row.keys()))
    # Base case ------------------------------------------------------------------------------------
    yaml_contents = dedent('''
        matrix:
          planet:
          - mercury
          - venus

          moon:
          - europa
          - ganymede

        ''')
    jobs_done_jobs = JobsDoneJob.CreateFromYAML(yaml_contents,
                                                repository=_REPOSITORY)
    assert sorted(map(key, jobs_done_jobs)) == [
        'moon-europa:planet-mercury', 'moon-europa:planet-venus',
        'moon-ganymede:planet-mercury', 'moon-ganymede:planet-venus'
    ]

    # Exclude everything matching planet-venus -----------------------------------------------------
    yaml_contents = dedent('''
        matrix:
          planet:
          - mercury
          - venus

          moon:
          - europa
          - ganymede

        planet-venus:exclude: yes
        ''')
    jobs_done_jobs = JobsDoneJob.CreateFromYAML(yaml_contents,
                                                repository=_REPOSITORY)
    assert sorted(map(key, jobs_done_jobs)) == [
        'moon-europa:planet-mercury',
        'moon-ganymede:planet-mercury',
    ]

    # Exclude everything matching planet-venus and moon europa -------------------------------------
    yaml_contents = dedent('''
        matrix:
          planet:
          - mercury
          - venus

          moon:
          - europa
          - ganymede

        planet-venus:moon-europa:exclude: yes
        ''')
    jobs_done_jobs = JobsDoneJob.CreateFromYAML(yaml_contents,
                                                repository=_REPOSITORY)
    assert sorted(map(key, jobs_done_jobs)) == [
        'moon-europa:planet-mercury', 'moon-ganymede:planet-mercury',
        'moon-ganymede:planet-venus'
    ]

    # Exclude everything ---------------------------------------------------------------------------
    yaml_contents = dedent('''
        matrix:
          planet:
          - mercury
          - venus

          moon:
          - europa
          - ganymede

        exclude: yes
        ''')
    jobs_done_jobs = JobsDoneJob.CreateFromYAML(yaml_contents,
                                                repository=_REPOSITORY)
    assert sorted(map(key, jobs_done_jobs)) == []
Beispiel #21
0
def testCreateJobsDoneJobFromYAML():
    yaml_contents = dedent('''
        junit_patterns:
        - "junit*.xml"

        boosttest_patterns:
        - "cpptest*.xml"

        display_name: "[{branch}] {planet}-{moon} {name}"

        label_expression: "planet-{planet}&&moon-{moon}"

        parameters:
        - choice:
            name: "PARAM"
            choices:
            - "choice_1"
            - "choice_2"
            description: "Description"

        build_batch_commands:
        - "command on planet {planet} (repository '{name}' on '{branch}')"

        matrix:
          planet:
          - mercury
          - venus

          moon:
          - europa
        ''')
    jobs_done_jobs = JobsDoneJob.CreateFromYAML(yaml_contents,
                                                repository=_REPOSITORY)

    # Two possible jobs based on matrix (mercury and venus)
    assert len(jobs_done_jobs) == 2

    def CheckCommonValues(jobs_done_job):
        assert jobs_done_job.matrix == {
            'moon': ['europa'],
            'planet': ['mercury', 'venus']
        }
        assert jobs_done_job.junit_patterns == ['junit*.xml']
        assert jobs_done_job.boosttest_patterns == ['cpptest*.xml']
        assert jobs_done_job.parameters == [{
            'choice': {
                'name': 'PARAM',
                'choices': ['choice_1', 'choice_2'],
                'description': 'Description',
            }
        }]

    CheckCommonValues(jobs_done_jobs[0])
    CheckCommonValues(jobs_done_jobs[1])

    # Tests for specific jobs
    mercury_job = jobs_done_jobs[0] if jobs_done_jobs[0].matrix_row[
        'planet'] == 'mercury' else jobs_done_jobs[1]
    venus_job = jobs_done_jobs[0] if jobs_done_jobs[0].matrix_row[
        'planet'] == 'venus' else jobs_done_jobs[1]

    assert mercury_job.matrix == {
        'moon': ['europa'],
        'planet': ['mercury', 'venus']
    }
    assert mercury_job.matrix_row == {'moon': 'europa', 'planet': 'mercury'}

    assert venus_job.matrix == {
        'moon': ['europa'],
        'planet': ['mercury', 'venus']
    }
    assert venus_job.matrix_row == {'moon': 'europa', 'planet': 'venus'}

    # In this case, our commands use some replacement variables, including variables defined in
    # 'matrix', and special cases 'name' and 'branch' based on repository.
    assert mercury_job.build_batch_commands == [
        "command on planet mercury (repository 'space' on 'milky_way')"
    ]
    assert venus_job.build_batch_commands == [
        "command on planet venus (repository 'space' on 'milky_way')"
    ]

    # Check display_name
    assert mercury_job.display_name == '[milky_way] mercury-europa space'
    assert mercury_job.label_expression == 'planet-mercury&&moon-europa'

    # Check labels
    assert venus_job.display_name == '[milky_way] venus-europa space'
    assert venus_job.label_expression == 'planet-venus&&moon-europa'