DevOps(4)Build RPM for CentOS
1. On CentOS
Install the RPM build ENV
>sudo yum install rpm-build
>sudo yum install gcc
>sudo yum install rpmdevtools
>sudo yum install rpmlint
2. On Ubuntu
>sudo apt-get install lintian
>sudo apt-get install fakeroot
>sudo apt-get install rpm
Error Message:
rpm:packageBin) java.io.IOException: Cannot run program "rpmbuild"
Solution:
Install the RPM build ENV
>sudo yum install rpm-build
>sudo yum install gcc
>sudo yum install rpmdevtools
>sudo yum install rpmlint
Error Message:
(localpoint-bridge-api-rpm/rpm:publish) java.io.IOException: destination file exists and overwrite == false
Solution:
I change the file
>vi ~/.sbt/repositories
[ivy] sbt.override.build.repos=true
But it does not work. I will check the artifactory side.
Error Message:
debian:genChanges) Cannot generate .changes file without a changelog
Solution:
Place a file changelog.txt in the project place will help.
Publish the RPM Build
>;project projectname; clean; project projectname-rpm; clean; rpm:publish
Package the PRM Build
>;project projectname; clean; project projectname-rpm; clean; rpm:packageBin
Package the Debian Build
>;project projectname; clean; project projectname-rpm; clean; debian:packageBin
3. Some Configuration in the Project Directory
I just do not plan to spend a lot of time on this right now. So I will just log the conf here.
build.properties
// 0.13.2 defaults to publishing ivy artifacts with overwrite = false, which we don't want to deal with yet
sbt.version=0.13.6
Build.scala
import sbt._
import Keys._
import com.typesafe.sbt.packager.Keys._
import scalariform.formatter.preferences._
import com.typesafe.sbt.SbtScalariform._
import spray.revolver.RevolverPlugin._
import org.sbtidea.SbtIdeaPlugin._
object ApplicationBuild extends Build {
lazy val ourVersion = Process("git describe --match=[^(jenkins)].* --always --long").lines.head
val akkaVersion = "2.2.0-RC1"
val sprayVersion = "1.2-M8"
val publishEnv = SettingKey[String]("publishEnv","artifact environment to publish to")
override lazy val settings: Seq[Project.Setting[_]] =
super.settings ++ Seq(
scalaVersion := "2.10.3",
version := ourVersion,
organization := "com.sillycat",
resolvers := Seq(),
externalResolvers := Seq(
Resolver.defaultLocal,
“sillycat Artifactory" at "http://repository.sillycat.com/artifactory/remote-repos"
),
credentials += Credentials("Artifactory Realm", "repository.sillycat.com", "builder", “sillycat2011!"),
publishTo := Some(“sillycat Artifactory Dev" at "http://repository.sillycat.com/artifactory/sillycat-dev/")
)
lazy val all = Project(id = "all",
base = file(".")).
aggregate(
main,
gerd,
auth,
util,
localpointBridgeApi,
migration,
messageQueue,
profilesSpark,
localpointAuthCenter
)
/**
Several projects have 2 ids, e.g. foo and foo-rpm
The 1st is for ease of development, so that changes to guts are recognized without publishing.
It depends on main, which will put guts on the classpath before libraryDependencies.
The 2nd is specifically for building the rpm, and uses the same sourcetree as the project above.
It doesnt use dependsOn; the guts jar is included from libraryDependencies,
so guts must be published before the rpm can be built.
*/
lazy val main = Project(id = "guts",
base = file("guts")).
dependsOn(util).
settings(scalariformSettings ++ Revolver.settings ++ Seq(
name := "guts",
scalacOptions := Seq("-unchecked", "-deprecation", "-feature", "-encoding", "utf8"),
publishEnv := "develop",
libraryDependencies ++= Seq(
// do not upgrade mysql connector, 5.1.27 broke hibernate
"mysql" % "mysql-connector-java" % "5.1.26",
"org.apache.cassandra" % "cassandra-all" % "1.2.8",
"com.datastax.cassandra" % "cassandra-driver-core" % "1.0.3",
//https://github.com/jorgeortiz85/scala-time
"org.scalaj" % "scalaj-time_2.10.0-M7" % "0.6",
"com.typesafe.slick" %% "slick" % "1.0.1",
"com.typesafe.slick" %% "slick-testkit" % "1.0.1" % "test",
"com.typesafe" % "config" % "1.0.0",
"org.scalatest" % "scalatest_2.10" % "1.9.1",
"io.spray" % "spray-json_2.10" % "1.2.3",
"c3p0" % "c3p0" % "0.9.1.2",
"com.typesafe" %% "scalalogging-slf4j" % "1.0.1",
"com.esotericsoftware.kryo" % "kryo" % "2.21",
"org.bouncycastle" % "bcprov-jdk16" % "1.46",
"org.jasypt" % "jasypt" % "1.9.0",
"com.google.guava" % "guava-parent" % "14.0.1",
// this is needed for guava
"com.google.code.findbugs" % "jsr305" % "2.0.1",
"redis.clients" % "jedis" % "2.0.0",
"org.apache.kafka" % "kafka_2.10" % "0.8.0",
"org.msgpack" %% "msgpack-scala" % "0.6.8",
"com.googlecode.flyway" % "flyway-core" % "2.2.1"
),
fork := true,
publishArtifact in Test := true,
publishTo <<= publishEnv { (p: String) =>
if(p == "master")
Some(“sillycat Artifactory master" at "http://repository.sillycat.com/artifactory/sillycat-master")
else if(p == "feature")
Some(“sillycat Artifactory feature" at "http://repository.sillycat.com/artifactory/sillycat-feature")
else if(p == "release")
Some(“sillycat Artifactory release" at "http://repository.sillycat.com/artifactory/sillycat-release")
else if(p == "maven")
Some(Resolver.file("file", new File(Path.userHome.absolutePath+"/.m2/repository")))
else
Some(“sillycat Artifactory dev" at "http://repository.sillycat.com/artifactory/sillycat-dev")
}
): _*)
lazy val auth = Project(id = "localpoint-auth",
base = file("localpoint-auth")).
dependsOn(main % "test->test;compile->compile").
dependsOn(util).
settings(scalariformSettings ++ Revolver.settings ++ Seq(
name := "localpoint-auth",
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8"),
libraryDependencies ++= Seq(
"io.spray" % "spray-can" % sprayVersion,
"io.spray" % "spray-routing" % sprayVersion,
"io.spray" % "spray-testkit" % sprayVersion,
"io.spray" % "spray-caching" % sprayVersion,
"io.spray" % "spray-client" % sprayVersion,
"com.typesafe.akka" %% "akka-actor" % akkaVersion,
"com.typesafe.akka" %% "akka-testkit" % akkaVersion,
"com.typesafe.akka" %% "akka-transactor" % akkaVersion
),
fork := true
): _*)
lazy val util = Project(id = "localpoint-auth-util",
base = file("localpoint-auth-util")).
settings(
autoScalaLibrary := false,
crossPaths := false
)
lazy val gerdSettings: Seq[Setting[_]] = scalariformSettings ++ Seq(
name := "gerd",
// gerd actually has more than one consumer, but this is the first one in the chain
mainClass := Some("com.sillycat.gerd.EntryEventConsumer"),
libraryDependencies ++= Seq(
"log4j" % "log4j" % "1.2.17",
"com.github.sgroschupf" % "zkclient" % "0.1",
"com.yammer.metrics" % "metrics-core" % "2.2.0",
"org.apache.kafka" % "kafka_2.10" % "0.8.0" intransitive()
)
)
lazy val gerd = Project(id = "gerd",
base = file("gerd")).
dependsOn(main)
lazy val gerdRpm = Project(id = "gerd-rpm",
base = gerd.base).
settings(gerdSettings ++ Packaging.settings ++ Packaging.server ++ Seq(
target := file("gerd/target-rpm"),
packageSummary := "Generalized Event Routing and Distribution (gerd)",
packageDescription := "consumers that process device traffic events from kafka",
publishTo := Packaging.rpmCalcPublishTo("gerd"),
libraryDependencies += "com.sillycat" %% "guts" % ourVersion,
ideaIgnoreModule := true,
rpmPost := Some(Packaging.rpmCalcPostChown("gerd"))
): _*)
lazy val localpointBridgeApiSettings: Seq[Setting[_]] =
scalariformSettings ++ Revolver.settings ++
Seq(
name := "localpoint-bridge-api",
mainClass := Some(“com.sillycat.localpoint.console.api.LocalpointBridgeAPIServer"),
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8"),
libraryDependencies ++= Seq(
"org.specs2" %% "specs2" % "1.13" % "test",
"io.spray" % "spray-io" % sprayVersion,
"io.spray" % "spray-can" % sprayVersion,
"io.spray" % "spray-routing" % sprayVersion,
"io.spray" % "spray-caching" % sprayVersion,
"io.spray" % "spray-http" % sprayVersion,
"io.spray" % "spray-testkit" % sprayVersion,
"io.spray" % "spray-util" % sprayVersion,
"io.spray" % "spray-client" % sprayVersion,
"com.typesafe.akka" %% "akka-actor" % akkaVersion,
"com.typesafe.akka" %% "akka-testkit" % akkaVersion,
"com.typesafe.akka" %% "akka-transactor" % akkaVersion
),
fork := true
)
lazy val localpointBridgeApi = {
val dir = "localpoint-bridge-api"
BuildInfo.write(dir,
Process("git rev-parse HEAD").lines.head,
Process("git rev-parse --abbrev-ref HEAD").lines.head,
ourVersion)
Project(id = "localpoint-bridge-api",
base = file(dir)).
dependsOn(auth).
dependsOn(main % "test->test").
dependsOn(messageQueue).
settings(localpointBridgeApiSettings: _*)
}
lazy val localpointBridgeApiRpm = Project(id = "localpoint-bridge-api-rpm",
base = localpointBridgeApi.base).
settings(localpointBridgeApiSettings ++ Packaging.settings ++ Packaging.server ++ Seq(
target := file("localpoint-bridge-api/target-rpm"),
packageSummary := "localpoint bridge api",
packageDescription := "localpoint bridge api for configuration of brand-specific settings",
publishTo := Packaging.rpmCalcPublishTo("localpoint-bridge-api"),
libraryDependencies ++= Seq(
"com.sillycat" %% "localpoint-auth" % ourVersion,
"com.sillycat" %% "message-queue" % ourVersion
),
ideaIgnoreModule := true,
rpmChangelogFile := Some("changelog.txt"),
maintainer := "Carl <luohuazju@gmail.com>",
rpmPost := Some(Packaging.rpmCalcPostChown("localpoint-bridge-api"))
): _*)
lazy val migration = Project(id = "migration",
base = file("migration")).
dependsOn(main).
settings(scalariformSettings ++ Seq(
name := "migration",
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8")
): _*)
lazy val messageQueueSettings: Seq[Setting[_]] = scalariformSettings ++ Seq(
name := "message-queue",
mainClass := Some("com.sillycat.messagequeue.Workers"),
libraryDependencies ++= Seq(
"com.rabbitmq" % "amqp-client" % "3.2.1",
"net.jodah" % "lyra" % "0.3.2",
"org.slf4j" % "slf4j-api" % "1.6.1",
"com.sillycat" %% "push_notifications_api" % "0.1-0-g20d290d",
"com.lmax" % "disruptor" % "3.2.0",
"org.javolution" % "javolution-core-java" % "6.0.0"
),
initialCommands in console := """
import com.sillycat.messagequeue.disruptor._
import com.sillycat.messagequeue.rabbitmq._
import com.sillycat.messagequeue.rabbitmq.CampaignPoller._
import com.sillycat.messagequeue.pushy._
import com.sillycat.messagequeue._
import com.sillycat.localpoint.model.DAL
import org.joda.time.{DateTimeZone, DateTime}""",
initialCommands in consoleQuick := ""
)
lazy val messageQueue = Project(id = "message-queue",
base = file("message-queue")).
dependsOn(main).
dependsOn(main % "test->test").
settings(messageQueueSettings: _*)
lazy val messageQueueRpm = Project(id = "message-queue-rpm",
base = messageQueue.base).
settings(messageQueueSettings ++ Packaging.settings ++ Packaging.server ++ Seq(
target := file("message-queue/target-rpm"),
packageSummary := "message queue processor",
packageDescription := "worker that reads from message queue and sends push notifications",
publishTo := Packaging.rpmCalcPublishTo("message-queue"),
libraryDependencies += "com.sillycat" %% "guts" % ourVersion,
ideaIgnoreModule := true,
rpmPost := Some(Packaging.rpmCalcPostChown("message-queue"))
): _*)
lazy val profilesSparkSettings: Seq[Setting[_]] = scalariformSettings ++ Seq(
name := "profiles-spark",
mainClass := Some("com.sillycat.localpoint.profile.ProfileUpdater"),
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "0.9.0-incubating",
"org.hectorclient" % "hector-core" % "1.1-3",
"org.apache.cassandra" % "cassandra-all" % "1.2.14"
)
)
lazy val profilesSpark = Project(id = "profiles-spark",
base = file("profiles-spark")).
dependsOn(main).
settings(profilesSparkSettings: _*)
lazy val profilesSparkRpm = Project(id = "profiles-spark-rpm",
base = profilesSpark.base).
settings(profilesSparkSettings ++ Packaging.settings ++ Packaging.app ++ Seq(
target := file("profiles-spark/target-rpm"),
packageSummary := "profiles spark job",
packageDescription := "spark job to update profiles in cassandra",
publishTo := Packaging.rpmCalcPublishTo("profiles-spark"),
rpmPost := Some("""
hn=`/bin/hostname | /bin/cut -d'.' -f1`
if [ $hn = "cassops" ]; then
echo "10 0 * * * spark /usr/bin/profiles-spark" > /etc/cron.d/profiles-spark
fi
"""),
rpmPostun := Some("""
rm -f /etc/cron.d/profiles-spark
"""),
libraryDependencies += "com.sillycat" %% "guts" % ourVersion,
ideaIgnoreModule := true
): _*)
lazy val localpointAuthCenterSettings: Seq[Setting[_]] =
scalariformSettings ++ Revolver.settings ++
Seq(
name := "localpoint-auth-center",
mainClass := Some("com.sillycat.localpoint.authcenter.Boot"),
scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8"),
fork := true
)
lazy val localpointAuthCenter = Project(id = "localpoint-auth-center",
base = file("localpoint-auth-center")).
dependsOn(main % "test->test;compile->compile").
dependsOn(util).
dependsOn(auth).
settings(localpointAuthCenterSettings: _*)
lazy val localpointAuthCenterRpm = Project(id = "localpoint-auth-center-rpm",
base = localpointAuthCenter.base).
settings(localpointAuthCenterSettings ++ Packaging.settings ++ Packaging.server ++ Seq(
target := file("localpoint-auth-center/target-rpm"),
packageSummary := "localpoint auth center",
packageDescription := "server process for localpoint authentication requests",
publishTo := Packaging.rpmCalcPublishTo("localpoint-auth-center"),
libraryDependencies += "com.sillycat" %% "localpoint-auth" % ourVersion,
ideaIgnoreModule := true,
rpmPost := Some(Packaging.rpmCalcPostChown("localpoint-auth-center"))
): _*)
}
BuildInfo.scala
import sbt._
import java.io.PrintWriter
object BuildInfo {
/*
* Generate buld information to be used by the /bldinfo.txt route
*
* logo taken from http://www.network-science.de/ascii/ using the "slant" font.
*/
def write(dir: String, gitHash: String, branch: String, version: String): Unit = {
val logo = """
BUILD-DATE : %s
GIT REV-PARSE : %s
GIT BRANCH : %s
VERSION : %s
"""
try {
val buildDate = new java.util.Date().toString()
val writer = new PrintWriter(new File(dir + "/src/main/resources/bldinfo.txt" ))
writer.write(logo.format(buildDate, gitHash, branch, version))
writer.close
} catch {
case e: Exception => {
println("Nonfatal build exception thrown creating bldinfo.txt : " + e.getMessage())
e.printStackTrace()
}
}
}
}
Packaging.scala
import sbt._
import Keys._
object Packaging {
import com.typesafe.sbt.packager.Keys._
import com.typesafe.sbt.SbtNativePackager._
def app = packageArchetype.java_application
def server = packageArchetype.java_server
def settings: Seq[Setting[_]] =
packagerSettings ++
deploymentSettings ++
Seq(
version in Rpm ~= { _.replace("-", "_") },
rpmVendor in Rpm := “sillycat",
rpmLicense in Rpm := Some("proprietary"),
publishArtifact in (Compile, packageBin) := false,
publishArtifact in (Rpm, packageBin) := true
)
/** calculate rpm publish location; default may add stuff like scala version that we dont want */
def rpmCalcPublishTo(name: String) = Some(
Resolver.url(“sillycat Artifactory Rpm",
new URL("http://repository.sillycat.com/artifactory/rpm-repo/6/os/x86_64/Packages/%s/".format(name))
)(Patterns("%s-[revision].[ext]".format(name))))
/** because we're lazy about logging and just use a single file, on a reinstall make sure the log file is writeable by the user. */
def rpmCalcPostChown(name: String) = s"""
chown ${name}:${name} /var/log/${name};
chown -f ${name}:${name} /var/log/${name}/*.log;
"""
}
plugins.sbt
resolvers := Seq()
externalResolvers ++= Seq(
Resolver.defaultLocal,
“sillycat Artifactory" at "http://repository.sillycat.com/artifactory/remote-repos"
)
credentials += Credentials("Artifactory Realm", "repository.sillycat.com", "builder", “sillycat2011!")
addSbtPlugin("io.spray" % "sbt-revolver" % "0.7.2")
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.3.0")
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.7.4")
//addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "0.7.0-RC2")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "0.8.0-M2")
It can build rpm and debian. I will try these later.
References:
http://www.scala-sbt.org/sbt-native-packager/installation.html
http://www.scala-sbt.org/sbt-native-packager/GettingStartedApplications/MyFirstProject.html
https://github.com/sbt/sbt-native-packager
https://github.com/sbt/sbt-native-packager/issues/103
https://github.com/sbt/sbt/issues/1156
http://www.scala-sbt.org/0.12.2/docs/Detailed-Topics/Launcher.html
http://www.scala-sbt.org/0.13/docs/Proxy-Repositories.html
- 浏览: 2539556 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
nation:
你好,在部署Mesos+Spark的运行环境时,出现一个现象, ...
Spark(4)Deal with Mesos -
sillycat:
AMAZON Relatedhttps://www.godad ...
AMAZON API Gateway(2)Client Side SSL with NGINX -
sillycat:
sudo usermod -aG docker ec2-use ...
Docker and VirtualBox(1)Set up Shared Disk for Virtual Box -
sillycat:
Every Half an Hour30 * * * * /u ...
Build Home NAS(3)Data Redundancy -
sillycat:
3 List the Cron Job I Have>c ...
Build Home NAS(3)Data Redundancy
发表评论
-
Update Site will come soon
2021-06-02 04:10 1672I am still keep notes my tech n ... -
Hadoop Docker 2019 Version 3.2.1
2019-12-10 07:39 288Hadoop Docker 2019 Version 3.2. ... -
Nginx and Proxy 2019(1)Nginx Enable Lua and Parse JSON
2019-12-03 04:17 437Nginx and Proxy 2019(1)Nginx En ... -
Data Solution 2019(13)Docker Zeppelin Notebook and Memory Configuration
2019-11-09 07:15 279Data Solution 2019(13)Docker Ze ... -
Data Solution 2019(10)Spark Cluster Solution with Zeppelin
2019-10-29 08:37 243Data Solution 2019(10)Spark Clu ... -
AMAZON Kinesis Firehose 2019(1)Firehose Buffer to S3
2019-10-01 10:15 313AMAZON Kinesis Firehose 2019(1) ... -
Rancher and k8s 2019(3)Clean Installation on CentOS7
2019-09-19 23:25 301Rancher and k8s 2019(3)Clean In ... -
Pacemaker 2019(1)Introduction and Installation on CentOS7
2019-09-11 05:48 333Pacemaker 2019(1)Introduction a ... -
Crontab-UI installation and Introduction
2019-08-30 05:54 442Crontab-UI installation and Int ... -
Spiderkeeper 2019(1)Installation and Introduction
2019-08-29 06:49 493Spiderkeeper 2019(1)Installatio ... -
Supervisor 2019(2)Ubuntu and Multiple Services
2019-08-19 10:53 363Supervisor 2019(2)Ubuntu and Mu ... -
Supervisor 2019(1)CentOS 7
2019-08-19 09:33 321Supervisor 2019(1)CentOS 7 Ins ... -
Redis Cluster 2019(3)Redis Cluster on CentOS
2019-08-17 04:07 365Redis Cluster 2019(3)Redis Clus ... -
Amazon Lambda and Version Limit
2019-08-02 01:42 432Amazon Lambda and Version Limit ... -
MySQL HA Solution 2019(1)Master Slave on MySQL 5.7
2019-07-27 22:26 507MySQL HA Solution 2019(1)Master ... -
RabbitMQ Cluster 2019(2)Cluster HA and Proxy
2019-07-11 12:41 456RabbitMQ Cluster 2019(2)Cluster ... -
Running Zeppelin with Nginx Authentication
2019-05-25 21:35 315Running Zeppelin with Nginx Aut ... -
Running Zeppelin with Nginx Authentication
2019-05-25 21:34 316Running Zeppelin with Nginx Aut ... -
ElasticSearch(3)Version Upgrade and Cluster
2019-05-20 05:00 320ElasticSearch(3)Version Upgrade ... -
Jetty Server and Cookie Domain Name
2019-04-28 23:59 389Jetty Server and Cookie Domain ...
相关推荐
This practical resource shows you how to use Python for everyday Linux systems administration tasks with today’s most useful DevOps tools, including Docker, Kubernetes, and Terraform.
基于Centos 7.X打造全方位Linux高级运维架构师课程,28G百集内容,是一套非常强大的Linux运维课程,后篇还有云计算运维课程,它集成了DevOps思想,或者说叫DevOps方法。 Linux自动化运维课程包括了Linux基础运维...
DevOps for Web Development.pdf DevOps for Web Development.pdf DevOps for Web Development.pdf DevOps for Web Development.pdf
信息安全如何与devops结合:作者通过常年的devops、信息安全研究,指出了安全如何帮助devops更快的进行发布。
4. 敏捷恢复与持续改进:当SAN失败时,CIO并没有选择等待长时间的定制解决方案,而是迅速转向能够快速提供帮助的Tegile Systems。这显示了敏捷恢复的思想,即在出现故障时能够快速恢复服务,并从失败中学习,持续...
DevOps for Networking 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书
### DevOps for Web Development #### 知识点一:DevOps 概念及核心原则 - **定义**:DevOps 是一种文化和实践方法,旨在通过自动化软件交付过程和基础设施变更来缩短系统变更从构建到生产的时间,同时保持高质量...
Over the last few years, Ansible has rapidly become one of the most popular IT automation tools in the world. We’ve seen the open source community expand from the beginning of the project in early ...
Develop faster with DevOps DevOps embraces a culture of unifying the ...DevOps For Dummies is essential reading for developers and operations professionals in the early stages of DevOps adoption.
This book takes a business-centric approach to DevOps. Today’s fast-moving world makes DevOps essential to all enterprises that must be agile and lean enough to respond rapidly to changes such as ...
### DevOps for Networking:深化理解与实践 #### 标题解析 标题“DevOps for Networking”直译为“面向网络的DevOps”,这表明本书旨在介绍如何将DevOps的文化、理念和技术应用于网络管理领域。传统的网络管理和...
【标题】"主会场-Toda-DevOps & TPS - For success your Business.zip" 提供的资料聚焦于DevOps和TPS(Toyota Production System)两大主题,它们都是现代企业成功的关键因素。DevOps是一种软件开发实践,旨在通过...
《DevOps for Web Development》这本书深入探讨了DevOps在Web开发中的应用,旨在帮助运维开发者提升工作效率和产品质量。DevOps是一种文化和实践,它强调开发人员和运维人员之间的协作,以缩短软件开发周期并提供更...
适用于Azure功能的Azure Devops Build Manager :construction: 该项目目前正在进行中。 请不要在生产中使用,因为我们希望随着时间的推移会有所发展。 :construction: 该项目提供了类AzureDevopsBuildManager和...
ansible-for-devops, DevOps Ansible的Ansible示例 用于DevOps示例的 Ansible 这个存储库包含了Ansible示例,为支持 Ansible的不同部分( 一本关于 Ansible的书),该书由。大多数示例都是完整的VM示例,它使用 ...
devops入门讲解,方便大家在项目管理中学习和使用。 DevOps (a clipped compound of "development" and "operations") is a software development methodology that combines software development (Dev) with ...