Skip to content
This repository was archived by the owner on Aug 21, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ gitlab-le \
--production `# OPTIONAL - Obtain a real certificate instead of a dummy one and configure your repository to use it`
--path `# OPTIONAL - Absolute path in your repository where challenge files should be uploaded`
--jekyll `# OPTIONAL - Upload challenge files with a Jekyll-compatible YAML front matter` \
--branch `# OPTIONAL - Upload challenge files to this branch, default is the main branch of the repository` \
```

See `gitlab-le --help` for more details.
Expand Down Expand Up @@ -77,4 +78,4 @@ However, GitLab does not provide a way to automatically renew certificates, so t

## Automation

Since 10.2, GitLab provides an API to configure HTTPS certificates on a GitLab page, which means `gitlab-le` can be configured to obtain new certificates when your existing ones are about to expire.
Since 10.2, GitLab provides an API to configure HTTPS certificates on a GitLab page, which means `gitlab-le` can be configured to obtain new certificates when your existing ones are about to expire.
6 changes: 5 additions & 1 deletion args.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,15 @@ module.exports = yargs
describe: 'Obtain a real certificate instead of a dummy one and configure your repository to use it',
type: 'boolean',
default: false
}).option('branch', {
describe: 'Select the branch where the challenge files should be uploaded.',
type: 'string',
default: ''
}).example('$0 --domain example.com www.example.com --email [email protected] --repository https://gitlab.com/foo/example.gitlab.io --token abc123', 'Simple build where all files are served from public/ inside your repository')
.example('$0 --jekyll --path / --domain example.com --email [email protected] --repository https://gitlab.example.com/foo/myrepo --token abc123', 'Jekyll website that serves all valid files in your repository\'s root directory')
.wrap(yargs.terminalWidth())
.check(argv => {
const empty = Object.keys(argv).filter(key => key !== '_' && argv[key].length == 0);
const empty = Object.keys(argv).filter(key => key !== '_' && key !== 'branch' && argv[key].length == 0);
if (empty.length > 0) {
console.error(`Missing required arguments: ${empty.join(', ')}`);
process.exit(1);
Expand Down
12 changes: 6 additions & 6 deletions lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ module.exports = (options) => {
});
};

const uploadChallenge = (key, value, repo, domain) => {
const uploadChallenge = (key, value, repo, domain, branch) => {
const challengeContent = options.jekyll ?
`---\nlayout: null\npermalink: /.well-known/acme-challenge/${key}\n---\n${value}` : value;
// Need to bluebird-ify to use .asCallback()
Expand All @@ -56,20 +56,20 @@ module.exports = (options) => {
url: `/projects/${repo.id}/repository/files/${filePath}`,
body: {
commit_message: 'Automated Let\'s Encrypt renewal: add challenge',
branch: repo.default_branch,
branch: branch || repo.default_branch,
content: challengeContent,
author_name: 'gitlab-le'
}
})).return([`http://${domain}/.well-known/acme-challenge/${key}`, value]);
};

const deleteChallenges = (key, repo) => {
const deleteChallenges = (key, repo, branch) => {
const filePath = encodeURIComponent(path.posix.resolve('/', options.path, key));
return Promise.resolve(gitlabRequest.delete({
url: `/projects/${repo.id}/repository/files/${filePath}`,
body: {
commit_message: 'Automated Let\'s Encrypt renewal: remove challenge',
branch: repo.default_branch,
branch: branch || repo.default_branch,
author_name: 'gitlab-le'
}
}));
Expand Down Expand Up @@ -151,13 +151,13 @@ module.exports = (options) => {
domains: options.domain,
setChallenge: (hostname, key, value, cb) => {
return Promise.resolve(deleteChallengesPromise)
.then(() => uploadChallenge(key, value, repo, hostname))
.then(() => uploadChallenge(key, value, repo, hostname, options.branch))
.tap(res => console.log(`Uploaded challenge file, polling until it is available at ${res[0]}`))
.spread(pollUntilDeployed)
.asCallback(cb);
},
removeChallenge: (hostname, key, cb) => {
return (deleteChallengesPromise = deleteChallenges(key, repo)).finally(() => cb(null));
return (deleteChallengesPromise = deleteChallenges(key, repo, options.branch)).finally(() => cb(null));
}
});
}).tap(cert =>
Expand Down