renovate
renovate copied to clipboard
Update doc for ecr and codeartifact
What would you like Renovate to be able to do?
In order to successfully self-host renovate to work with aws ecr for docker images and aws codeartifact for nuget/pypi/... quite some configuration effort is needed. I wanted to share my results so the documentation can be updated. Hopefully this will be helpful to someone =)
If you have any ideas on how this should be implemented, please tell us here.
First of all, codeartifact requires temporary credentials. I obtained those using an init-container. Here is my cron job:
kind: CronJob
metadata:
name: renovate
namespace: renovate
spec:
schedule: '@daily'
concurrencyPolicy: Forbid
jobTemplate:
spec:
backoffLimit: 0
template:
spec:
serviceAccountName: renovate
initContainers:
- name: init-config
image: <e.g. alpine with aws cli installed>
# code artifact is only accessible via temporary credentials.
# Until https://github.com/renovatebot/renovate/issues/11325 is done, we need to obtain the token manually, and insert it into the config
command:
- /bin/bash
- -c
- |
#!/bin/bash
AUTH_TOKEN=$( aws codeartifact get-authorization-token --domain <domain> --domain-owner 123456789012 --query authorizationToken --output text )
sed "s/<PLACEHOLDER>/$AUTH_TOKEN/g" /workdir/config.json >> /processed/config.json
volumeMounts:
- name: config-volume
mountPath: /processed
- name: template-volume
mountPath: /workdir
containers:
- name: renovate
image: renovate/renovate:31.28
env:
- name: LOG_LEVEL
value: info
- name: RENOVATE_CONFIG_FILE
value: "/usr/src/app/config/config.json"
envFrom:
- secretRef:
name: bitbucket-renovate-token
- secretRef:
name: github-renovate-token
volumeMounts:
- name: config-volume
mountPath: /usr/src/app/config/
readOnly: true
restartPolicy: Never
volumes:
- name: template-volume
configMap:
name: renovate-config
- name: config-volume
emptyDir: {}
This is my config map:
kind: ConfigMap
metadata:
name: renovate-config
namespace: renovate
data:
config.json: |-
{
"dryRun" : false,
"autodiscover" : true,
"platform" : "bitbucket-server",
"endpoint" : "https://git.my_company.com",
"username" : "<the bots name>",
"gitAuthor" : "<the bots name>",
"packageRules": [
{
"matchDatasources": ["nuget"],
"registryUrls": [
"https://api.nuget.org/v3/index.json",
"https://<domain>-123456789012.d.codeartifact.<region>.amazonaws.com/nuget/<nu-get-repo>/v3/index.json"
]
}
],
"hostRules" : [
{"matchHost":"https://123456789012.dkr.ecr.<region>.amazonaws.com", "enabled":true, "hostType":"docker"},
{"matchHost":"<domain>-123456789012.d.codeartifact.<region>.amazonaws.com", "enabled":true, "token":"<PLACEHOLDER>"}
],
"branchPrefix" : "renovate-",
"onboardingBranch" : "renovate-configure"
}
In addition, you need to create the namespace, service account and secrets obviously, as well as a iam role for the service account. I use the following iam role, which (in my opinion) has sufficiently minimalistic permissions:
"Version" : "2012-10-17",
"Statement" : [
{
"Sid" : "Stmt1642517217303",
"Action" : [
"ecr:BatchCheckLayerAvailability",
"ecr:BatchGetImage",
"ecr:DescribeImageReplicationStatus",
"ecr:DescribeImageScanFindings",
"ecr:DescribeImages",
"ecr:DescribePullThroughCacheRules",
"ecr:DescribeRegistry",
"ecr:DescribeRepositories",
"ecr:GetDownloadUrlForLayer",
"ecr:GetLifecyclePolicy",
"ecr:GetLifecyclePolicyPreview",
"ecr:GetRegistryPolicy",
"ecr:GetRegistryScanningConfiguration",
"ecr:GetRepositoryPolicy",
"ecr:ListImages",
"ecr:ListTagsForResource"
],
"Effect" : "Allow",
"Resource" : "arn:aws:ecr:<region>:123456789012:repository/*"
},
{
"Sid" : "Stmt1642517217304",
"Action": ["ecr:GetAuthorizationToken"],
"Effect": "Allow",
"Resource": "*"
},
{
"Sid" : "Stmt1642517217305",
"Action" : [
"codeartifact:Get*",
"codeartifact:List*",
"codeartifact:Describe*",
"codeartifact:Read*"
],
"Effect" : "Allow",
"Resource" : [
"arn:aws:codeartifact:<region>:123456789012:domain/<domain>",
"arn:aws:codeartifact:<region>:123456789012:repository/<domain>/*"
]
},
{
"Sid" : "Stmt1642517217306",
"Action" : "sts:GetServiceBearerToken",
"Effect" : "Allow",
"Resource" : "*",
"Condition" : {
"StringEquals" : {
"sts:AWSServiceName" : "codeartifact.amazonaws.com"
}
}
}
]
}
Is this a feature you are interested in implementing yourself?
No
Thanks. Such documentation can live in https://github.com/renovatebot/renovate/blob/main/lib/datasource/docker/readme.md where it would then end up in https://docs.renovatebot.com/modules/datasource/docker/
Where do you log into ECR?
I'm expecting commands like this in your init somewhere, so helm and docker can auth.
aws ecr get-login-password --region us-west-2 > /tmp/creds
Renovate does not call helm
or docker
directly
I'm increasing the priority of this issue. We're getting questions about AWS CodeArtifact in the discussions. We can probably prevent questions by updating the docs. 😄
We got it working. I'm pasting a redacted helm values.yaml below of our helm chart with the important parts required. Some notes
- We use github for NPM, AWS for PY and ECR, and some github for ECR
- Use init containers to get both the github app token (for renovatebot) as well as the AWS CLI auth tokens
- Github still requires a robot USER token (not app token) for NPM
- Heavy use of the "init container to file, then read file to variable" pattern.
- Use kubernetes external-secrets to load up our github app token and user tokens from ENV
existingSecret: renovatebot-env
serviceAccount:
create: true
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::${cluster_account_id}:role/${cluster_env}-renovatebot
image:
repository: ${cluster_account_id}.dkr.ecr.us-west-2.amazonaws.com/third-party/renovate/renovate
extraVolumes:
- name: shared
emptyDir: {}
- name: renovatebot-apptoken
secret:
secretName: renovatebot-apptoken
- name: renovatebot-extra-config
configMap:
name: renovatebot-extra-config
extraVolumeMounts:
- mountPath: /shared
name: shared
- name: renovatebot-extra-config
mountPath: /usr/src/app/config.js
subPath: config.js
redis:
# Cache run results
enabled: true
env:
LOG_LEVEL: debug
extraConfigmaps:
- name: config
data:
# A lot of this idea is taken from https://github.com/renovatebot/helm-charts/discussions/237
config.js: |
const fs = require('fs');
// fs read idea taken from https://github.com/renovatebot/helm-charts/issues/248
const token = fs.readFileSync('/shared/token', 'utf8');
// Token from code-artifact
const pipToken = fs.readFileSync('/shared/pip-login-token', 'utf8').trim();
// All the configuration options are here: https://docs.renovatebot.com/self-hosted-configuration/#token
module.exports = {
// Without trim, the \n at the end of the file causes the token to be invalid
token: token.trim(),
// Some of these config options are from https://docs.renovatebot.com/modules/platform/github/
// Note: must EXACTLY match application name or bad things happen
username: 'our-renovatebot[bot]',
gitAuthor: "our-bot <123456+our-bot[bot]@users.noreply.github.enterprise.com>",
platform: "github",
autodiscover: true,
// Run everywhere!
autodiscoverFilter: ["COMPANYH/*"],
// https://docs.renovatebot.com/self-hosted-configuration/#onboardingconfigfilename
onboardingConfigFileName: ".github/renovate.json",
hostRules: [
{
matchHost: 'https://ghcr.io',
token: token.trim()
}, {
matchHost: "https://npm.pkg.github.com/",
hostType: "npm",
token: process.env.ROBOT_TOKEN
}, {
matchHost: "COMPANY-private-123123123.d.codeartifact.us-west-2.amazonaws.com",
token:pipToken
}
],
python: {
registryUrls: ["https://COMPANY-private-123123123.d.codeartifact.us-west-2.amazonaws.com/pypi/pypi-private/simple/"]
},
npmrc: "@COMPANY:registry=https://npm.pkg.github.com/",
secrets: {}
}
cronjob:
# Run every hour
schedule: "0 * * * *"
initContainers:
- name: github-app-installation-token
env:
# Get these two values from https://github.com/organizations/COMPANY/settings/installations/123123
- name: GITHUB_APP_ID
value: "123123"
- name: GITHUB_INSTALLATION_ID
value: "456456"
image: node:16.17.1-alpine3.15
command: ["/bin/sh"]
args:
- -c
- |
npx github-app-installation-token \
--appId $GITHUB_APP_ID \
--installationId $GITHUB_INSTALLATION_ID \
--privateKeyLocation /secret/renovatebot-apptoken/renovatebot-apptoken.pem > /shared/token
volumeMounts:
- mountPath: /shared
name: shared
- name: renovatebot-apptoken
mountPath: "/secret/renovatebot-apptoken"
readOnly: true
- name: aws-cli-commands
image: amazon/aws-cli:2.9.9
command: ["/bin/bash"]
args:
- -c
- |
#!/bin/bash
aws codeartifact get-authorization-token --domain COMPANY-private --domain-owner 123123123 \
--query authorizationToken --output text > /shared/pip-login-token
volumeMounts:
- mountPath: /shared
name: shared
renovate:
existingConfigFile: "/usr/src/app/config.js"
Can someone please share the detailed steps on how to do this? I have been trying to do the same since last 3 weeks but no luck yet. @leoffj @rarkins @cep21 @HonkingGoose
I don't know enough about this to help you.
Ok here I am posting a complete working solution with self hosted renovate on github actions. Please note that this solution is for Kotlin/Gradle/Maven based repos.
Inside .github/workflows create a renovate.yml file with the following content. Change the placeholder values according to your needs. (Keep REPLACE_WITH_GITHUB_TOKEN and REPLACE_WITH_CODEARTIFACT_AUTH_TOKEN as it is)
name: Renovate
on:
schedule:
- cron: '*/10 * * * *' # Set the schedule according to your preference
jobs:
renovate:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: 18.12.0
- name: Install Renovate
run: npm install -g renovate
- name: Replace GitHub token in renovate-config.json
run: sed -i 's/REPLACE_WITH_GITHUB_TOKEN/${{ secrets.GITHUB_TOKEN }}/g' renovate-config.json
- name: Replace CodeArtifact token in renovate-config.json
run: sed -i 's/REPLACE_WITH_CODEARTIFACT_AUTH_TOKEN/${{ secrets.CODEARTIFACT_AUTH_TOKEN }}/g' renovate-config.json
- name: Run Renovate
run: renovate
env:
RENOVATE_CONFIG_FILE: renovate-config.json
CODEARTIFACT_AUTH_TOKEN: ${{ secrets.CODEARTIFACT_AUTH_TOKEN }}
Now in the root of your repo create a file named renovate-config.json with the following content. ( Keep REPLACE_WITH_CODEARTIFACT_AUTH_TOKEN here as it is too)
{
"platform": "github",
"endpoint": "https://api.github.com",
"token": "<github token>",
"enabled": true,
"repositories": ["repoOwner/repoName"],
"dependencyDashboard": true,
"repositoryCache": "gradle-test-renovate-cache",
"packageRules": [
{
"matchDatasources": ["maven"],
"registryUrls": [
"https://domain-domainOwner.d.codeartifact.region.amazonaws.com/maven/repository/"
]
}
],
"hostRules": [
{
"hostType": "maven",
"baseUrl": "https://domain-domainOwner.d.codeartifact.region.amazonaws.com/maven/repository/",
"token": "REPLACE_WITH_CODEARTIFACT_AUTH_TOKEN"
}
]
}
This should be enough to make it work. Also if you have enabled the renovate bot on this repo or on the organizational level then in the root of repo you will see a file named " renovate.json ". Replace the content of that file with the following
{
"enabled": true
}
Hope this will help. Thanks
Ok here I am posting a complete working solution with self hosted renovate on github actions. Please note that this solution is for Kotlin/Gradle/Maven based repos.
Inside .github/workflows create a renovate.yml file with the following content. Change the placeholder values according to your needs. (Keep REPLACE_WITH_GITHUB_TOKEN and REPLACE_WITH_CODEARTIFACT_AUTH_TOKEN as it is)
name: Renovate on: schedule: - cron: '*/10 * * * *' # Set the schedule according to your preference jobs: renovate: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v2 - name: Set up Node.js uses: actions/setup-node@v2 with: node-version: 18.12.0 - name: Install Renovate run: npm install -g renovate - name: Replace GitHub token in renovate-config.json run: sed -i 's/REPLACE_WITH_GITHUB_TOKEN/${{ secrets.GITHUB_TOKEN }}/g' renovate-config.json - name: Replace CodeArtifact token in renovate-config.json run: sed -i 's/REPLACE_WITH_CODEARTIFACT_AUTH_TOKEN/${{ secrets.CODEARTIFACT_AUTH_TOKEN }}/g' renovate-config.json - name: Run Renovate run: renovate env: RENOVATE_CONFIG_FILE: renovate-config.json CODEARTIFACT_AUTH_TOKEN: ${{ secrets.CODEARTIFACT_AUTH_TOKEN }}
Now in the root of your repo create a file named renovate-config.json with the following content. ( Keep REPLACE_WITH_CODEARTIFACT_AUTH_TOKEN here as it is too)
{ "platform": "github", "endpoint": "https://api.github.com", "token": "<github token>", "enabled": true, "repositories": ["repoOwner/repoName"], "dependencyDashboard": true, "repositoryCache": "gradle-test-renovate-cache", "packageRules": [ { "matchDatasources": ["maven"], "registryUrls": [ "https://domain-domainOwner.d.codeartifact.region.amazonaws.com/maven/repository/" ] } ], "hostRules": [ { "hostType": "maven", "baseUrl": "https://domain-domainOwner.d.codeartifact.region.amazonaws.com/maven/repository/", "token": "REPLACE_WITH_CODEARTIFACT_AUTH_TOKEN" } ] }
This should be enough to make it work. Also if you have enabled the renovate bot on this repo or on the organizational level then in the root of repo you will see a file named " renovate.json ". Replace the content of that file with the following
{ "enabled": true }
Hope this will help. Thanks
Is there a way how renovate can also look at the typical public registrys aswell? We disabled upstream registrys in the CodeArtifact settings. So with your settings enabled I can only update my packages that are on CodeArtifact.
Ok here I am posting a complete working solution with self hosted renovate on github actions. Please note that this solution is for Kotlin/Gradle/Maven based repos. Inside .github/workflows create a renovate.yml file with the following content. Change the placeholder values according to your needs. (Keep REPLACE_WITH_GITHUB_TOKEN and REPLACE_WITH_CODEARTIFACT_AUTH_TOKEN as it is)
name: Renovate on: schedule: - cron: '*/10 * * * *' # Set the schedule according to your preference jobs: renovate: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v2 - name: Set up Node.js uses: actions/setup-node@v2 with: node-version: 18.12.0 - name: Install Renovate run: npm install -g renovate - name: Replace GitHub token in renovate-config.json run: sed -i 's/REPLACE_WITH_GITHUB_TOKEN/${{ secrets.GITHUB_TOKEN }}/g' renovate-config.json - name: Replace CodeArtifact token in renovate-config.json run: sed -i 's/REPLACE_WITH_CODEARTIFACT_AUTH_TOKEN/${{ secrets.CODEARTIFACT_AUTH_TOKEN }}/g' renovate-config.json - name: Run Renovate run: renovate env: RENOVATE_CONFIG_FILE: renovate-config.json CODEARTIFACT_AUTH_TOKEN: ${{ secrets.CODEARTIFACT_AUTH_TOKEN }}
Now in the root of your repo create a file named renovate-config.json with the following content. ( Keep REPLACE_WITH_CODEARTIFACT_AUTH_TOKEN here as it is too)
{ "platform": "github", "endpoint": "https://api.github.com", "token": "<github token>", "enabled": true, "repositories": ["repoOwner/repoName"], "dependencyDashboard": true, "repositoryCache": "gradle-test-renovate-cache", "packageRules": [ { "matchDatasources": ["maven"], "registryUrls": [ "https://domain-domainOwner.d.codeartifact.region.amazonaws.com/maven/repository/" ] } ], "hostRules": [ { "hostType": "maven", "baseUrl": "https://domain-domainOwner.d.codeartifact.region.amazonaws.com/maven/repository/", "token": "REPLACE_WITH_CODEARTIFACT_AUTH_TOKEN" } ] }
This should be enough to make it work. Also if you have enabled the renovate bot on this repo or on the organizational level then in the root of repo you will see a file named " renovate.json ". Replace the content of that file with the following
{ "enabled": true }
Hope this will help. Thanks
Is there a way how renovate can also look at the typical public registrys aswell? We disabled upstream registrys in the CodeArtifact settings. So with your settings enabled I can only update my packages that are on CodeArtifact.
Yes there is. I used that but dont remember exactly now. You can ask for chatgpt as the solution I posted was suggested by chatgpt. That was something like
registry=https://your-codeartifact-url/
@scope:registry=https://npmjs.org/
Just checked with chatgpt and it showed below suggested way to solve your problem.
{
"platform": "github",
"endpoint": "https://api.github.com",
"token": "
WARN: Excess registryUrls found for datasource lookup - using first configured only (repository=repo123, baseBranch=develop)
28 | "datasource": "npm", 29 | "packageName": "@babel/core", 30 | "registryUrls": [ 31 | "https://domain-domainowner.d.codeartifact.eu-central-1.amazonaws.com/npm/repository", 32 | "https://registry.npmjs.org" 33 | ]
may be try this
{
"platform": "github",
"endpoint": "https://api.github.com",
"token": "
Sorry, I typed npm which made it confusing. Here just an example JUST with maven:
My code:
{
"platform": "github",
"endpoint": "https://api.github.com",
"token": "",
"enabled": true,
"repositories": ["repoOwner/repoName"],
"dependencyDashboard": true,
"repositoryCache": "gradle-test-renovate-cache",
"packageRules": [
{
"matchDatasources": ["maven"],
"registryUrls": [
"https://domain-domainOwner.d.codeartifact.region.amazonaws.com/maven/repository/",
"https://repo.maven.apache.org/maven2"
]
}
],
"hostRules": [
{
"hostType": "maven",
"baseUrl": "https://domain-domainOwner.d.codeartifact.region.amazonaws.com/maven/repository/",
"token": "REPLACE_WITH_CODEARTIFACT_AUTH_TOKEN"
}
]
}
The error message: WARN: Excess registryUrls found for datasource lookup - using first configured only (repository=repo123, baseBranch=develop)
I also tried adding a second hostType entry:
{
"hostType": "maven",
"baseUrl": "https://domain-domainOwner.d.codeartifact.region.amazonaws.com/maven/repository/",
"token": "https://repo.maven.apache.org/maven2"
}
But still no luck
I think i found a way filtering for packageprefixes (example for npm):
{
"matchDatasources": ["npm"],
"registryUrls": [
"https://registry.npmjs.org/"
]
},
{
"matchDatasources": ["npm"],
"matchPackagePrefixes": ["@myAwesomePrefix"],
"registryUrls": [
"https://domain-domainOwner.d.codeartifact.region.amazonaws.com/npm/repository/"
]
}
I think i found a way filtering for packageprefixes (example for npm):
{ "matchDatasources": ["npm"], "registryUrls": [ "https://registry.npmjs.org/" ] }, { "matchDatasources": ["npm"], "matchPackagePrefixes": ["@myAwesomePrefix"], "registryUrls": [ "https://domain-domainOwner.d.codeartifact.region.amazonaws.com/npm/repository/" ] }
Great.. thanks