github软件包怎么用_GitHub软件包上的Android库

  • Post author:
  • Post category:其他


github软件包怎么用

TL; DR

(

TL;DR

)

An example Android project and walk-through of how to publish and consume libraries via

GitHub Packages

, along with features and tips such as achieving transitive dependencies through Gradle API dependency, source code availability in published package and local publishing through custom repo or MavenLocal.

一个Android项目示例,以及如何通过

GitHub软件包

发布和使用库的

演练

以及功能和技巧,例如通过Gradle API依赖关系实现传递依赖关系,已发布包中的源代码可用性以及通过自定义repo或MavenLocal进行本地发布。

GitHub软件包

(

GitHub Packages

)



GitHub Packages


is a new package repository, a.k.a artifactory, service from Github. According to its

documentation

, they support a list of common package standards such as

Maven, npm, Docker, RubyGems and NuGet

. Android uses

Maven

to manage library packages. Compared to other Maven solutions, such as

Nexus, JitPack & JFrog

,

Github Packages

has become my favorite pick for the following reasons:



GitHub Packages


是来自Github的新软件包存储库,又名人工制品。 根据其

文档

,它们支持一系列常见的软件包标准,例如

Maven,npm,Docker,RubyGems和NuGet

。 Android使用

Maven

来管理库包。 与

Nexus,JitPack和JFrog

等其他Maven解决方案相比,

Github Packages

已成为我最喜欢的选择,原因如下:

  1. Packages live in one place with their source code repository(Github). Easier for navigation and lookup between the two.

    软件包及其源代码存储库(Github)放在一个地方。 两者之间的导航和查找更加容易。

  2. Share the same authentication credential(

    Personal Access Token

    ) and permission system on Github.

    在Github上共享相同的身份验证凭据(

    个人访问令牌

    )和权限系统。

  3. Straightforward setup and we don’t need DevOps support.

    简单的设置,我们不需要DevOps支持。

  4. Large

    free data quota

    for Enterprise accounts.

    企业帐户的大量

    免费数据配额

为什么在工作中使用软件包存储库?

(

Why do I use package repositories at work?

)

As an

Application-Platform

engineer, my recent work has been to abstract common layers of application architectures(e.g. MVI base classes, View component layer) into central repositories, publish them into libraries then consume them by client apps through Gradle dependencies. Example:

作为一名

应用程序平台

工程师,我最近的工作是将应用程序体系结构的常见层(例如MVI基类,视图组件层)抽象到中央存储库中,将其发布到库中,然后由客户端应用程序通过Gradle依赖项使用它们。 例:

Image for post

Example of using Github Packages for Android libraries
对Android库使用Github软件包的示例

一个示例项目

(

An Example Project

)

Let me use an example project to demo how to leverage

Github Packages

as an artifactory to publish and consume Android libraries.

让我使用一个示例项目来演示如何利用

Github软件包

作为发布和使用Android库的工件。


Goals


目标

This is what we would like to achieve with the project:

这是我们希望通过该项目实现的目标:

Image for post

Goals for example project to achieve
例如项目要实现的目标

  1. droidlibrary

    published

    as an


    Android library


    droidlibrary

    发布




    Android库


  2. droidlibrary2

    depends on

    droidlibrary,

    and itself is published

    as


    another Android library


    droidlibrary2

    取决于

    droidlibrary,

    其本身

    作为


    另一个Android库发布


  3. Application

    declared to depend on

    droidlibrary2

    only but

    transitively


    depends

    on

    droidlibrary

    声明仅依赖

    droidlibrary2的


    应用程序

    ,但可

    传递地


    依赖


    droidlibrary

  4. All

    source code

    of dependency libraries(

    droidlibrary

    &

    droidlibrary2

    ) are available for client(app) to navigate into

    依赖库的所有

    源代码

    (

    droidlibrary



    droidlibrary2

    )可供客户端(应用程序)导航到


Nuance of Gradle Dependency : API vs. implementation


Gradle依赖性的细微差别:API与实现

In the example,

droidlibrary2

library depends on

droidlibrary

with Gradle

API

declaration, so it can expose

droidlibrary

as

transitive dependency

(we will see how so in the later Publishing section)

.

Here is the

official doc

to explain

API vs implementation

for Gradle.

在该示例中,

droidlibrary2

库依赖于具有Gradle

API

声明的

droidlibrary

,因此它可以将

droidlibrary

公开为

传递依赖项

(我们将在后面的Publishing部分中了解如何实现)



这是解释Gradle的

API与实现



官方文档

api 'com.chenzhang2006.libraries:droidlib:x.x.x'

But

app

simply declared

implementation

dependency to consume droidlibrary2:

但是

应用程序

只是声明

实现

依赖来消耗droidlibrary2:

implementation 'com.chenzhang2006.libraries:droidlib2:x.x.x'


解释发布脚本


(


Explaining Publishing Script


)


Single Gradle Script For Publishing


用于发布的单一Gradle脚本

The best way to compose your publishing script is to aggregate all publishing related script into one single file, called

publish.gradle

:

撰写发布脚本的最佳方法是将所有与发布相关的脚本聚合到一个名为

publish.gradle的

文件中:

apply plugin: 'maven-publish'


def LIB_GROUP_ID = 'com.chenzhang2006.libraries'
def LIB_ARTIFACT_ID = 'droidlib2'
def LIB_VERSION = '3.0.1'


task sourceJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier "sources"
}


publishing {
    repositories {
        maven {
            name = "GithubPackages"
            url = uri("https://maven.pkg.github.com/chenzhang2006/AndroidLibForArtifactory")
            credentials {
                username = System.getenv('GITHUB_USER') ?: project.properties['GITHUB_USER']
                password = System.getenv('GITHUB_PERSONAL_ACCESS_TOKEN') ?: project.properties['GITHUB_PERSONAL_ACCESS_TOKEN']
            }
        }
        maven {
            name = 'CustomMavenRepo'
            url = "file://${buildDir}/repo"
        }
    }
    publications {
        droidlib2(MavenPublication) {
            groupId LIB_GROUP_ID
            artifactId LIB_ARTIFACT_ID
            version LIB_VERSION
            artifact("$buildDir/outputs/aar/droidlibrary2-release.aar")
            artifact(sourceJar)


            pom.withXml {
                def dependenciesNode = asNode().appendNode('dependencies')


                //Iterate over the compile dependencies (we don't want the test ones), adding a <dependency> node for each
                configurations.api.allDependencies.each {
                    def dependencyNode = dependenciesNode.appendNode('dependency')
                    dependencyNode.appendNode('groupId', it.group)
                    dependencyNode.appendNode('artifactId', it.name)
                    dependencyNode.appendNode('version', it.version)
                }
            }
        }
    }
}

Then in

build.gradle

, you can simply add a 1-liner in the beginning:

然后在

build.gradle中

,您只需在开头添加一个1-liner:

apply from: file('publish.gradle')

There are a few points in

publish.gradle

that are worth calling out:


publish.gradle

中有几点值得一提:


  1. Use Maven Publish Gradle Plugin


    使用Maven Publish Gradle插件

apply plugin: 'maven-publish'


2. Declare Maven Repositories & Credentials


2.声明Maven存储库和凭据

We declared 2 maven repositories in the example: one for

Github Packages

(named “GithubPackages



), the other in local directory(named “CustomMavenRepo” for verification/debugging purpose). I will explain how to use the local custom repository in later

Perform Publishing

section.

在示例中,我们声明了2个Maven存储库:一个用于

Github软件包

(名为“ GithubPackages



),另一个在本地目录中(用于验证/调试的名称为“ CustomMavenRepo”)。 我将在稍后的“

执行发布”

部分中说明如何使用本地自定义存储库。

repositories {
        maven {
            name = "GithubPackages"
            url = uri("https://maven.pkg.github.com/chenzhang2006/AndroidLibForArtifactory")
            credentials {
                username = System.getenv('GITHUB_USER') ?: project.properties['GITHUB_USER']
                password = System.getenv('GITHUB_PERSONAL_ACCESS_TOKEN') ?: project.properties['GITHUB_PERSONAL_ACCESS_TOKEN']
            }
        }
        maven {
            name = 'CustomMavenRepo'
            url = "file://${buildDir}/repo"
        }
    }

There are a few ways to set credentials as Gradle properties or system environment variables. For example, you can simply set

GITHUB_USER & GITHUB_PERSONAL_ACCESS_TOKEN

in gradle properties under your home directory:

~/.gradle/gradle.properties

有几种方法可以将凭据设置为Gradle属性或系统环境变量。 例如,您可以仅在主目录下的gradle属性中设置

GITHUB_USER和GITHUB_PERSONAL_ACCESS_TOKEN



〜/ .gradle / gradle.properties

Refer to

this document

for details of credential configuration for GitHub Packages.

有关GitHub软件包的凭证配置的详细信息,请参阅

此文档


3. Declare Publications


3.声明出版物

In this example, each library only has one publication:

在此示例中,每个库只有一个出版物:

publications {
        droidlib2(MavenPublication) {
            groupId LIB_GROUP_ID
            artifactId LIB_ARTIFACT_ID
            version LIB_VERSION
            artifact("$buildDir/outputs/aar/droidlibrary2-release.aar")
            artifact(sourceJar)


            pom.withXml {
                def dependenciesNode = asNode().appendNode('dependencies')


                //Iterate over the compile dependencies (we don't want the test ones), adding a <dependency> node for each
                configurations.api.allDependencies.each {
                    def dependencyNode = dependenciesNode.appendNode('dependency')
                    dependencyNode.appendNode('groupId', it.group)
                    dependencyNode.appendNode('artifactId', it.name)
                    dependencyNode.appendNode('version', it.version)
                }
            }
        }
    }
  • Note that

    configurations.api.allDependencies

    is the part that carried out the magic of

    exposing API dependencies as transitive dependency

    and manifest the transitive dependencies in Maven pom.xml(will show in later

    Perform Publishing

    section):

    请注意,

    configurations.api.allDependencies

    是实现

    将API依赖



    公开为传递性依赖关系

    并在Maven pom.xml中显示传递性依赖关系的部分(将在以后的

    Perform Publishing

    部分中显示):

pom.withXml {
    def dependenciesNode = asNode().appendNode('dependencies')


    configurations.api.allDependencies.each {
        def dependencyNode = dependenciesNode.appendNode('dependency')
        dependencyNode.appendNode('groupId', it.group)
        dependencyNode.appendNode('artifactId', it.name)
        dependencyNode.appendNode('version', it.version)
    }
}
  • Note that this is what makes the

    source code jar

    available in the published package:

    请注意,这就是使

    源代码jar

    在已发布的程序包中可用的原因:

task sourceJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier "sources"
}
//...
artifact(sourceJar)

执行发布

(

Perform Publishing

)


Publish with Android Studio UI


使用Android Studio UI发布

In

Gradle

panel of

Android Studio

, each module that is configured with publishing plugin would display the

publishing

tasks as available actions. Because we declared 2 maven repositories in the publish script in the example, there are multiple publishing tasks available:

* publish[Publication]To


CustomMavenRepo


Repository* publish[Publication]To


GithubPackages


Repository



Android Studio的


Gradle

面板中,配置有发布插件的每个模块都将

发布

任务显示为可用操作。 因为在示例中,我们在发布脚本中声明了2个maven存储库,所以有多个发布任务可用:

* publish [Publication]到


CustomMavenRepo


Repository * publish [Publication]到


GithubPackages


Repository

Image for post

Available granular publishing tasks
可用的精细发布任务
  • Clicking on those

    publish[Publication]To


    CustomMavenRepo


    Repository tasks

    would result in publishing to the local directory, which is a great way to examine locally what artifacts are actually in the package before publishing them to the remote repository.

    单击

    发布到


    CustomMavenRepo信息


    库的任务

    将导致发布到本地目录,这是在将它们发布到远程信息库之前在本地检查包中实际存在哪些工件的好方法。

Image for post

** If you open

pom.xml

, note that

transitive dependencies

are manifested here for maven to understand that

droidlib2

transitively depends on

droidlib

. Finally, that explained why we wanted

API

Gradle dependency in earlier section.

**如果打开

pom.xml

,请注意,

传递的依赖关系

在此处显示,供maven理解

droidlib2的

传递依赖于

droidlib

。 最后,这解释了为什么在前面的部分中我们想要

API

Gradle依赖性。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.chenzhang2006.libraries</groupId>
  <artifactId>droidlib2</artifactId>
  <version>3.0.1</version>
  <packaging>aar</packaging>
  <dependencies>
    <dependency>
      <groupId>com.chenzhang2006.libraries</groupId>
      <artifactId>droidlib</artifactId>
      <version>2.0.1</version>
    </dependency>
  </dependencies>
</project>

** Please note that droidlib2-xxx-

sources.jar

is also generated in the package along with the binary artifact(aar). That is why client app would be able to navigate into source code of the libraries.

**请注意,droidlib2-xxx-

sources.jar

也会与二进制工件(aar)一起在软件包中生成。 这就是为什么客户端应用程序能够导航到库的源代码的原因。

  • Clicking on those

    publish[Publication]To


    GithubPackages


    Repository

    tasks would post the package to the remote

    Github Packages

    .

    单击

    发布到


    GithubPackages


    存储库的


    [Publication]

    任务会将其发布到远程

    Github Packages

  • Clicking on

    publish

    task would trigger both local and remote publishings.

    单击

    发布

    任务将触发本地和远程发布。

Now if you navigate to

Github Packages UI

for

droidlib2

, you should see its transitive dependency and 3 artifacts in its published package.

现在,如果您导航到

droidlib2的


Github Packages UI

,您应该在其发布的包中看到其传递依赖关系和3个工件。

Image for post

Image for post

Image for post


Command Line or CI/CD Automation


命令行或CI / CD自动化

You can achieve the same result as from

Android Studio

by running Gradle commands for manual publishing. For example:

您可以通过运行Gradle命令进行手动发布来获得与

Android Studio

相同的结果。 例如:


gradlew :droidlibrary:publish


gradlew:droidlibrary:publish

This command can be run in your CI/CD to achieve automation, if that is desired.

如果需要,可以在CI / CD中运行此命令以实现自动化。


Publish SNAPSHOTs To MavenLocal For Local Integration


将SNAPSHOT发布到MavenLocal进行本地集成

This is a very common practice to integrate libraries locally with client apps and verify library functionalities before publishing to remote repositories. In that case,

publishToMavenLocal

comes to rescue.

在本地将库与客户端应用程序集成并在发布到远程存储库之前验证库功能是一种非常普遍的做法。 在这种情况下,

publishToMavenLocal

可以解救。

Image for post

Note that in convention, locally published library should be versioned with “-SNAPSHOT” as suffix. E.g.

LIB_VERSION =


‘3.0.1-SNAPSHOT’

. The client side should match the same version to consume.

请注意,按照惯例,本地发布的库应使用“ -SNAPSHOT”作为后缀。 例如

LIB_VERSION =


‘3.0.1-SNAPSHOT’

。 客户端应匹配使用相同的版本。

客户端Gradle设置和运行

(

Client Side Gradle Setup and Run

)

In client

app

, we configured Maven repositories in

build.gradle

in project root, so clients can access

both Github Packages and MavenLocal repositories

:

在客户端

应用程序中

,我们在项目根目录的

build.gradle

中配置了Maven存储库,因此客户端可以访问

Github软件包和MavenLocal存储库

allprojects {
    repositories {
        // google(), jcenter()...


        mavenLocal()
        maven {
            name = "AndroidLibForArtifactory"
            url = uri("https://maven.pkg.github.com/chenzhang2006/AndroidLibForArtifactory")
            credentials {
                username = System.getenv('GITHUB_USER') ?: project.properties['GITHUB_USER']
                password = System.getenv('GITHUB_PERSONAL_ACCESS_TOKEN') ?: project.properties['GITHUB_PERSONAL_ACCESS_TOKEN']
            }
        }
    }
}

For Github Maven repo setup:

对于Github Maven回购设置:

  • Hostname of

    url

    always


    starts with

    maven.pkg.github.com

    for

    Github Packages


    网址的

    主机名始终




    maven.pkg.github.com

    开始以获取

    Github软件包

  • Path of

    url

    matches the library project(source code)name on Github


    网址

    路径与Github上的库项目(源代码)名称匹配

Dependency declaration:

依赖声明:

implementation 'com.chenzhang2006.libraries:droidlib2:x.x.x'

Now you can spin up the app and verify that it can access both libraries and navigate into source code as described in our

Goals

section earlier.

现在,您可以启动该应用程序,并验证它可以访问两个库并导航到源代码,如前面“

目标”

部分所述。

Hope the demo and the walk-through helps if the topic fits your need. Feel free to fork repo as playground. Let me know if you hit snags somewhere and I will try my best to answer.

如果主题适合您,希望演示和演练对您有所帮助。 随意叉回购作为游乐场。 让我知道您是否在某处碰到障碍物,我会尽力回答。

翻译自:

https://proandroiddev.com/android-libraries-on-github-packages-21f135188d58

github软件包怎么用