예제 #1
0
파일: builder.cs 프로젝트: atsushieno/drosh
 public static void ProcessBuild(BuildRecord build)
 {
     if (build == null)
         throw new ArgumentNullException ("build");
     build.Status = BuildStatus.Ongoing;
     build.BuildStartedTimestamp = DateTime.Now;
     DataStore.UpdateBuildRecord (build);
     try {
         ProcessBuildCore (build);
     } catch (Exception ex) {
         build.Status = BuildStatus.Failure;
         DataStore.UpdateBuildRecord (build);
         throw;
     }
 }
예제 #2
0
파일: builder.cs 프로젝트: atsushieno/drosh
        public static List<string> QueueBuild(ProjectRevision rev, UserReference user)
        {
            if (rev == null)
                throw new ArgumentNullException ("rev");

            List<string> newIds = new List<string> ();
            var project = DataStore.GetProjectWithRevision (rev.ProjectOwner, rev.ProjectName, rev.RevisionId);
            if (project == null)
                throw new Exception (String.Format ("Project {0}/{1} for ProjectRevision {2} was not found", rev.ProjectOwner, rev.ProjectName, rev.RevisionId));
            if (project.Owner != user && !project.Builders.Contains (user))
                throw new Exception (String.Format ("User {0} is not granted to build this project", user));

            foreach (var ndkType in target_ndks) {
                if ((project.TargetNDKs & ndkType) == 0)
                    continue;
                foreach (var archType in target_archs) {
                    if ((project.TargetArchs & archType) == 0)
                        continue;

                    var newId = Guid.NewGuid ().ToString ();
                    newIds.Add (newId);
                    var build = new BuildRecord () {
                        BuildId = newId,
                        ProjectOwner = rev.ProjectOwner,
                        ProjectName = rev.ProjectName,
                        ProjectRevision = rev.RevisionId,
                        TargetArch = archType,
                        Builder = user,
                        Status = BuildStatus.Queued,
                        };

                    build.BuildRecordedTimestamp = DateTime.Now;
                    DataStore.RegisterBuildRecord (build);
                }
            }
            return newIds;
        }
예제 #3
0
파일: builder.cs 프로젝트: atsushieno/drosh
        static void ProcessBuildCore(BuildRecord build)
        {
            var project = DataStore.GetProjectWithRevision (build.ProjectOwner, build.ProjectName, build.ProjectRevision);
            if (project == null)
                throw new Exception ("Project was not found");

            // Create a build directory
            string buildDir = Path.Combine (Drosh.BuildTopdir, build.BuildId);
            string resultDir = Path.Combine (buildDir, "build");
            string depsDir = Path.Combine (buildDir, "deps");
            string buildSrcDir = Path.Combine (buildDir, "src");
            /*
            Directory.CreateDirectory (buildDir);
            Directory.CreateDirectory (resultDir);
            Directory.CreateDirectory (depsDir);
            Directory.CreateDirectory (buildSrcDir);
            */
            // pull source and deps

            if (project.Dependencies != null) {
                foreach (var dep in project.Dependencies) {
                    // user/projectname or projectId
                    var dp = dep.Contains ('/') ? DataStore.GetProject (dep.Substring (0, dep.IndexOf ('/')), dep.Substring (dep.IndexOf ('/') + 1)) : DataStore.GetProject (dep);
                    var b = DataStore.GetLatestBuild (dp, build.TargetArch);
                    if (b == null)
                        throw new Exception (String.Format ("Dependency project {0}/{1} has no successful result for {2} yet", dp.Owner, dp.Name, build.TargetArch));
                    var deppath = Path.Combine (Drosh.DownloadTopdir, b.LocalResultArchive);
                    Unpack (deppath, depsDir);
                }
            }

            string path = Path.Combine (Drosh.DownloadTopdir, "user", build.ProjectOwner, project.LocalArchiveName);
            string srcCopied = Path.Combine (buildSrcDir, Path.GetFileName (path));
            File.Copy (path, srcCopied);
            Unpack (srcCopied, buildSrcDir);
            var dirs = Directory.GetDirectories (buildSrcDir);
            string actualSrcDir = dirs.Length == 1 ? dirs [0] : buildSrcDir;

            foreach (var patch in from p in project.Patches select p) {
                var patchFile = Path.Combine (actualSrcDir, String.Format ("__drosh_patch_{0}_{1}.patch", project.TargetNDKs, build.TargetArch));
                using (var fs = File.CreateText (patchFile))
                    fs.Write (patch.Text);
                var psi = new ProcessStartInfo () { FileName = "patch", Arguments = String.Format ("-p{0} -i \"{1}\"", patch.Text.StartsWith ("diff --git") ? 1 : 0, patchFile), WorkingDirectory = actualSrcDir };
                var proc = Process.Start (psi);
                if (!proc.WaitForExit (10000)) {
                    proc.Kill ();
                    throw new Exception ("Forcibly terminated patch.");
                }
            }

            // Go to srcdir and start build

            foreach (var buildStep in build_steps) {
                var scriptObj = project.Scripts.FirstOrDefault (s => s.Step == buildStep);
                string script = scriptObj != null ? scriptObj.Text : null;
                script = script != null ? script.Trim () : null;
                script = String.IsNullOrEmpty (script) ? GetDefaultScript (project.BuildType, buildStep, project.TargetNDKs) : script;

                string scriptFile = Path.Combine (actualSrcDir, String.Format ("__build_command_{0}.sh", buildStep));
                using (var fs = File.CreateText (scriptFile))
                    fs.WriteLine (script);
                var psi = new ProcessStartInfo () { FileName = "bash", Arguments = scriptFile, WorkingDirectory = actualSrcDir, UseShellExecute = false };
                psi.EnvironmentVariables.Add ("ANDROID_NDK_ROOT", Drosh.GetAndroidRoot (project.TargetNDKs));
                psi.EnvironmentVariables.Add ("DEPS_TOPDIR", depsDir);
                psi.EnvironmentVariables.Add ("RESULT_TOPDIR", resultDir);
                psi.EnvironmentVariables.Add ("RUNNER_DIR", Drosh.ToolDir);
                var proc = Process.Start (psi);
                if (!proc.WaitForExit (1000 * 60 * 10)) {
                    proc.Kill ();
                    throw new Exception (String.Format ("Forcibly terminated build step: {0}", buildStep));
                }
                if (proc.ExitCode != 0)
                    throw new Exception (String.Format ("Process error at build step: {0} with exit code {1}", buildStep, proc.ExitCode));
            }

            // Now that build and install is done successfully, pack the results into an archive.

            // FIXME: handle filesbypkg

            string destArc = Path.Combine (buildDir, build.ProjectName + "-bin.tar.bz2");
            string files = String.Join (" ", from fsi in new DirectoryInfo (resultDir).GetFileSystemInfos () select "\"" + fsi.Name + "\"");
            var pkpsi = new ProcessStartInfo () { FileName = "tar", Arguments = String.Format ("jcf {0} {1}", destArc, files), WorkingDirectory = resultDir };
            var pkproc = Process.Start (pkpsi);
            if (!pkproc.WaitForExit (10000)) {
                pkproc.Kill ();
                throw new Exception (String.Format ("Forcibly terminated packing step."));
            }
            string dlname = Path.Combine ("user", project.Owner, Guid.NewGuid () + "_" + Path.GetFileName (destArc));
            File.Move (destArc, Path.Combine (Drosh.DownloadTopdir, dlname));
            build.PublicResultArchive = Path.GetFileName (destArc);
            build.LocalResultArchive = dlname;
            build.Status = BuildStatus.Success;
            build.BuildFinishedTimestamp = DateTime.Now;
            DataStore.UpdateBuildRecord (build);
        }