2014/09/22

git subtree

git subtree 的用法

假如有一个iOS的项目,我用到了很多外部的库,如AFNetworking,我怎么把它集成进来呢?

通过submodule的方法

把这个项目追加到自己是项目中:

git submodule add git@github.com:AFNetworking/AFNetworking.git Vendor/AFNetworking

然后看看因此而出现的问题:

好吧,如果当你发现一个AFNetworking的bug呢.而且你有办法能够fix它,通过submodule, 怎么办?
通常都是这样的:

  1. 先fork这个项目
  2. 修改之前添加的那个submodule,改成对应你自己fork的那一个,
  3. 修改你的那个fork
  4. 来一个pull request 给AFNetworking.
  5. 等待那个PR是否能够通过, 且同时保持你的fork能够最新,
  6. 如果接受了,那就再把你的submodule给切到官方的repo上,
  7. 继续
    好吧,我感觉到什么的路子很屎.如果你没有真正体验过你是感觉不到到底有多屎的.

如果subtree的方式

首先还是添加那个工程到你的

git subtree add –prefix=Vendor/AFNetworking –squash git@github.com:AFNetworking/AFNetworking.git master

看上去很相似目前为止除了你的伙伴不知道怎么git submodule update,因为subtrees确实是把source保存在你的项目中的.
现在,我们再看看上面出现的场景,有了bug怎么办,处理上有什么不同的呢?
我做了修改,然后提交到了我的repo中,技术上来说,我现在可以停下来,因为修复bug的代码就在我的repo里,但是,我是一个好的开源市民啊,我要怎么办呢?

做一个好的开源市民

  1. 我要fork AFNetworking 这个repo到我的项目中
  2. 回到的本地的repo

    git subtree split –prefix=Vendor/AFNetworking/ –branch AFNetworking


通过这个命令配置,可以让我推这个修改到我的分支上,而不是等待做一个PR,然后等待merge,帅不?

git push git@github.com:kvnsmth/AFNetworking.git AFNetworking:critical-bug-fix

  1. 我会建立一个PR希望能够被merge, 这个方式有很大的不同就是合并我的PR与否都不会影响我轻松得和官方的AFNetworking同步.

我还可以这样做:

git subtree pull –prefix=Vendor/AFNetworking –squash git@github.com:AFNetworking/AFNetworking.git master

这样我可以保持和官方最新的代码同步.

现在,我想这样的方式大大的好于使用submodule的方式

2014/09/09

Jenkins build flow plugin

Jenkins build flow plugin

关于build flow plugin

概要

This plugin is designed to handle complex build workflows (aka build pipelines) as a dedicated entity in Jenkins.
Without such a plugin, to manage job orchestration the user has to combine parameterized-build, join, downstream-ext
and a few more plugins, polluting the job configuration.
The build process is then scattered in all those jobs and very complex to maintain.
Build Flow enables you to define an upper level Flow item to manage job orchestration and link up rules,
using a dedicated DSL. This DSL makes the flow definition very concise and readable.

配置

基础

  1. 定义了job 序列

    build( "job1" )
    build( "job2" )
    build( "job3" )
    
  2. 定义一个环境变量通过下面的方式

    def revision = b.environment.get("GIT_REVISION")
    
  3. 预定义的变量

    You can also access some pre-defined variables in the DSL :
    
    "build" the current flow execution
    "out" the flow build console
    "env" the flow environment, as a Map
    "params" triggered parameters
    "upstream" the upstream job, assuming the flow has been triggered as a downstream job for another job.
    
  4. Guard/ Rescue

执行结束之后的收尾工作, 如java里的try-finally块.

guard {
    build( "this_job_may_fail" )
} rescue {
    build( "cleanup" )
}

5. ignore

一个任务的结果可以忽略的. 他们在你的flow里可以被忽略.使用 ignore

ignore(FAILURE) {
    build( "send_twitter_notification" )
}

6. 重试

    retry ( 3 ) {
        build( "this_job_may_fail" )
    }       

7. parallel

flow是一个严格定义的序列.但是能够并行执行,等待完成.

parallel (
    // job 1, 2 and 3 will be scheduled in parallel.
    { build("job1") },
    { build("job2") },
    { build("job3") }
)
// job4 will be triggered after jobs 1, 2 and 3 complete
build("job4")

parallel区别于join插件的就是它可以串联很多的并行

parallel (
    {
        build("job1A")
        build("job1B")
        build("job1C")
    },
    {
        build("job2A")
        build("job2B")
        build("job2C")
    }
)

另外, 它还可以和其他的结合关键字混用:

parallel (
    {
        guard {
            build("job1A")
        } rescue {
            build("job1B")
        }
    },
    {
        retry 3, {
            build("job2")
        }
    }
)

扩展点