2014年8月27日 星期三

使用git bisect 搜尋災難發生點

之前因為強者我同學阿蹦大神的關係,接觸了neovim這個大型專案,光星星數就有9300多顆,是我星星最多的project的9300多倍lol。
雖然說看了幾個issue,大部分都插不上話--討論的層次太高了,偶爾有個好像比較看得懂的,trace下去之後提出解法,沒想到是個不徹底的解法,pull request就被拒絕了TAT,要參加這個超過9000顆星星的project,像我這種花盆果然還是「垃圾請再加油」

--

雖然說是這樣,但我還是趁這個機會,研究一下如何使用git bisect 在project裡面找到洞洞。
基本上project無論用了多少test,多少還是跟我的腦袋一樣有一些洞,要如何找到洞洞就是一門學問了,git 提供了git bisect這個指令幫助開發者找到出錯的地方

我們用一個比較小的project: pyquery來實驗這個功能,這是強者我同學JJL大神參與的專案

https://github.com/gawel/pyquery

我們trace 一下issue 74: Behavior of PyQuery...
因為這個issue 發生在v1.2.4,但到了v1.2.9已經消失了,那我想知道這從哪裡發生的(這種狀況比較少見,一般都是有錯要找哪裡出錯了),就用bisect 來找吧。

首先是bisect 的基本設定,我們要先啟動bisect,然後指定一個good commit 跟一個bad commit,而bad commit 在歷史上要比good commit 來得晚,bisect 會從bad commit 一路回溯到good commit 為止。通常可以透過checkout tag的方式作大範圍的搜尋,以免bisect檢查太多commit,在這個例子中,我們發現v1.2.8->v1.2.9的過程中這個bug 被修掉了。

因此我們設定:
$ git bisect start
$ git bisect bad 1.2.9
$ git bisect good 1.2.8
Bisecting: 11 revisions left to test after this (roughly 4 steps)
[bc1b16509cec70de7a32354026443fca777f4d7d] created a .gitignore file(which is almost a copy of .hgignore with some minor changes and comments)

這時候我們已經進入bisect 狀態,用git branch的話會看到現在是(no branch)狀態。
要說明一下這裡的good, bad只是bisect上的一個概念,它會從bad 開始找到good,至於裡面是不是真的 good/bad,這由開發者決定。
這時bisect會checkout 處在good/bad 中間位置的版本,我們執行事先寫好的一個測試檔test.py,它會自動測試這個issue的狀態

from pyquery import PyQuery as pq
x = pq("<div></div>")
y = pq("<div><table></table></div>")
print(x.is_("table"))
print(y.is_("table"))

執行發現它還是回傳False/False,因此我們輸入
$ git bisect bad
Bisecting: 5 revisions left to test after this (roughly 3 steps)
[b81a9e8a2b0d48ec0c64d6de14293dd4a680a20b] fixed issue #9

bisect 會以binary search的方式checkout 一個更舊的版本,然後你再測試一次。
經過五次的bad/good的測試結果,bisect回傳:
300cd0822505a4bd308acd1520ff3ef0f20f8635 is the first bad commit
commit 300cd0822505a4bd308acd1520ff3ef0f20f8635
Author: Gael Pasgrimaud <gael@gawel.org>
Date: Fri Jan 3 10:35:30 2014 +0100

fixed issue #19

:040000 040000 1d9cb3b170a8fdb2846e3c0e0fb6d2be9a9538d5 07d3a40ff73dda078d7543be2fab2f9f927b0c1f M pyquery

這樣就抓到這個 fixed issue #19 的commit 就是修好這個issue 的commit 了,最後要用
$ git bisect reset
結束bisect狀態。

--

上面這個方法好像還是不夠方便,理論上bisect 支援git bisect run這個方法,可以送一個script 給它,它會自動執行,並以回傳值0表示這個commit 是good,回傳值1表示這個commit 是bad,回傳值125表示這個commit 要skip掉。
所以我改了上面這個script 為:
import sys
from pyquery import PyQuery as pq
x = pq("<div></div>")
y = pq("<div><table></table></div>")
if x.is_("table") == False and y.is_("table") == False:
    sys.exit(1)
else:
    sys.exit(0)
可是不知道為啥,bisect run ./test.py的結果,每個commit 都會是bad的輸出…這真的是太奇怪了,我猜有可能會是git bisect的問題也說不定,有空再來詳加研究。

--

8/28增補:

後來經過阿蹦大神的指出,問題可能是出在*.pyc上面,因為python要是看到現在的pyc跟現在的時間相同,就不會更新pyc而是直接跑pyc。
git bisect run會極速的checkout 舊分枝,跑python script,看結果跑下一步;而pyc的檢定大概是用秒在算的,就變成python並沒有更新pyc檔,反而是用pyc跑出同樣的結果,bisect 自然出錯了。
解決方法有兩個,第一個是寫一個shell script test.sh,先刪掉所有pyc檔之後,再執行python script:
find . -name “*.pyc” -exec rm {} \;
./test.py
然後用git bisect run ./test.sh
第二個是讓python script 跑慢一點,讓python能察覺到python 的版本變化:
import time
time.sleep(1)
第三個應該才是根本的解法:
在python 的shebang上面加上 -B的參數就好了
執行結果就跟手動的一樣了,去你的pyc。

結論:

bisect很好用?不是,我認為從這個案例中最重要的概念,其實是自動測試的重要性,如果程式能保持一個自動測試的script,在除錯上可以透過script 自動找到錯誤點,不需要人工手動介入,試想若每個commit都需要手動10步驟的測試,兩個版本間有10個commit ,測試步驟立刻變成100步,但用script只要一個指令就能知道是好是壞,搭配bisect才能事半功倍。

參考資料:


Git-bisect doc: http://git-scm.com/docs/git-bisect

2014年8月22日 星期五

Git-flow 簡介

最近因為工作的關係接觸了git-flow相關的內容,在這裡就介紹一下git-flow的相關概念。基本上git-flow就是一個git 的擴展,把一群git 指令集合在一起,更方便管理人的操控,如果去看它的執行檔,其實就是一個shell script,所以使用git-flow時也可以用git 指令,同時只要熟練git的話,就算不用git-flow 也能操作自如。

我認為git-flow最重要的還是背後那個分枝的規則,我覺得學起這個規則就好,我們就先討論它設計的理由,同時搭配相關的git 指令:

git-flow會有五個主要的branch: master, develop, feature, release, hotfix,以下一一介紹:

有master branch是當然的,master branch是要讓使用者使用的,使用者checkout project時就要看到的內容,master branch上的commit 應該加上tag表示軟體的版本。
$ git tag -a v0.1 -m 'message here'

因為是要讓使用者用的,所以平時自然不能隨便在master 上面修修改改,開發者要先換個 develop branch上面進行開發。
$ git checkout -b develop
or
$ git branch develop && git checkout develop

git 允許許多開發者一同開發這個project ,如果大家都一股腦往develop 上放東西,每個開發者都會被commit 時的衝突問題煩到死,因此要開發一個新的feature,就要新建一個feature 分枝。
開發完時,這個分枝再併回develop 上:
$ git checkout -b feature-issue42
git commits
$ git checkout develop && git merge –no-ff feature-issue42
這個部分應該是最花時間的,通常會遇到共同開發的pull/push也是在這個部分,這裡不贅述,就請參考之前的文章:

軟體開發到一個程度,就進入release 流程,從develop 切換到release中,停止新增feature,開始專注在修bug 跟改文件等等工作上,準備就緒後,就外送到master 跟送回develop 中。
$ git checkout develop && git checkout -b release
git commits (only bugs)
$ git checkout master && git merge --no-ff release
$ git tag add -v0.2 -m 'message here'
$ git checkout develop && git merge --no-ff release

最後,沒有軟體是沒問題的,如果master上被檢出需要立即修補的重大問題,這時就要動用hotfix,把master 分枝出hotfix branch,修完後再併入master 和develop中。
$ git checkout master
$ git checkout -b hotfix
fix bugs, commit
$ git checkout master && git merge --no-ff hotfix
$ git tag -a 0.2.1 -m 'message here'
$ git checkout develop && git merge --no-ff hotfix
$ git branch -d hotfix

在文中的merge 指令都有使用 no fast-forwarding的--no-ff 指令,這是為了保留一個分枝跟合併的 記錄,以免fast-forwarding造成所有branch全混成一條。
當然這個流程只是參考,事實上接觸的幾個project幾乎都沒有照這個流程,大部分都是把master當成文中的develop在用,一樣分出feature來開發但沒有release,然後hotfix branch就是用master一路往前修。

所以說,感謝大家花了幾分鐘看了這篇廢文XDD

2014年8月17日 星期日

我與HDE

故事要從五月開始說起,那時候參加了pycon Taipei 2014,看著台上眾多大神的報告,覺得自己真是一個花盆。不過,在進場的小袋子裡,除了會議時程表外,還有一些其他的東西,像是可愛的github小貼紙,另外還有一些求職傳單。

其中,就有我將要開始實習的HDE。

--

回來的時候也沒想這麼多,雖然平時我都有寫一些程式,但是我研究所念的東西跟軟體還是想差太遠,如果畢業之後要進到軟體業的話,還是需要一些實戰經驗,我定下兩個方向,一個是參與free software的開發,另一個就是參與實習。
那時候大概把找得到的暑期實習機會都投過了,很幸運的,HDE竟然回應我的申請。

第一階段是直接考程式,第一題要寫一個簡單的數字處理程式,可以用python,Erlang,C++,Ruby之類的。
個人是覺得還滿簡單的,用python解決輕鬆寫意( ̄▽ ̄)-|_
第二題比較機車,跟網路有關,要用python的httplibs去解,這時候就要瘋狂查網路資料lol,我懷疑如果是當面考的話我應該寫不出來,拜google大神才順利寫出來,實在有夠廢。

--

後來通知Skype面試,人生第一次Skype面試呀
結果對方打電話過來,我的Skype就當機了= =,莫名奇妙,「你爸沒教過你不要在人家第一次面試這樣搞嗎?」 
面試是用英文(如果是日文的話我大概會直接GG)記了一些問的問題,僅列如下,順便附自己的回答:
*請簡介一下你自己?
A喔這好像是萬年老梗了,結果我還是答得亂七八槽(T_T)

*可以說明一下你有什麼experience跟internship?
A恁北網管這樣算嗎?

*請說明一下你的生涯規劃,有想要在哪裡工作嗎?台灣、日本、韓國、Bay Area…
A吾乃魯蛇,不要求什麼國家,只要能有工作,然後能有時間持續充電,我就不排斥
(是說這樣是不是刪掉不少台灣公司…?不過我真的認為持續充電很重要呀)

*請說明你這個人有什麼優勢?
A本回答已被QClean屏蔽

*請說明你這個人有什麼劣勢?
A本回答已被QClean屏蔽

*請說明你未來職場上的規劃?我看你大學是念微波的,未來呢?
A我認為這算我的劣勢之一,未來想走軟體路線可是念的是硬體
所以目前我努力找軟體Intern,參與free software project,就是要證明我有軟體能力…

*本問題已被QClean屏蔽
A滿新奇的呃啊哈哈,我還有借機車來環島啊哈哈,還要適應各種交通狀況

*所以你會說日文嗎?
A一點點吧,讀跟聽比較沒問題,寫跟說就會GG

--

另一個面試官

*我們來點技術性的,首先看到你mission 1,你用python寫的,可否說明
A嗯,題目要求可以用C, Erlang, Go, Python, Ruby,其中我會C跟python
我選Python,因為……因為寫起來比較快嘛(生命苦短,珍惜生命,請用python =w=)。

*請問你大概花了多久?
A約30分吧我猜…

*那如果用C來寫呢?追問:那C++呢?
A我想都可以的,我應該會一點C++
按:老實說這裡我忘了跟他們確認是第一題或第二題了,要是是第二題的話我大概不會QAQ。

*請問你有寫過網頁App或是網頁service嗎?
A沒有TAT

*那請問有自架網站過嗎?
A我曾經用php mySQL架過一個測試用留言版,跟個人網頁,不過只能從自己電腦連線
如果要夠安全,能夠公開,大概有點難度

*現在要你架一個網站server,你要多久
A幾小時吧,要完全的安全大概要更久

*請問你熟Configuration Management or Continuous Integration
A我目前參與的github project有使用Travis CI,不過我本身是沒用過啦(yay)

--
我們的問題到這邊,請問你有什麼問題?
Q2:本問題已被QClean屏蔽。
本回答已被QClean屏蔽

Q1:請問本司預計招多少個Intern呢?(這類問題好像是禁忌?)
本回答已被QClean屏蔽

公司的地址在渋谷。
BGM: Welcome to Tokyo:
住處的話公司推薦我去找Sakura house,專給外國人在日本的短期住宿,後來找到的房子在代代木公園(yoyogi Koen),跟渋谷、原宿大概成一個正三角形,經過代代木八幡站後面就是代代木公園跟明治神宮,晚上可以出去慢跑一圈,感覺挺好的。

HDE Intern的規定是每月有150000 JPY的薪水生活補助,另加保險與來回機票,這1.5勝文150K JPY……呃……它是寫「這不是薪水,而是生活費的補助」網頁的解釋是說:
...not for work (because the program are not for work, to comply with the visa regulation) but for your living costs (food/ traveling expenses/ apartment).
在沖繩留學的同學也解釋,這是因為「日本規定沒有勞簽證,不能拿正當的薪水」,至於當中有什麼差異,也許我再跟他們請教
啊老實說我是感覺很有趣,廣義上來說這就是薪水呀,它這樣講就感覺就是給了錢然後說:「這……這才不是給你的薪水呢≥ ≤。」什麼奇怪的傲嬌XD

--

然後我訂機票又訂到華航松山-羽田的機票,比起桃園-成田的機票…呃…貴了3K,這我得辯解一下,買華航是因為他的飛行時間比較正常,中午就可以到東京,這樣下午才有時間辦入住;然後看google map羽田比成田離東京比較近嘛,誰想得到一個城市兩個機場,一個機場比另一個機場貴3K啦(╯-_-)╯ ~╩╩

人生第一次坑人錢就坑3K,我真的不是故意的啊O_O

--

另外,因為「Yoda言論自我審查」的關係,與HDE相關的內容在我的Facebook上會儘量屏蔽,畢竟在下也是位延畢生,之前同學口試通過啦、出國去conference啦、各種畢業證書照啦、出國去大學課程或是不然就各種去玩啦,深知一群人用「過得很爽的感覺」的內容洗別人版,叫我這種花盆情何以堪,因此Facebook上將進行言論管制。

事實上有關實習之前都是列機密,知道的應該在五十人左右。

至於是在東京,知道的人數,嗯,大概是十來位吧,感謝大家幫我守住祕密,沒有四處聲張,至於我幹嘛不說在東京……因為……因為你們沒問啊 /人◕ ‿‿ ◕人\,而且我其實有說我在東京吼,你看我有發一則'welcome to Tokyo'的連結(炸)。

我記得暑假初期有一本書,是講當社群網路跟鄉民文化發展到極致時,世界上會出現多麼光怪陸離的事情,女主角一開始不願意在社群網路上分享東西,於是有了這段對話:

「這是一位臥病在床的小孩,她也許想看到妳看到的美麗海面和滿天星斗,妳不分享你看到的,等於是在傷害她們,剝奪她們看到這樣風景的權利。」還有一段總結是:
「祕密即是謊言;分享即是關懷;隱私即是偷竊」
嗯這個,請大家不要讓世界變成那樣,有事不發到Facebook好像變罪過一樣;請大家將花盆比花盆,營造低調Facebook環境。

--

同時話說回來,我也不覺得在日本工作算是什麼值得炫耀的事情,強者我同學要不是好幾年前的暑假,當花盆我還在各種耍廢的時候,就開始各種像101、日月神教、法國實驗室的實習了,現在還有同學直接在灣區工作,花盆現在才在人生第一次實習,差這幾年的時間根本悲劇,老早就看不見大家的車尾燈了。

總之,實習正式展開,希望花盆能活過這一關。

相關連結:

1.HDEwebsite:
HDE.co.jp
2.HDE Intern website:
http://www.hde.co.jp/gip/
3.SakuraHouse:
http://www.sakura-house.com/

2014年8月7日 星期四

使用sed取代ADS檔案路徑

最近實驗室正在畢業潮(已羨慕),學長們約定俗成要把自己的設計燒成一片光碟傳給學弟……喔或是學妹。
一般習慣不好的話,在ADS 的設計檔裡,會包含很多絕對路徑的內容,這樣這個設計project就變得難以移植。
以我隔壁超強的同學「瓦哥」為例,過去的電磁模擬記錄會這樣寫
D:\Program Files (x86)\Sonnet\0.18um_m\transformer\PA\sonnet\Stack_PA\XXX.snp
移到別的電腦就找不到這些電磁模擬檔。

比較好的做法是把電磁模擬放到ADS的project資料夾內,例如新建一個EM的資料夾,然後用相對路徑去存取:
EM\Stack_PA\XXX.snp
就能確保模擬檔的可移動性。

那如果已經做完了,難道要一個一個改嗎?
ADS的設計是記錄在dsn文字檔裡面,這類文字檔的操作其實也很簡單,在ADS project的networks資料夾,改掉dsn裡面的檔案即可:
用sed 一行解決,加上for loop 輕鬆寫意,就跟喝水一樣輕鬆:

for i in *.dsn; do sed -i 's/XXX/yyy/g' $i; done

缺點:Unix 限定……,windows我還真想不出解法,可能要用python, mingw,不然powershell可能有類似的功能?
當然要一個檔案一個檔案打開來改也不是不行,只是很不smart就是。

2014年8月1日 星期五

無意間做了不得了的事呢

7/31晚上本來還在練日文聽力,卻瞄到FB(謎:練聽力不專心,拖出去砍了)一兩位高雄的朋友在貼出家門口發生爆炸、或是聽到巨大爆炸響聲的消息,照片跟影片有點猛,根本就是watch dog實況飛機轟炸了。
後來幾條即時新聞貼出來,看到一兩個爆炸點離我家好近,發條簡訊回家問候,沒想到家人回電說離家不到50公尺的馬路整個爆炸,現在家裡都是瓦斯味,整條街的人都疏散到附近的學校操場了。

從這時開始追蹤BBS上面的消息,發現爆炸範圍大得誇張,一堆路口都有爆炸的消息,一開始消息很亂還一度有新聞說前金區都有爆炸(後來更正是感覺得到震動)

後來發現沒人好好整理一個爆炸點圖,只看文字實在不知道哪裡發生事情,經過好友qcl大神的指點,用了google map engine,憑著新聞上的路口報導,網友提供的圖片影片,對照自己生活18年記下來的腦中地圖,大略畫了一張高雄的救災地圖:

後來在Facebook和BBS上被廣泛轉貼,大概是我做過最多人看的東西(我猜應該是用萬當單位的吧),一度流量大到我自己都不能編輯,今天新聞網頁也都有放地圖的連結。
不可否認做地圖滿累的,要不斷掃視即時新聞跟BBS的發文,判讀照片、影片的位置,救災單位的消息出來也要更新上去,後來3點多看事件差不多平息了才上床睡覺。

一天一夜的驚濤駭浪,要感謝強者我同學qcl,寄信跟丟水球提醒資訊更新的網友,整理住宿地圖資訊的網友;最後還要感謝提供平台的google map ,據說還引起google內部工程師的注意,把地圖的流量上限往上調,這個即時調動頻寬的能力真是世界一流啊OAO

結語,該怎麼說呢?
很有幸我們生在這個時代,網路讓每個人都有機會對資訊貢獻一點心力,而正如上一篇對Uber的評論:
「資訊有效的傳遞,是很值錢,甚至攸關性命的」
但網路再有效也有它的極限,現在市府已經進場救災,更有效的指揮體系已經建起來了,這張地圖也差不多可以功成身退了;進一步的原因追蹤不是坐在電腦前抓得出來的,但有幸能宅在學校,對家鄉提供一些心力,個人表示十分榮幸,做了一個大家都在看的地圖,大概就跟「qcl誠徵女友」
http://qcl.github.io/qclwgf.html
一樣,無意間做了一件了不得的事,我自己也滿驚訝的。

ps: 要是我寫的code也有這麼多人看就好了(炸)