使用 NGINX 转发 Github Pages 站点

背景

新的 Blog 是基于 Hugo 搭建的,原始博客内容和生成的静态资源,都是托管在 Github 仓库里面的。但 Github Pages 有时候会抽风,并且访问速度并不是很稳定,因此萌生了使用 NGINX 反向代理 Github Pages 的想法。

解决

基本原理就是将目标站点(Github Pages) 作为一个 upstream 服务,然后 NGINX 负责将所有流量都转发到 upstream 即可。因此,我们的配置文件编写就比较简单了,只需要注意 Host 等信息需要使用 upstream 站点的信息(Github Pages)。

使用 ssl on 时,NGINX 提示 Warn

现象

部分站点配置启用了 SSL 证书,启动站点的时候提示 warn。

default.conf

1
2
3
4
5
6
7
8
server{
    listen 443 ssl http2;
    server_name something.example.com;

    ssl on;
    
    # ...
}

Shell 输出

1
2022/09/27 09:39:10 [warn] 1#1: the "ssl" directive is deprecated, use the "listen ... ssl" directive instead in /etc/nginx/conf.d/default.conf:5

原因

C# 使用 AltCover 获得代码覆盖率 - E2E Test 和 Unit Test

背景

在 CI/CD 流程当中,测试是 CI 中很重要的部分。跟开发人员关系最大的就是单元测试,单元测试编写完成之后,我们可以使用 IDE 或者 dot cover 等工具获得单元测试对于业务代码的覆盖率。不过我们需要一个独立的 CLI 工具,这样我们才能够在 Jenkins 的 CI 流程集成。

端到端测试(End to End Test) 是在 Preview 版本部署完成之后,需要对 Preview 版本进行自动化测试,测试完成之后输出对应的覆盖率报告。根据代码覆盖率报告,我们可以了解 QA 编写的测试用例,是否完整覆盖了所有分支流程。

实现

工具选型

单元测试框架我选择的是 xUnit,它对于 .NET Core 与 .NET Framework 的支持都不错,并且也提供了独立于 IDE 之外的 Console Runner,可以很方便地同 Jenkins 集成。

覆盖率收集工具我选择的是 AltCover,因为它能够收集到部署在 IIS 的 ASP.NET MVC 程序覆盖率指标,这样我们就能够对一些 .NET Framework 老项目进行测试覆盖率汇总计算。AltCover 可以生成多种格式的覆盖率报告,默认格式是 OpenCover。

AltCover 生成的覆盖率报告并不是直接可读的,我们需要一个工具来生成人类可以阅读理解的报告。这里我选择的是 ReportGenerator ,它支持 OpenCover 格式的覆盖率报告,并生成对应的 HTML 文件方便查看。

Bitbucket 使用 SSH 拉取仓库失败的问题

问题

在 Bitbucket 使用 Linux 机器上 ssh-keygen 工具生成的公钥作为 API KEY,然后在 Jenkins 里面存储对应的 SSH 私钥,最后执行 Job 的时候,Windows Agent 提示 SSH 密钥不正确。

 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
 > git fetch --tags --force --progress -- ssh://git@bitbucket.xxxxx.com:7999/xxxx.git +refs/heads/*:refs/remotes/origin/* # timeout=10
ERROR: Error fetching remote repo 'origin'
hudson.plugins.git.GitException: Failed to fetch from git@bitbucket.xxxxx.com:7999/xxxx.git
	at hudson.plugins.git.GitSCM.fetchFrom(GitSCM.java:1001)
	at hudson.plugins.git.GitSCM.retrieveChanges(GitSCM.java:1242)
	at hudson.plugins.git.GitSCM.checkout(GitSCM.java:1302)
	at org.jenkinsci.plugins.workflow.steps.scm.SCMStep.checkout(SCMStep.java:129)
	at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:97)
	at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:84)
	at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start$0(SynchronousNonBlockingStepExecution.java:47)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: hudson.plugins.git.GitException: Command "git fetch --tags --force --progress -- ssh://git@bitbucket.xxxxx.com:7999/xxxx.git +refs/heads/*:refs/remotes/origin/*" returned status code 128:
stdout: 
stderr: git@bitbucket.xxxxx.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:2671)
	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandWithCredentials(CliGitAPIImpl.java:2096)
	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.access$500(CliGitAPIImpl.java:84)
	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$1.execute(CliGitAPIImpl.java:618)
	at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler$GitCommandMasterToSlaveCallable.call(RemoteGitImpl.java:158)
	at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler$GitCommandMasterToSlaveCallable.call(RemoteGitImpl.java:151)
	at hudson.remoting.UserRequest.perform(UserRequest.java:211)
	at hudson.remoting.UserRequest.perform(UserRequest.java:54)
	at hudson.remoting.Request$2.run(Request.java:376)
	at hudson.remoting.InterceptingExecutorService.lambda$wrap$0(InterceptingExecutorService.java:78)
	at java.util.concurrent.FutureTask.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at hudson.remoting.Engine$1.lambda$newThread$0(Engine.java:122)
	at java.lang.Thread.run(Unknown Source)
	Suppressed: hudson.remoting.Channel$CallSiteStackTrace: Remote call to xxx-xxx-xxx.xxx.xxx
		at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1797)
		at hudson.remoting.UserRequest$ExceptionResponse.retrieve(UserRequest.java:356)
		at hudson.remoting.Channel.call(Channel.java:1001)
		at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler.execute(RemoteGitImpl.java:143)
		at jdk.internal.reflect.GeneratedMethodAccessor8221.invoke(Unknown Source)
		at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
		at java.base/java.lang.reflect.Method.invoke(Method.java:566)
		at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler.invoke(RemoteGitImpl.java:129)
		at com.sun.proxy.$Proxy126.execute(Unknown Source)
		at hudson.plugins.git.GitSCM.fetchFrom(GitSCM.java:999)
		at hudson.plugins.git.GitSCM.retrieveChanges(GitSCM.java:1242)
		at hudson.plugins.git.GitSCM.checkout(GitSCM.java:1302)
		at org.jenkinsci.plugins.workflow.steps.scm.SCMStep.checkout(SCMStep.java:129)
		at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:97)
		at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:84)
		at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start$0(SynchronousNonBlockingStepExecution.java:47)
		at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
		at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
		at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
		at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
		at java.base/java.lang.Thread.run(Thread.java:829)

最后登录到对应的 Windows 节点,直接使用 git clone 命令也是这样,说明不是 Jenkins 的权限问题。

查询资料得知,出现这种情况需要将对应公钥(id_rsa)与私钥文件(id_rsa.pub) 复制到 Jenkins Agent 执行用户的 HOME 目录下的 .ssh 文件夹。

普通用户的 HOME 目录就是 echo $HOME,一般也就是 C:\User\UserName 的路径。但是 Jenkins Agent 一旦作为服务执行,那么他的执行用户就是 SYSTEM ACCOUNT,它的 HOME 目录路径是 C:\WINDOWS\system32\config\systemprofile\.ssh

根据上述情况试了,还是没有解决,不管是 ssh-add xxx,还是更改 Git 的 SSH CONFIG 文件都无法解决。

Abp vNext 源码分析 - 20. 电子邮件与短信支持

一、简介

ABP vNext 使用 Volo.Abp.Sms 包和 Volo.Abp.Emailing 包将短信和电子邮件作为基础设施进行了抽象,开发人员仅需要在使用的时候注入 ISmsSenderIEmailSender 即可实现短信发送和邮件发送。

二、源码分析

2.1 启动模块

短信发送的抽象层比较简单,AbpSmsModule 模块内部并无任何操作,仅作为空模块进行定义。

电子邮件的 AbpEmailingModule 模块内,主要添加了一些本地化资源支持。另一个动作就是添加了一个 BackgroundEmailSendingJob 后台作业,这个后台作业主要是用于后续发送电子邮件使用。因为邮件发送这个动作实时性要求并不高,在实际的业务实践当中,我们基本会将其加入到一个后台队列慢慢发送,所以这里 ABP 为我们实现了 BackgroundEmailSendingJob

Built with Hugo
主题 StackJimmy 设计