Build and Release

A continuous learner for experience and life.

Playing With Gerrit Jira Plugin

Gerrit

Build and Setup

1. Clone the Gerrit source:

1
$ git clone https://gerrit.googlesource.com/gerrit

2. Checkout to version 2.8 (2.8 is the latest stable version), include to update submodules:

1
2
3
$ cd gerrit
$ git checkout -b stable-2.8 stable-2.8
$ git submodule update --init --rebase # commands, please referece to git submodule

3. Clone buck, buck is the build system for the latest Gerrit, then build it with ant (‘sudo apt-get install ant’):

1
2
3
$ git clone https://gerrit.googlesource.com/buck
$ cd buck
$ ant

4. Install buck to be accessed globally:

1
2
3
4
5
$ mkdir ~/bin
$ export PATH=~/bin:$PATH
$ ln -s `pwd`/bin/buck ~/bin/
$ ln -s `pwd`/bin/buckd ~/bin/
$ which buck

5. Build Gerrit:

1
2
$ cd gerrit
$ buck build gerrit

NOTE: The gerrit.war will be generated here: buck-out/gen/gerrit.war

6. Build extension, plugin, GWT API jar files, and install them:

1
2
$ buck build api
$ buck build api_install

7. Build all core plugins (optional):

1
$ buck build plugins:core

NOTE: All core plugins will be generated here: buck-out/gen/plugins/<name>/<name>.jar

8. Clone the hooks-its, and hooks-jira projects:

1
2
3
4
5
$ git clone https://gerrit.googlesource.com/plugins/hooks-its plugins/hooks-its
$ cd plugins/hooks-its
$ git checkout -b v2.8 origin/stable-2.8
$ cd ../..
$ git clone https://gerrit.googlesource.com/plugins/hooks-jira plugins/hooks-jira

9. Modify the pom.xml files under plugins/hooks-its AND plugins/hooks-its/hooks-its:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
cd plugins/hooks-its
$ git diff
diff --git a/hooks-its/pom.xml b/hooks-its/pom.xml
index a206459..75e11dc 100644
--- a/hooks-its/pom.xml
+++ b/hooks-its/pom.xml
@@ -22,7 +22,7 @@ limitations under the License.
   <parent>
     <groupId>com.googlesource.gerrit.plugins.its</groupId>
     <artifactId>hooks-its-parent</artifactId>
-    <version>2.9-SNAPSHOT</version>
+    <version>2.8</version>
   </parent>
   <artifactId>hooks-its</artifactId>
   <name>Gerrit Code Review - Commit validation and Workflow</name>
diff --git a/pom.xml b/pom.xml
index 600bff9..995d008 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@ limitations under the License.
   <groupId>com.googlesource.gerrit.plugins.its</groupId>
   <artifactId>hooks-its-parent</artifactId>
   <packaging>pom</packaging>
-  <version>2.9-SNAPSHOT</version>
+  <version>2.8</version>

   <name>Gerrit Code Review - Issue tracker support</name>

10. Build the hooks-its:

1
2
$ cd plugins/hooks-its
$ mvn -DskipTests -Dmaven.test.skip=true package install

NOTE: The hooks-its-2.8.jar will be generated here: hooks-its/target/hooks-its-2.8.jar NOTE: If don’t skip tests, run with the command: mvn clean package install, then will fail on test case! NOTE: Gerrit select BUCK as its new build system, for new plugin, please reference to the following NOTES #5

11. Modify the pom.xml files under plugins/hooks-jira:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ cd plugins/hooks-jira
$ git diff
diff --git a/pom.xml b/pom.xml
index 7b04c60..8f60c78 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@ limitations under the License.
   <parent>
     <groupId>com.googlesource.gerrit.plugins.its</groupId>
     <artifactId>hooks-its-parent</artifactId>
-    <version>2.9-SNAPSHOT</version>
+    <version>2.8</version>
   </parent>
   <artifactId>hooks-jira</artifactId>
   <packaging>jar</packaging>

12. Build the hooks-jira:

1
2
$ cd plugins/hooks-jira
$ mvn clean package

NOTE: The hooks-jira-2.8.jar will be generated here: target/hooks-jira-2.8.jar

13. Copy the following jar files to the plugin folder under the Gerrit installation path on remote server:

1
2
hooks-its-2.8.jar
hooks-jira-2.8.jar

For example:

1
$ scp hooks-its/target/hooks-its-2.8.jar ../hooks-jira/target/hooks-jira-2.8.jar gerrit2@review.example.co:/home/gerrit2/review_site/plugins

14. Add a new file etc/its/action.config under the Gerrit installation path on remote server:

1
2
3
4
5
6
7
8
9
10
11
12
[rule "merged"]
        event-type = change-merged
        action = add-standard-comment
[rule "comment"]
        event-type = comment-added
        action = add-standard-comment
[rule "patch-set"]
        event-type = patchset-created
        action = add-standard-comment
[rule "ref-updated"]
        event-type = ref-updated
        action = add-standard-comment

15. Run the Gerrit initial installation command on remote server:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
$ java -jar gerrit-2.8.war init -d review_site

*** Gerrit Code Review 2.8
***


*** Git Repositories
***

Location of Git repositories   [git]:

*** SQL Database
***

Database server type           [mysql]:
Server hostname                [localhost]:
Server port                    [(mysql default)]:
Database name                  [reviewdb]:
Database username              [gerrit2]:
Change gerrit2's password      [y/N]?

*** User Authentication
***

Authentication method          [DEVELOPMENT_BECOME_ANY_ACCOUNT/?]:

*** Email Delivery
***

SMTP server hostname           [localhost]:
SMTP server port               [(default)]:
SMTP encryption                [NONE/?]:
SMTP username                  [gerrit2]:
Change gerrit2's password      [y/N]?

*** Container Process
***

Run as                         [gerrit2]:
Java runtime                   [C:\Program Files (x86)\Java\jre7]:
Upgrade c:\Users\gerrit2\gerrit\bin\gerrit.war [Y/n]?
Copying gerrit-2.8.war to c:\Users\gerrit2\gerrit\bin\gerrit.war

*** SSH Daemon
***

Listen on address              [*]:
Listen on port                 [29418]:

*** HTTP Daemon
***

Behind reverse proxy           [y/N]?
Use SSL (https://)             [y/N]?
Listen on address              [*]:
Listen on port                 [8080]:
Canonical URL                  [http://review.example.com:8080/]:

*** Plugins
***

Install plugin reviewnotes version v2.8 [y/N]?
Install plugin download-commands version v2.8 [y/N]?
Install plugin replication version v2.8 [y/N]?
Install plugin commit-message-length-validator version v2.8 [y/N]?


*** Jira connectivity
***

Jira URL (empty to skip)       [https://jira.example.com/]:
Jira username                  [jira-robot]:
Change jira-robot's password        [y/N]?
Test connectivity to https://jira.example.com [y/N]? y
Checking Jira connectivity ... [OK]

*** Jira issue-tracking association
***

Jira issue-Id regex            [([A-Z]+-[0-9]+)]:
Issue-id enforced in commit message [MANDATORY/?]:?
Supported options are:
           mandatory
           suggested
           optional
Issue-id enforced in commit message [MANDATORY/?]: suggested
Initialized C:\Users\gerrit2\gerrit

16. Restart gerrit-jetty service:

1
$ sudo service gerrit-jetty.sh restart

17. Done!

NOTES:

1. Download Gerrit here: http://gerrit-releases.storage.googleapis.com/index.html

2. The file review_site/etc/gerrit.config should look like:

1
2
3
4
5
6
7
8
[jira]
        url = http://review.example.com:8080
        username = jira-robot
        commentOnRefUpdatedGitWeb = false   # to comment gitweb comments on jira
[commentLink "jira"]
        match = ([A-Z]+-[0-9]+)
        html = <a href=\"http://jira.example.com:8080/browse/$1\">$1</a>
        association = SUGGESTED

3. If we just want to parse the jira id on the subject of the git comments, then here is the diff:

1
2
3
4
5
6
7
8
9
10
11
12
13
diff --git a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/util/
index a04b175..3d56426 100644
--- a/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/util/CommitM
+++ b/hooks-its/src/main/java/com/googlesource/gerrit/plugins/hooks/util/CommitM
@@ -31,7 +31,7 @@ public class CommitMessageFetcher {
       RevWalk revWalk = new RevWalk(repo);
       RevCommit commit = revWalk.parseCommit(ObjectId.fromString(commitId));

-      return commit.getFullMessage();
+      return commit.getShortMessage();
     } finally {
       repo.close();
     }

4. Get the log message from jetty/logs on Gerrit server. 5. Gerrit choose BUCK as its new build system, so for the new plugin, the build steps should be (take cookbook-plugin as an example):

1
buck build plugins/cookbook-plugin

The output is created in: buck-out/gen/plugins/cookbook-plugin/cookbook-plugin.jar

References:

1. https://groups.google.com/forum/#!msg/repo-discuss/GSyHMeaCyyw/cJGunFcNc4oJ 2. https://gerrit-review.googlesource.com/Documentation/dev-buck.html

Written with StackEdit.

Playing With Jenkins Create Job

Jenkins logo

create new job from templates

In this article, we will talk about how to create a Jenkins job with a template by some commands.

Instructions

1. Get the Jenkins CLI client package

1
$ wget http://jenkins/jnlpJars/jenkins-cli.jar

2. Check which commands supported by the client package [Exception 1,2]

1
$ java -jar jenkins-cli.jar -s http://jenkins/ help

3. List all jobs under the view: tools

1
$ java -jar jenkins-cli.jar -s http://jenkins/ list-jobs tools

4. Get the configuration of the job: template

1
$ java -jar jenkins-cli.jar -s http://jenkins/ get-job template > template.xml

5. Create a new job based on the configuration

1
$ java -jar jenkins-cli.jar -s http://jenkins/ create-job new_job_name < new_job_name.xml

6. Run groovy script

1
$ java -jar jenkins-cli.jar -s http://jenkins/ groovy scripts/add_job_to_view.groovy

If there are any parameters in the script, just as:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import jenkins.model.*

if (args.length != 2 ) {
  println "Error on arguments!"
}
def jobName  = args[0] ?: 'a_job'
def viewName = args[1] ?: 'a_view'

println jobName + ' ' + viewName

def v = Jenkins.instance.getView(viewName)
def i = Jenkins.instance.getItemByFullName(jobName)
if (v && i) {
  v.add(i)
}

pass the parameters as:

1
$ java -jar jenkins-cli.jar -s http://jenkins/ groovy scripts/add_job_to_view.groovy JOB_NAME VIEM_NAME

7. Build a job

1
$ java -jar jenkins-cli.jar -s http://jenkins/ build new_job_name

8. Diable a job

1
$ java -jar jenkins-cli.jar -s http://jenkins/ disable-job new_job_name

Exceptions:

1. Description:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Exception in thread "main" java.io.IOException: No X-Jenkins-CLI2-Port among [null, Vary, Date, Content-Length, Keep-Alive, Set-Cookie, Connection, Content-Type, X-Powered-By, Server]
  at hudson.cli.CLI.getCliTcpPort(CLI.java:281)
  at hudson.cli.CLI.<init>(CLI.java:128)
  at hudson.cli.CLIConnectionFactory.connect(CLIConnectionFactory.java:72)
  at hudson.cli.CLI._main(CLI.java:449)
  at hudson.cli.CLI.main(CLI.java:378)
  Suppressed: java.io.EOFException: unexpected stream termination
      at hudson.remoting.ClassicCommandTransport.create(ClassicCommandTransport.java:100)
      at hudson.remoting.Channel.<init>(Channel.java:392)
      at hudson.remoting.Channel.<init>(Channel.java:388)
      at hudson.remoting.Channel.<init>(Channel.java:349)
      at hudson.remoting.Channel.<init>(Channel.java:345)
      at hudson.remoting.Channel.<init>(Channel.java:333)
      at hudson.cli.CLI.connectViaHttp(CLI.java:159)
      at hudson.cli.CLI.<init>(CLI.java:132)
      ... 3 more

Solution: check the port which Jenkins is running on, put 8080 on URL should fix, just as:

1
$ java -jar jenkins-cli.jar -s http://jenkins:8080/ help

2. Description:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Failed to authenticate with your SSH keys.
hudson.security.AccessDeniedException2: anonymous is missing the ExtendedRead permission
  at hudson.security.ACL.checkPermission(ACL.java:54)
  at hudson.model.AbstractItem.checkPermission(AbstractItem.java:441)
  at hudson.cli.GetJobCommand.run(GetJobCommand.java:46)
  at hudson.cli.CLICommand.main(CLICommand.java:229)
  at hudson.cli.CliManagerImpl.main(CliManagerImpl.java:92)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:616)
  at hudson.remoting.RemoteInvocationHandler$RPCRequest.perform(RemoteInvocationHandler.java:275)
  at hudson.remoting.RemoteInvocationHandler$RPCRequest.call(RemoteInvocationHandler.java:256)
  at hudson.remoting.RemoteInvocationHandler$RPCRequest.call(RemoteInvocationHandler.java:215)
  at hudson.remoting.UserRequest.perform(UserRequest.java:118)
  at hudson.remoting.UserRequest.perform(UserRequest.java:48)
  at hudson.remoting.Request$2.run(Request.java:326)
  at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72)
  at hudson.cli.CliManagerImpl$1.call(CliManagerImpl.java:63)
  at hudson.remoting.InterceptingExecutorService$2.call(InterceptingExecutorService.java:95)
  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
  at java.util.concurrent.FutureTask.run(FutureTask.java:166)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
  at java.lang.Thread.run(Thread.java:679)

Solution: add client public ssh key to the Jenkins server at: http://jenkins/user/USERNAME/configure | SSH Public Keys.

3. Description:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
hudson.security.AccessDeniedException2: <USERNAME> is missing the Job/ExtendedRead permission
  at hudson.security.ACL.checkPermission(ACL.java:54)
  at hudson.model.AbstractItem.checkPermission(AbstractItem.java:446)
  at hudson.cli.GetJobCommand.run(GetJobCommand.java:46)
  at hudson.cli.CLICommand.main(CLICommand.java:234)
  at hudson.cli.CliManagerImpl.main(CliManagerImpl.java:92)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at hudson.remoting.RemoteInvocationHandler$RPCRequest.perform(RemoteInvocationHandler.java:300)
  at hudson.remoting.RemoteInvocationHandler$RPCRequest.call(RemoteInvocationHandler.java:281)
  at hudson.remoting.RemoteInvocationHandler$RPCRequest.call(RemoteInvocationHandler.java:240)
  at hudson.remoting.UserRequest.perform(UserRequest.java:118)
  at hudson.remoting.UserRequest.perform(UserRequest.java:48)
  at hudson.remoting.Request$2.run(Request.java:328)
  at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72)
  at hudson.cli.CliManagerImpl$1.call(CliManagerImpl.java:63)
  at hudson.remoting.InterceptingExecutorService$2.call(InterceptingExecutorService.java:95)
  at jenkins.util.ContextResettingExecutorService$2.call(ContextResettingExecutorService.java:46)
  at java.util.concurrent.FutureTask.run(FutureTask.java:262)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
  at java.lang.Thread.run(Thread.java:745)

Solution: Jenkins server –> Manage Jenkins –> Configure Global Security to add related permissions.

References:

  1. http://www.blackpepper.co.uk/generating-new-jenkins-jobs-from-templates-and-parameterised-builds/
  2. http://javadoc.jenkins-ci.org/jenkins/model/Jenkins.html
  3. https://github.com/jenkinsci/jenkins

Written with StackEdit.

Playing With Git Submodule

enter image description here

Intructions:

  • add a submodule
1
2
$ git submodule add -b BRANCH ssh://REPO_URL/REPO_PATH SUBMODULE_PATH
$ git commit -m "add a submodule at SUBMODULE_PATH"
  • clone the project with submodule(s)
1
2
3
$ git clone ssh://REPO_URL/REPO_PATH PROJECT
cd PROJECT
$ git submodule update --init --rebase
  • get submodule status
1
2
$ git submodule status
$ git submodule foreach git branch -a
  • checkout all submodule to a branch defined in .gitmodule (which means we specify the branch when we add the submodule with ‘-b BRANCH’)
1
2
3
$ git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; git checkout $branch'
# OR a short version
$ git submodule foreach git checkout master
  • pull the latest master for all of the submodule
1
$ git submodule -q foreach git pull -q origin master
  • develop in submodule
1
2
3
4
5
# Make your changes in submoduleA
$ cd submoduleA
$ git add .
$ git commit -m "Updated the submoduleA"
$ git push origin BRANCH
  • sync to project
1
2
3
$ cd PROJECT
$ git pull
$ git submodule update --rebase
  • manually update the project to track submodule (Gerrit submodule description commit the track automatically)
1
2
3
4
$ cd PROJECT
$ git add submoduleA
$ git commit -m "Updated submodule a."
$ git push origin BRANCH_NAME
  • deinit, and remove a submodule
1
2
3
$ git submodule deinit SUBMODULE_PATH
$ git rm SUBMODULE_PATH
$ git commit -m "remove the submodule at SUBMODULE_PATH"

References:

  1. http://git-scm.com/docs/git-submodule
  2. http://git-scm.com/docs/git-rm.html
  3. http://stackoverflow.com/questions/8642668/how-to-make-submodule-with-detached-head-to-be-attached-to-actual-head
  4. http://www.vogella.com/tutorials/Git/article.html#submodules

Written with StackEdit.

Rename Repository on Gerrit

Gerrit icon

Instructions:

1. Move the repository folder on server:

1
2
3
# on gerrit server
$ cd $site_path/git;
$ mv old_name.git new_name.git

2. Flush the caches on server:

1
2
# On another client image:
$ ssh -p 29418 gerrit.server.com gerrit flush-caches

3. Run sql statement to update the changes:

1
2
3
4
5
6
7
8
# On another client image (need "Access Database" capability):
$ ssh -p 29418 gerrit.server.com gerrit gsql [Enter]
gerrit> USE {Database};
gerrit> SELECT * FROM changes WHERE dest_project_name = 'old_name';
# if have more than 1, run the following command to update, otherwise, quit with \q;
gerrit> UPDATE changes SET dest_project_name = 'new_name' WHERE
dest_project_name = 'old_name';
gerrit> \q

References:

  1. https://groups.google.com/forum/#!topic/repo-discuss/ltIxBipUPKI

Written with StackEdit.

Migrate Svn to Git

migrate svn to git

Instructions:

1. Check out the source tree from SVN server with svn command:

1
svn co http://my-project.googlecode.com/svn/trunk

2. Generate an users.txt with the command:

1
2
$ svn log ^/ --xml | grep -P "^<author" | sort -u | \
      perl -pe 's/<author>(.*?)<\/author>/$1 = /' > users.txt

and following the formatting:

1
2
schacon = Scott Chacon <schacon@geemail.com>
selse = Someo Nelse <selse@geemail.com>

NOTE: You can try the script to generate authors list automatically: https://gist.github.com/lifuzu/9081923#file-findauthors-sh

3. Once the users.txt is ready, then checkout the source tree again with the command ‘git svn clone’:

1
2
$ git svn clone http://my-project.googlecode.com/svn/ \
      --authors-file=users.txt --no-metadata -s my_project

4. To move the tags to be proper Git tags, run:

1
$ git for-each-ref refs/remotes/tags | cut -d / -f 4- | grep -v @ | while read tagname; do git tag "$tagname" "tags/$tagname"; git branch -r -d "tags/$tagname"; done

5. To move the rest of the references under refs/remotes to be local branches:

1
$ git for-each-ref refs/remotes | cut -d / -f 3- | grep -v @ | while read branchname; do git branch "$branchname" "refs/remotes/$branchname"; git branch -r -d "$branchname"; done

6. Adding the git server as a remote:

1
$ git remote add origin git@my-git-server:myrepository.git

7. Push all your branches and tags to go up:

1
2
$ git push origin --all
$ git push origin --tags

8. Update the changes from SVN (before you update, please cleanup your local workspace)

1
2
3
4
5
$ git svn fetch
...
r81152 = c2465633b56d16081334336ee87d506b97d10449 (refs/remotes/git-svn)
$ git checkout master
$ git merge remotes/git-svn

NOTE: Sometimes when you run git svn fetch:

1
2
...
r81217 = eb79c770f852f6158a583bb17a8c1a326f7b4e03 (refs/remotes/trunk)

Then you need to run:

1
2
$ git checkout master
$ git merge remotes/trunk

9. Then check them into GIT

1
2
$ git log # should have some changes merged from SVN
$ git push origin master

10. If you have a temporary migration branch you modified something on that, then you need rebase the changes on master to migration:

1
2
$ git checkout migration
$ git rebase master  # fix the conflicts if have

11. Finally, you need merge the changes on migration, fast forward, since you have rebased.

1
2
$ git checkout master
$ git merge migration

That is it!

Reference:

  1. http://git-scm.com/book/en/Git-and-Other-Systems-Migrating-to-Git
  2. http://git-scm.com/book/ch3-6.html
  3. http://stackoverflow.com/questions/16565991/keep-svn-repository-in-sync-with-git-one
  4. http://stackoverflow.com/questions/5241898/is-a-bidrectional-git-svn-sync-both-writable-possible

Written with StackEdit.

Raft - Distributed Consensus Protocol

Rafe is a distributed consensus protocol, which allows a collection of processes to maintain consistency even in the face of multiple node failure. The two main tenants of the protocol are leader election and log replication.

产品设计冲刺:为期五天的创业配方

原文地址:http://www.designstaff.org/articles/product-design-sprint-2012-10-02.html

在谷歌风险投资公司,我们每天都与创业公司做产品设计工作。由于我们行动迅速 ,他们也希望能迅速行动,我们优化了一些过程,可以让我们在五天以内见到良好的效果。我们把它叫做一个产品设计的冲刺,这个相当不错,它可以让你不再抓狂并加速已经进行中的项目。

我已经策划并运行了40几个这样的冲刺,先是在谷歌内部的团队,现在在谷歌风险投资公司投资的一些初创公司。给你一个直观的样子,这里是我们与CustomMade做了一个项目:

产品设计Sprint

原文地址:http://robots.thoughtbot.com/the-product-design-sprint

产品设计Sprint是一个5个阶段的演习,使用设计思维,减少内在风险,把产品成功推向市场。到目前为止,我们已经做了六大产品的设计Sprint,并使得他们成为我们咨询活动预设的一部分。

参加一个以设计Sprint为定向的团队,旨在努力达成明确清晰的目标。开始一个新的功能,工作流程,产品,业务或解决一个现有产品的问题,Sprint都是有用的出发点。

集设计Sprint和设计思想到我们的产品开发过程中,使我们与我们的目标保持一致,并帮助我们明智地投资我们的时间和金钱。

设计思想

设计思想结合换位思考,创造力和理性来解决以人为本的问题。它是设计Sprint建立的基础。

换位思考

有了设计思想,我们用换位思考的方法,通过我们客户的眼睛看世界,了解他们碰到的问题。这些问题可能涉及到技术,金融,政治,宗教,人,社会和文化等等。我们的工作就是要全面地理解这些问题,在一个更适用的环境下,开发出一套强化的、脉络清晰的架构。

除了从我们自己的角度,我们的目标是尽可能多地理解其他人的观点,以更好地使我们的理解多元化。

换位思考是第1阶段(理解)的首要重点和第5阶段(测试和学习)的主要部分。我们的目标应该是为人类解决问题和制造产品,要始终保持换位思考。

创造力

创意是机会的发现。我们运用创造力来产生洞察力和解决方案的概念。

最有创意的解决方案是由独到的见解和交叉的视角启发的。换位思考,如上所述,让我们具有理解不同的观点和更具创造性的能力。

合作激发创造力。更多的观点,想法和见解导致更多的机会。

创意是第2阶段(发散)的焦点,但存在于所有阶段(开发原型,测试/面试,研究/观察,创造实验等)

理性

我们使用理性,通过实验,测试和定性/定量的测量,以找到适应问题背景的解决方案。这是第3阶段(汇流)和第5阶段(测试和学习)的主要焦点。

设计思想也应该渗透我们所有的设计Sprint过程中,从工程设计到营销到业务发展。在复杂的商业生态系统中,设计思想可以作为一种全面的方法来促进和维护与客户的共生关系。

如何成为一个伟大的开发者

原文地址:https://the-pastry-box-project.net/ed-finkler/2014-january-6

  • 同理心是你最重要的技能。把它应用在和你接触、或者和你的工作接触的每一个人身上。

  • 谦卑与同理心携手并进。对你可能是错误的,保持开放的心态(甚至只是似然可能)。要知道,你将永远保持学习和提高。接受并立刻修改错误。

  • 你越少怕做错,你越有信心。很多事情你都会错。你很少知道大多数的事情。其他人和你完全一样。拥抱它。不断学习,总是质疑,不断适应和成长。

  • 知道你能做好什么,做不好什么。

  • 如果你有一份喜欢的工作,而且收入不错,要懂得幸运。我们生活的这个时期,对开发者的需求超过了供给。不是所有人都这么幸运。

  • 拒绝参与团伙。我们是社会性的动物,作为一个群组的一部分给了我们信心,但技术选择的战争会分散我们信心,让我们不能良好的工作和锻炼同理心。建立与我们有共同点的社区,拥抱让我们每个人有特点的多样性。使那些有兴趣参与的人感到安全、舒适。

  • 使用你的技能,让人们的生活更好。

  • 不要担心有多少人使用你做的东西。能帮助5个人都是令人难以置信。他们会记住你为他们做了什么。

  • 让你周围的社区更好。你不需要去一些科技天才的魔术城去找重要的工作去做。你在哪里不要紧 – 重要的是你要在你生活的周围作出不同。现在是互联网,所以“在你身边”的人可能是在世界的另一边。

  • 与你周围的人分享你学到的东西。请他们和你分享他们所学到的。

  • 您选择技术和工艺,仅此而已,别人关心你做给他们的东西。作为一个音乐家,我看到很多人有很好的工具、喜欢争论设备,但很少人能完成一首歌曲。

  • 极度怀疑地检视绝对声明。

  • 如果没有健全的、合理的说法,放弃一项技术是懒惰的,而且容易出错。

  • 要很小心参与X与Y的论战。他们很少值得你花时间。

  • 学习新的技术和方法,要放轻松。保守地使用它们。

  • 每星期拨出一点时间来了解新技术。甚至只是订阅每周聚集的通讯(如每周的(PHP|Python|JavaScript|等))可以引发对很酷的新事物的探索。

  • 如果你去参加会议(你应该如果可以的话),尽量参加一两次你完全没有经验的技术会谈。找些你从来没有学过的一门语言,或者你完全没有经验的平台的初学者/介绍级演讲。即使你从来没有在生产中使用它,接触到不同的方法和技巧将使你成为一个更好的开发者。

  • 任何技术都可以是正确的选择,这取决于项目的需求和团队的优势。

  • 永远不要假设你知道做决定的原因,除非做这个决定的时候你在房间里。

  • 始终牢记两组人:用户和你的团队的其他成员。他们是受你做出的决定影响的人。

  • 沟通不畅会扼杀最有天赋的球队的效率。在有效的、结构化的沟通和文档下功夫。

  • 对大家保持忠诚。不是品牌,不是公司,也不是技术。

Written with StackEdit.