test(corpus): add public real yaml seeds
Vendor the pinned public YAML seeds used by the real-corpus and Yams differential gates.
This commit is contained in:
parent
b9215d4015
commit
ca96772207
91728
Tests/Fixtures/real-yaml/api-guru-stripe-openapi.yaml
Normal file
91728
Tests/Fixtures/real-yaml/api-guru-stripe-openapi.yaml
Normal file
File diff suppressed because it is too large
Load Diff
95627
Tests/Fixtures/real-yaml/api-guru-zoom-openapi.yaml
Normal file
95627
Tests/Fixtures/real-yaml/api-guru-zoom-openapi.yaml
Normal file
File diff suppressed because it is too large
Load Diff
24
Tests/Fixtures/real-yaml/argocd-applicationset-design.yaml
Normal file
24
Tests/Fixtures/real-yaml/argocd-applicationset-design.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
# This is an example of a typical ApplicationSet which uses the cluster generator.
|
||||
# An ApplicationSet is comprised with two stanzas:
|
||||
# - spec.generator - producer of a list of values supplied as arguments to an app template
|
||||
# - spec.template - an application template, which has been parameterized
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: ApplicationSet
|
||||
metadata:
|
||||
name: guestbook
|
||||
spec:
|
||||
goTemplate: true
|
||||
goTemplateOptions: ["missingkey=error"]
|
||||
generators:
|
||||
- clusters: {}
|
||||
template:
|
||||
metadata:
|
||||
name: '{{.name}}-guestbook'
|
||||
spec:
|
||||
source:
|
||||
repoURL: https://github.com/infra-team/cluster-deployments.git
|
||||
targetRevision: HEAD
|
||||
chart: guestbook
|
||||
destination:
|
||||
server: '{{.server}}'
|
||||
namespace: guestbook
|
||||
@ -0,0 +1 @@
|
||||
# Blank values.yaml
|
||||
@ -0,0 +1,10 @@
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: angular
|
||||
target: builder
|
||||
ports:
|
||||
- 4200:4200
|
||||
volumes:
|
||||
- ./angular:/project
|
||||
- /project/node_modules
|
||||
@ -0,0 +1,9 @@
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: app
|
||||
target: builder
|
||||
ports:
|
||||
- '80:80'
|
||||
volumes:
|
||||
- ./app:/var/www/html/
|
||||
@ -0,0 +1,22 @@
|
||||
services:
|
||||
web:
|
||||
build: app/aspnetapp
|
||||
ports:
|
||||
- 80:80
|
||||
db:
|
||||
environment:
|
||||
ACCEPT_EULA: "Y"
|
||||
SA_PASSWORD: example_123
|
||||
# mssql server image isn't available for arm64 architecture, so we use azure-sql instead
|
||||
image: mcr.microsoft.com/azure-sql-edge:1.0.4
|
||||
# If you really want to use MS SQL Server, uncomment the following line
|
||||
#image: mcr.microsoft.com/mssql/server
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P example_123 -Q 'SELECT 1' || exit 1"]
|
||||
interval: 10s
|
||||
retries: 10
|
||||
start_period: 10s
|
||||
timeout: 3s
|
||||
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: app
|
||||
target: builder
|
||||
ports:
|
||||
- '8000:8000'
|
||||
@ -0,0 +1,48 @@
|
||||
services:
|
||||
elasticsearch:
|
||||
image: elasticsearch:7.16.1
|
||||
container_name: es
|
||||
environment:
|
||||
discovery.type: single-node
|
||||
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
|
||||
ports:
|
||||
- "9200:9200"
|
||||
- "9300:9300"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
networks:
|
||||
- elastic
|
||||
logstash:
|
||||
image: logstash:7.16.1
|
||||
container_name: log
|
||||
environment:
|
||||
discovery.seed_hosts: logstash
|
||||
LS_JAVA_OPTS: "-Xms512m -Xmx512m"
|
||||
volumes:
|
||||
- ./logstash/pipeline/logstash-nginx.config:/usr/share/logstash/pipeline/logstash-nginx.config
|
||||
- ./logstash/nginx.log:/home/nginx.log
|
||||
ports:
|
||||
- "5000:5000/tcp"
|
||||
- "5000:5000/udp"
|
||||
- "5044:5044"
|
||||
- "9600:9600"
|
||||
depends_on:
|
||||
- elasticsearch
|
||||
networks:
|
||||
- elastic
|
||||
command: logstash -f /usr/share/logstash/pipeline/logstash-nginx.config
|
||||
kibana:
|
||||
image: kibana:7.16.1
|
||||
container_name: kib
|
||||
ports:
|
||||
- "5601:5601"
|
||||
depends_on:
|
||||
- elasticsearch
|
||||
networks:
|
||||
- elastic
|
||||
networks:
|
||||
elastic:
|
||||
driver: bridge
|
||||
@ -0,0 +1,11 @@
|
||||
services:
|
||||
api:
|
||||
build:
|
||||
context: .
|
||||
target: builder
|
||||
container_name: fastapi-application
|
||||
environment:
|
||||
PORT: 8000
|
||||
ports:
|
||||
- '8000:8000'
|
||||
restart: "no"
|
||||
@ -0,0 +1,10 @@
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: app
|
||||
target: builder
|
||||
# flask requires SIGINT to stop gracefully
|
||||
# (default stop signal from Compose is SIGTERM)
|
||||
stop_signal: SIGINT
|
||||
ports:
|
||||
- '8000:8000'
|
||||
@ -0,0 +1,18 @@
|
||||
services:
|
||||
redis:
|
||||
image: redislabs/redismod
|
||||
ports:
|
||||
- '6379:6379'
|
||||
web:
|
||||
build:
|
||||
context: .
|
||||
target: builder
|
||||
# flask requires SIGINT to stop gracefully
|
||||
# (default stop signal from Compose is SIGTERM)
|
||||
stop_signal: SIGINT
|
||||
ports:
|
||||
- '8000:8000'
|
||||
volumes:
|
||||
- .:/code
|
||||
depends_on:
|
||||
- redis
|
||||
@ -0,0 +1,31 @@
|
||||
services:
|
||||
gitea:
|
||||
image: gitea/gitea:latest
|
||||
environment:
|
||||
- DB_TYPE=postgres
|
||||
- DB_HOST=db:5432
|
||||
- DB_NAME=gitea
|
||||
- DB_USER=gitea
|
||||
- DB_PASSWD=gitea
|
||||
restart: always
|
||||
volumes:
|
||||
- git_data:/data
|
||||
ports:
|
||||
- 3000:3000
|
||||
db:
|
||||
image: postgres:alpine
|
||||
environment:
|
||||
- POSTGRES_USER=gitea
|
||||
- POSTGRES_PASSWORD=gitea
|
||||
- POSTGRES_DB=gitea
|
||||
restart: always
|
||||
volumes:
|
||||
- db_data:/var/lib/postgresql/data
|
||||
expose:
|
||||
- 5432
|
||||
volumes:
|
||||
db_data:
|
||||
git_data:
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
services:
|
||||
minecraft:
|
||||
image: itzg/minecraft-server
|
||||
ports:
|
||||
- "25565:25565"
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1.5G
|
||||
volumes:
|
||||
- "~/minecraft_data:/data"
|
||||
@ -0,0 +1,27 @@
|
||||
services:
|
||||
nc:
|
||||
image: nextcloud:apache
|
||||
environment:
|
||||
- POSTGRES_HOST=db
|
||||
- POSTGRES_PASSWORD=nextcloud
|
||||
- POSTGRES_DB=nextcloud
|
||||
- POSTGRES_USER=nextcloud
|
||||
ports:
|
||||
- 80:80
|
||||
restart: always
|
||||
volumes:
|
||||
- nc_data:/var/www/html
|
||||
db:
|
||||
image: postgres:alpine
|
||||
environment:
|
||||
- POSTGRES_PASSWORD=nextcloud
|
||||
- POSTGRES_DB=nextcloud
|
||||
- POSTGRES_USER=nextcloud
|
||||
restart: always
|
||||
volumes:
|
||||
- db_data:/var/lib/postgresql/data
|
||||
expose:
|
||||
- 5432
|
||||
volumes:
|
||||
db_data:
|
||||
nc_data:
|
||||
@ -0,0 +1,45 @@
|
||||
services:
|
||||
nc:
|
||||
image: nextcloud:apache
|
||||
restart: always
|
||||
ports:
|
||||
- 80:80
|
||||
volumes:
|
||||
- nc_data:/var/www/html
|
||||
networks:
|
||||
- redisnet
|
||||
- dbnet
|
||||
environment:
|
||||
- REDIS_HOST=redis
|
||||
- MYSQL_HOST=db
|
||||
- MYSQL_DATABASE=nextcloud
|
||||
- MYSQL_USER=nextcloud
|
||||
- MYSQL_PASSWORD=nextcloud
|
||||
redis:
|
||||
image: redis:alpine
|
||||
restart: always
|
||||
networks:
|
||||
- redisnet
|
||||
expose:
|
||||
- 6379
|
||||
db:
|
||||
image: mariadb:10.5
|
||||
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
|
||||
restart: always
|
||||
volumes:
|
||||
- db_data:/var/lib/mysql
|
||||
networks:
|
||||
- dbnet
|
||||
environment:
|
||||
- MYSQL_DATABASE=nextcloud
|
||||
- MYSQL_USER=nextcloud
|
||||
- MYSQL_ROOT_PASSWORD=nextcloud
|
||||
- MYSQL_PASSWORD=nextcloud
|
||||
expose:
|
||||
- 3306
|
||||
volumes:
|
||||
db_data:
|
||||
nc_data:
|
||||
networks:
|
||||
dbnet:
|
||||
redisnet:
|
||||
@ -0,0 +1,46 @@
|
||||
services:
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
restart: always
|
||||
secrets:
|
||||
- db-password
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
- ASPNETCORE_URLS=http://+:8000
|
||||
|
||||
db:
|
||||
# We use a mariadb image which supports both amd64 & arm64 architecture
|
||||
image: mariadb:10-focal
|
||||
# If you really want to use MySQL, uncomment the following line
|
||||
#image: mysql:8
|
||||
command: '--default-authentication-plugin=mysql_native_password'
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'mysqladmin ping -h 127.0.0.1 --password="$$(cat /run/secrets/db-password)" --silent']
|
||||
interval: 3s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
environment:
|
||||
- MYSQL_DATABASE=example
|
||||
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db-password
|
||||
|
||||
proxy:
|
||||
build: proxy
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
@ -0,0 +1,29 @@
|
||||
services:
|
||||
web:
|
||||
image: nginx
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/tmp/nginx.conf
|
||||
environment:
|
||||
- FLASK_SERVER_ADDR=backend:9091
|
||||
command: /bin/bash -c "envsubst < /tmp/nginx.conf > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: flask
|
||||
target: builder
|
||||
# flask requires SIGINT to stop gracefully
|
||||
# (default stop signal from Compose is SIGTERM)
|
||||
stop_signal: SIGINT
|
||||
environment:
|
||||
- FLASK_SERVER_PORT=9091
|
||||
volumes:
|
||||
- ./flask:/src
|
||||
depends_on:
|
||||
- mongo
|
||||
|
||||
mongo:
|
||||
image: mongo
|
||||
@ -0,0 +1,62 @@
|
||||
services:
|
||||
db:
|
||||
# We use a mariadb image which supports both amd64 & arm64 architecture
|
||||
image: mariadb:10-focal
|
||||
# If you really want to use MySQL, uncomment the following line
|
||||
#image: mysql:8
|
||||
command: '--default-authentication-plugin=mysql_native_password'
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'mysqladmin ping -h 127.0.0.1 --password="$$(cat /run/secrets/db-password)" --silent']
|
||||
interval: 3s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
networks:
|
||||
- backnet
|
||||
environment:
|
||||
- MYSQL_DATABASE=example
|
||||
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 3306
|
||||
- 33060
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: builder
|
||||
restart: always
|
||||
secrets:
|
||||
- db-password
|
||||
ports:
|
||||
- 8000:8000
|
||||
networks:
|
||||
- backnet
|
||||
- frontnet
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
proxy:
|
||||
build: proxy
|
||||
restart: always
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- backend
|
||||
networks:
|
||||
- frontnet
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
|
||||
networks:
|
||||
backnet:
|
||||
frontnet:
|
||||
@ -0,0 +1,17 @@
|
||||
services:
|
||||
proxy:
|
||||
image: nginx
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ./proxy/nginx.conf
|
||||
target: /etc/nginx/conf.d/default.conf
|
||||
read_only: true
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: builder
|
||||
@ -0,0 +1,51 @@
|
||||
services:
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: builder
|
||||
secrets:
|
||||
- db-password
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
db:
|
||||
# We use a mariadb image which supports both amd64 & arm64 architecture
|
||||
image: mariadb:10-focal
|
||||
# If you really want to use MySQL, uncomment the following line
|
||||
#image: mysql:8
|
||||
command: '--default-authentication-plugin=mysql_native_password'
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'mysqladmin ping -h 127.0.0.1 --password="$$(cat /run/secrets/db-password)" --silent']
|
||||
interval: 3s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
environment:
|
||||
- MYSQL_DATABASE=example
|
||||
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 3306
|
||||
|
||||
proxy:
|
||||
image: nginx
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ./proxy/nginx.conf
|
||||
target: /etc/nginx/conf.d/default.conf
|
||||
read_only: true
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
@ -0,0 +1,48 @@
|
||||
services:
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: builder
|
||||
secrets:
|
||||
- db-password
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
db:
|
||||
image: postgres
|
||||
restart: always
|
||||
user: postgres
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
environment:
|
||||
- POSTGRES_DB=example
|
||||
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||
expose:
|
||||
- 5432
|
||||
healthcheck:
|
||||
test: [ "CMD", "pg_isready" ]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
proxy:
|
||||
image: nginx
|
||||
volumes:
|
||||
- type: bind
|
||||
source: ./proxy/nginx.conf
|
||||
target: /etc/nginx/conf.d/default.conf
|
||||
read_only: true
|
||||
ports:
|
||||
- 80:80
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
@ -0,0 +1,27 @@
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: 'redislabs/redismod'
|
||||
ports:
|
||||
- '6379:6379'
|
||||
web1:
|
||||
restart: on-failure
|
||||
build: ./web
|
||||
hostname: web1
|
||||
ports:
|
||||
- '81:5000'
|
||||
web2:
|
||||
restart: on-failure
|
||||
build: ./web
|
||||
hostname: web2
|
||||
ports:
|
||||
- '82:5000'
|
||||
nginx:
|
||||
build: ./nginx
|
||||
ports:
|
||||
- '80:80'
|
||||
depends_on:
|
||||
- web1
|
||||
- web2
|
||||
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
services:
|
||||
nginx-proxy:
|
||||
build: nginx
|
||||
restart: always
|
||||
volumes:
|
||||
- ./nginx/default.conf:/tmp/default.conf
|
||||
environment:
|
||||
- FLASK_SERVER_ADDR=flask-app:8000
|
||||
ports:
|
||||
- "80:80"
|
||||
depends_on:
|
||||
- flask-app
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl --silent --fail localhost:80/health-check || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
command: /app/start.sh
|
||||
flask-app:
|
||||
build: flask
|
||||
restart: always
|
||||
ports:
|
||||
- '8000:8000'
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl --silent --fail localhost:8000/flask-health-check || exit 1"]
|
||||
interval: 10s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
command: gunicorn -w 3 -t 60 -b 0.0.0.0:8000 app:app
|
||||
@ -0,0 +1,55 @@
|
||||
version: '3.7'
|
||||
services:
|
||||
cloudflared:
|
||||
image: visibilityspots/cloudflared
|
||||
container_name: cloudflared
|
||||
ports:
|
||||
- "5054:5054/tcp"
|
||||
- "5054:5054/udp"
|
||||
environment:
|
||||
- TZ=${TIMEZONE}
|
||||
- PORT=5054
|
||||
- ADDRESS=0.0.0.0
|
||||
restart: always
|
||||
networks:
|
||||
dns-net:
|
||||
ipv4_address: 172.20.0.2
|
||||
|
||||
pihole:
|
||||
container_name: pihole
|
||||
image: pihole/pihole:latest
|
||||
ports:
|
||||
- "53:53/tcp"
|
||||
- "53:53/udp"
|
||||
- "67:67/udp"
|
||||
- "8080:80/tcp"
|
||||
- "8443:443/tcp"
|
||||
environment:
|
||||
- TZ=${TIMEZONE}
|
||||
- PIHOLE_DNS_=172.20.0.2#5054;1.1.1.1 # referencing by name results in "Invalid IP detected in PIHOLE_DNS_: cloudflared#5054"
|
||||
- WEBPASSWORD=${PIHOLE_PW}
|
||||
- REV_SERVER=true
|
||||
- REV_SERVER_TARGET=${PIHOLE_ROUTER_IP}
|
||||
- REV_SERVER_DOMAIN=${PIHOLE_NETWORK_DOMAIN}
|
||||
- REV_SERVER_CIDR=${PIHOLE_REVERSE_DNS}
|
||||
- ServerIP=${PIHOLE_HOST_IP}
|
||||
- ServerIPv6=${PIHOLE_HOST_IPV6}
|
||||
#dns:
|
||||
#- 127.0.0.1 # "Sets your container's resolve settings to localhost so it can resolve DHCP hostnames [...]" - github.com/pi-hole/docker-pi-hole
|
||||
#- 1.1.1.1 # Backup server
|
||||
volumes: # store your data between container upgrades
|
||||
- "/etc/pihole/:/etc/pihole/"
|
||||
- "/etc/dnsmasq.d/:/etc/dnsmasq.d/"
|
||||
cap_add:
|
||||
- NET_ADMIN # Recommended but not required (DHCP needs NET_ADMIN) https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
|
||||
depends_on:
|
||||
- "cloudflared"
|
||||
restart: always
|
||||
networks:
|
||||
- dns-net
|
||||
|
||||
networks:
|
||||
dns-net:
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.20.0.0/24
|
||||
@ -0,0 +1,10 @@
|
||||
services:
|
||||
plex:
|
||||
image: linuxserver/plex
|
||||
container_name: plex
|
||||
network_mode: host
|
||||
environment:
|
||||
- VERSION=docker
|
||||
restart: always
|
||||
volumes:
|
||||
- ${PLEX_MEDIA_PATH}:/media/
|
||||
@ -0,0 +1,14 @@
|
||||
services:
|
||||
portainer:
|
||||
image: portainer/portainer-ce:alpine
|
||||
container_name: portainer
|
||||
command: -H unix:///var/run/docker.sock
|
||||
ports:
|
||||
- "9000:9000"
|
||||
volumes:
|
||||
- "/var/run/docker.sock:/var/run/docker.sock"
|
||||
- "portainer_data:/data"
|
||||
restart: always
|
||||
|
||||
volumes:
|
||||
portainer_data:
|
||||
@ -0,0 +1,21 @@
|
||||
services:
|
||||
postgres:
|
||||
container_name: postgres
|
||||
image: postgres:latest
|
||||
environment:
|
||||
- POSTGRES_USER=${POSTGRES_USER}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PW}
|
||||
- POSTGRES_DB=${POSTGRES_DB} #optional (specify default database instead of $POSTGRES_DB)
|
||||
ports:
|
||||
- "5432:5432"
|
||||
restart: always
|
||||
|
||||
pgadmin:
|
||||
container_name: pgadmin
|
||||
image: dpage/pgadmin4:latest
|
||||
environment:
|
||||
- PGADMIN_DEFAULT_EMAIL=${PGADMIN_MAIL}
|
||||
- PGADMIN_DEFAULT_PASSWORD=${PGADMIN_PW}
|
||||
ports:
|
||||
- "5050:80"
|
||||
restart: always
|
||||
@ -0,0 +1,25 @@
|
||||
services:
|
||||
prometheus:
|
||||
image: prom/prometheus
|
||||
container_name: prometheus
|
||||
command:
|
||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||
ports:
|
||||
- 9090:9090
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./prometheus:/etc/prometheus
|
||||
- prom_data:/prometheus
|
||||
grafana:
|
||||
image: grafana/grafana
|
||||
container_name: grafana
|
||||
ports:
|
||||
- 3000:3000
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_USER=admin
|
||||
- GF_SECURITY_ADMIN_PASSWORD=grafana
|
||||
volumes:
|
||||
- ./grafana:/etc/grafana/provisioning/datasources
|
||||
volumes:
|
||||
prom_data:
|
||||
@ -0,0 +1,47 @@
|
||||
services:
|
||||
frontend:
|
||||
build:
|
||||
context: frontend
|
||||
target: development
|
||||
ports:
|
||||
- 3000:3000
|
||||
stdin_open: true
|
||||
volumes:
|
||||
- ./frontend:/usr/src/app
|
||||
- /usr/src/app/node_modules
|
||||
restart: always
|
||||
networks:
|
||||
- react-express
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
backend:
|
||||
restart: always
|
||||
build:
|
||||
context: backend
|
||||
target: development
|
||||
volumes:
|
||||
- ./backend:/usr/src/app
|
||||
- /usr/src/app/node_modules
|
||||
depends_on:
|
||||
- mongo
|
||||
networks:
|
||||
- express-mongo
|
||||
- react-express
|
||||
expose:
|
||||
- 3000
|
||||
mongo:
|
||||
restart: always
|
||||
image: mongo:4.2.0
|
||||
volumes:
|
||||
- mongo_data:/data/db
|
||||
networks:
|
||||
- express-mongo
|
||||
expose:
|
||||
- 27017
|
||||
networks:
|
||||
react-express:
|
||||
express-mongo:
|
||||
|
||||
volumes:
|
||||
mongo_data:
|
||||
@ -0,0 +1,68 @@
|
||||
services:
|
||||
backend:
|
||||
build:
|
||||
args:
|
||||
- NODE_ENV=development
|
||||
context: backend
|
||||
target: development
|
||||
command: npm run start-watch
|
||||
environment:
|
||||
- DATABASE_DB=example
|
||||
- DATABASE_USER=root
|
||||
- DATABASE_PASSWORD=/run/secrets/db-password
|
||||
- DATABASE_HOST=db
|
||||
- NODE_ENV=development
|
||||
ports:
|
||||
- 80:80
|
||||
- 9229:9229
|
||||
- 9230:9230
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- ./backend/src:/code/src:ro
|
||||
- ./backend/package.json:/code/package.json
|
||||
- ./backend/package-lock.json:/code/package-lock.json
|
||||
- back-notused:/opt/app/node_modules
|
||||
networks:
|
||||
- public
|
||||
- private
|
||||
depends_on:
|
||||
- db
|
||||
db:
|
||||
# We use a mariadb image which supports both amd64 & arm64 architecture
|
||||
image: mariadb:10.6.4-focal
|
||||
# If you really want to use MySQL, uncomment the following line
|
||||
#image: mysql:8.0.27
|
||||
command: '--default-authentication-plugin=mysql_native_password'
|
||||
restart: always
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
networks:
|
||||
- private
|
||||
environment:
|
||||
- MYSQL_DATABASE=example
|
||||
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db-password
|
||||
frontend:
|
||||
build:
|
||||
context: frontend
|
||||
target: development
|
||||
ports:
|
||||
- 3000:3000
|
||||
volumes:
|
||||
- ./frontend/src:/code/src
|
||||
- /code/node_modules
|
||||
networks:
|
||||
- public
|
||||
depends_on:
|
||||
- backend
|
||||
networks:
|
||||
public:
|
||||
private:
|
||||
volumes:
|
||||
back-notused:
|
||||
db-data:
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
@ -0,0 +1,58 @@
|
||||
services:
|
||||
backend:
|
||||
build: backend
|
||||
restart: always
|
||||
secrets:
|
||||
- db-password
|
||||
environment:
|
||||
MYSQL_HOST: db
|
||||
networks:
|
||||
- react-spring
|
||||
- spring-mysql
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
db:
|
||||
# We use a mariadb image which supports both amd64 & arm64 architecture
|
||||
image: mariadb:10.6.4-focal
|
||||
# If you really want to use MySQL, uncomment the following line
|
||||
#image: mysql:8.0.19
|
||||
environment:
|
||||
- MYSQL_DATABASE=example
|
||||
- MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db-password
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
|
||||
interval: 3s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
secrets:
|
||||
- db-password
|
||||
volumes:
|
||||
- db-data:/var/lib/mysql
|
||||
networks:
|
||||
- spring-mysql
|
||||
frontend:
|
||||
build:
|
||||
context: frontend
|
||||
target: development
|
||||
ports:
|
||||
- 3000:3000
|
||||
volumes:
|
||||
- ./frontend/src:/code/src
|
||||
- /project/node_modules
|
||||
networks:
|
||||
- react-spring
|
||||
depends_on:
|
||||
- backend
|
||||
expose:
|
||||
- 3306
|
||||
- 33060
|
||||
volumes:
|
||||
db-data: {}
|
||||
secrets:
|
||||
db-password:
|
||||
file: db/password.txt
|
||||
networks:
|
||||
react-spring: {}
|
||||
spring-mysql: {}
|
||||
@ -0,0 +1,7 @@
|
||||
services:
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
container_name: frontend
|
||||
ports:
|
||||
- "80:80"
|
||||
@ -0,0 +1,52 @@
|
||||
name: react-rust-postgres
|
||||
services:
|
||||
frontend:
|
||||
build:
|
||||
context: frontend
|
||||
target: development
|
||||
networks:
|
||||
- client-side
|
||||
ports:
|
||||
- 3000:3000
|
||||
volumes:
|
||||
- ./frontend/src:/code/src:ro
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: backend
|
||||
target: development
|
||||
environment:
|
||||
- ADDRESS=0.0.0.0:8000
|
||||
- RUST_LOG=debug
|
||||
- PG_DBNAME=postgres
|
||||
- PG_HOST=db
|
||||
- PG_USER=postgres
|
||||
- PG_PASSWORD=mysecretpassword
|
||||
networks:
|
||||
- client-side
|
||||
- server-side
|
||||
volumes:
|
||||
- ./backend/src:/code/src
|
||||
- backend-cache:/code/target
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
db:
|
||||
image: postgres:12-alpine
|
||||
restart: always
|
||||
environment:
|
||||
- POSTGRES_PASSWORD=mysecretpassword
|
||||
networks:
|
||||
- server-side
|
||||
ports:
|
||||
- 5432:5432
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
|
||||
networks:
|
||||
client-side: {}
|
||||
server-side: {}
|
||||
|
||||
volumes:
|
||||
backend-cache: {}
|
||||
db-data: {}
|
||||
40
Tests/Fixtures/real-yaml/bitnami-apache-chart.yaml
Normal file
40
Tests/Fixtures/real-yaml/bitnami-apache-chart.yaml
Normal file
@ -0,0 +1,40 @@
|
||||
# Copyright Broadcom, Inc. All Rights Reserved.
|
||||
# SPDX-License-Identifier: APACHE-2.0
|
||||
|
||||
annotations:
|
||||
images: |
|
||||
- name: apache
|
||||
image: docker.io/bitnami/apache:2.4.65-debian-12-r2
|
||||
- name: apache-exporter
|
||||
image: docker.io/bitnami/apache-exporter:1.0.10-debian-12-r55
|
||||
- name: git
|
||||
image: docker.io/bitnami/git:2.51.0-debian-12-r0
|
||||
licenses: Apache-2.0
|
||||
tanzuCategory: service
|
||||
apiVersion: v2
|
||||
appVersion: 2.4.65
|
||||
dependencies:
|
||||
- name: common
|
||||
repository: oci://registry-1.docker.io/bitnamicharts
|
||||
tags:
|
||||
- bitnami-common
|
||||
version: 2.x.x
|
||||
description: Apache HTTP Server is an open-source HTTP server. The goal of this project
|
||||
is to provide a secure, efficient and extensible server that provides HTTP services
|
||||
in sync with the current HTTP standards.
|
||||
home: https://bitnami.com
|
||||
icon: https://dyltqmyl993wv.cloudfront.net/assets/stacks/apache/img/apache-stack-220x234.png
|
||||
keywords:
|
||||
- apache
|
||||
- http
|
||||
- https
|
||||
- www
|
||||
- web
|
||||
- reverse proxy
|
||||
maintainers:
|
||||
- name: Broadcom, Inc. All Rights Reserved.
|
||||
url: https://github.com/bitnami/charts
|
||||
name: apache
|
||||
sources:
|
||||
- https://github.com/bitnami/charts/tree/main/bitnami/apache
|
||||
version: 11.4.30
|
||||
820
Tests/Fixtures/real-yaml/bitnami-apache-values.yaml
Normal file
820
Tests/Fixtures/real-yaml/bitnami-apache-values.yaml
Normal file
@ -0,0 +1,820 @@
|
||||
# Copyright Broadcom, Inc. All Rights Reserved.
|
||||
# SPDX-License-Identifier: APACHE-2.0
|
||||
|
||||
## @section Global parameters
|
||||
## Global Docker image parameters
|
||||
## Please, note that this will override the image parameters, including dependencies, configured to use the global value
|
||||
## Current available global Docker image parameters: imageRegistry, imagePullSecrets and storageClass
|
||||
|
||||
## @param global.imageRegistry Global Docker image registry
|
||||
## @param global.imagePullSecrets Global Docker registry secret names as an array
|
||||
## @param global.defaultStorageClass Global default StorageClass for Persistent Volume(s)
|
||||
## @param global.storageClass DEPRECATED: use global.defaultStorageClass instead
|
||||
##
|
||||
global:
|
||||
imageRegistry: ""
|
||||
## E.g.
|
||||
## imagePullSecrets:
|
||||
## - myRegistryKeySecretName
|
||||
##
|
||||
imagePullSecrets: []
|
||||
defaultStorageClass: ""
|
||||
storageClass: ""
|
||||
## Compatibility adaptations for Kubernetes platforms
|
||||
##
|
||||
compatibility:
|
||||
## Compatibility adaptations for Openshift
|
||||
##
|
||||
openshift:
|
||||
## @param global.compatibility.openshift.adaptSecurityContext Adapt the securityContext sections of the deployment to make them compatible with Openshift restricted-v2 SCC: remove runAsUser, runAsGroup and fsGroup and let the platform use their allowed default IDs. Possible values: auto (apply if the detected running cluster is Openshift), force (perform the adaptation always), disabled (do not perform adaptation)
|
||||
##
|
||||
adaptSecurityContext: auto
|
||||
## Security parameters
|
||||
##
|
||||
security:
|
||||
## @param global.security.allowInsecureImages By default, this chart verifies that the original container images that were designed, tested, and validated are used. This option makes the chart skip the verification step and proceed
|
||||
##
|
||||
allowInsecureImages: false
|
||||
|
||||
## @section Common parameters
|
||||
|
||||
## @param kubeVersion Override Kubernetes version
|
||||
##
|
||||
kubeVersion: ""
|
||||
## @param nameOverride String to partially override common.names.fullname
|
||||
##
|
||||
nameOverride: ""
|
||||
## @param fullnameOverride String to fully override common.names.fullname
|
||||
##
|
||||
fullnameOverride: ""
|
||||
## @param commonLabels Labels to add to all deployed objects
|
||||
##
|
||||
commonLabels: {}
|
||||
## @param commonAnnotations Annotations to add to all deployed objects
|
||||
##
|
||||
commonAnnotations: {}
|
||||
## @param extraDeploy Array of extra objects to deploy with the release
|
||||
##
|
||||
extraDeploy: []
|
||||
## @section Apache parameters
|
||||
|
||||
## Bitnami Apache image
|
||||
## ref: https://hub.docker.com/r/bitnami/apache/tags/
|
||||
## @param image.registry [default: REGISTRY_NAME] Apache image registry
|
||||
## @param image.repository [default: REPOSITORY_NAME/apache] Apache image repository
|
||||
## @skip image.tag Apache image tag (immutable tags are recommended)
|
||||
## @param image.digest Apache image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag
|
||||
## @param image.pullPolicy Apache image pull policy
|
||||
## @param image.pullSecrets Apache image pull secrets
|
||||
## @param image.debug Enable image debug mode
|
||||
##
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: bitnami/apache
|
||||
tag: 2.4.65-debian-12-r2
|
||||
digest: ""
|
||||
## Specify a imagePullPolicy
|
||||
## ref: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-images
|
||||
##
|
||||
pullPolicy: IfNotPresent
|
||||
## Optionally specify an array of imagePullSecrets.
|
||||
## Secrets must be manually created in the namespace.
|
||||
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
|
||||
## e.g:
|
||||
## pullSecrets:
|
||||
## - myRegistryKeySecretName
|
||||
##
|
||||
pullSecrets: []
|
||||
## Enable debug mode
|
||||
##
|
||||
debug: false
|
||||
## Bitnami Git image version
|
||||
## ref: https://hub.docker.com/r/bitnami/git/tags/
|
||||
## @param git.registry [default: REGISTRY_NAME] Git image registry
|
||||
## @param git.repository [default: REPOSITORY_NAME/git] Git image name
|
||||
## @skip git.tag Git image tag (immutable tags are recommended)
|
||||
## @param git.digest Git image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag
|
||||
## @param git.pullPolicy Git image pull policy
|
||||
## @param git.pullSecrets Specify docker-registry secret names as an array
|
||||
##
|
||||
git:
|
||||
registry: docker.io
|
||||
repository: bitnami/git
|
||||
tag: 2.51.0-debian-12-r0
|
||||
digest: ""
|
||||
pullPolicy: IfNotPresent
|
||||
## Optionally specify an array of imagePullSecrets.
|
||||
## Secrets must be manually created in the namespace.
|
||||
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
|
||||
## e.g:
|
||||
## pullSecrets:
|
||||
## - myRegistryKeySecretName
|
||||
##
|
||||
pullSecrets: []
|
||||
## @param replicaCount Number of replicas of the Apache deployment
|
||||
##
|
||||
replicaCount: 1
|
||||
## @param revisionHistoryLimit The number of old history to retain to allow rollback
|
||||
##
|
||||
revisionHistoryLimit: 10
|
||||
## @param podAffinityPreset Pod affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard`
|
||||
## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity
|
||||
##
|
||||
podAffinityPreset: ""
|
||||
## @param podAntiAffinityPreset Pod anti-affinity preset. Ignored if `affinity` is set. Allowed values: `soft` or `hard`
|
||||
## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity
|
||||
##
|
||||
podAntiAffinityPreset: soft
|
||||
## Node affinity preset
|
||||
## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity
|
||||
##
|
||||
nodeAffinityPreset:
|
||||
## @param nodeAffinityPreset.type Node affinity preset type. Ignored if `affinity` is set. Allowed values: `soft` or `hard`
|
||||
##
|
||||
type: ""
|
||||
## @param nodeAffinityPreset.key Node label key to match. Ignored if `affinity` is set
|
||||
##
|
||||
key: ""
|
||||
## @param nodeAffinityPreset.values Node label values to match. Ignored if `affinity` is set
|
||||
## E.g.
|
||||
## values:
|
||||
## - e2e-az1
|
||||
## - e2e-az2
|
||||
##
|
||||
values: []
|
||||
## @param affinity Affinity for pod assignment
|
||||
## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
|
||||
## NOTE: podAffinityPreset, podAntiAffinityPreset, and nodeAffinityPreset will be ignored when it's set
|
||||
##
|
||||
affinity: {}
|
||||
## @param nodeSelector Node labels for pod assignment
|
||||
## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/
|
||||
##
|
||||
nodeSelector: {}
|
||||
## @param tolerations Tolerations for pod assignment
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
|
||||
##
|
||||
tolerations: []
|
||||
## @param topologySpreadConstraints Topology Spread Constraints for pod assignment spread across your cluster among failure-domains. Evaluated as a template
|
||||
## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods
|
||||
##
|
||||
topologySpreadConstraints: []
|
||||
## @param extraPodSpec Optionally specify extra PodSpec
|
||||
##
|
||||
extraPodSpec: {}
|
||||
## Get the server static content from a git repository
|
||||
## @param cloneHtdocsFromGit.enabled Get the server static content from a git repository
|
||||
## @param cloneHtdocsFromGit.repository Repository to clone static content from
|
||||
## @param cloneHtdocsFromGit.branch Branch inside the git repository
|
||||
## @param cloneHtdocsFromGit.enableAutoRefresh Enables an automatic git pull with a sidecar container
|
||||
## @param cloneHtdocsFromGit.interval Interval for sidecar container pull from the repository
|
||||
## @param cloneHtdocsFromGit.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if cloneHtdocsFromGit.resources is set (cloneHtdocsFromGit.resources is recommended for production).
|
||||
## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15
|
||||
## @param cloneHtdocsFromGit.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads)
|
||||
## Example:
|
||||
## resources:
|
||||
## requests:
|
||||
## cpu: 2
|
||||
## memory: 512Mi
|
||||
## limits:
|
||||
## cpu: 3
|
||||
## memory: 1024Mi
|
||||
## @param cloneHtdocsFromGit.extraVolumeMounts Add extra volume mounts for the GIT containers
|
||||
##
|
||||
cloneHtdocsFromGit:
|
||||
enabled: false
|
||||
repository: ""
|
||||
branch: ""
|
||||
enableAutoRefresh: true
|
||||
interval: 60
|
||||
resourcesPreset: "nano"
|
||||
resources: {}
|
||||
## Useful to mount keys to connect through ssh. (normally used with extraVolumes)
|
||||
## E.g:
|
||||
## extraVolumeMounts:
|
||||
## - name: ssh-dir
|
||||
## mountPath: /root/.ssh/
|
||||
##
|
||||
extraVolumeMounts: []
|
||||
## @param htdocsConfigMap Name of a config map with the server static content
|
||||
##
|
||||
htdocsConfigMap: ""
|
||||
## @param htdocsPVC Name of a PVC with the server static content
|
||||
##
|
||||
htdocsPVC: ""
|
||||
## @param vhostsConfigMap Name of a config map with the virtual hosts content
|
||||
##
|
||||
vhostsConfigMap: ""
|
||||
## @param httpdConfConfigMap Name of a config map with the httpd.conf file contents
|
||||
##
|
||||
httpdConfConfigMap: ""
|
||||
## @param podLabels Extra labels for Apache pods
|
||||
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
##
|
||||
podLabels: {}
|
||||
## @param podAnnotations Pod annotations
|
||||
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
|
||||
##
|
||||
podAnnotations: {}
|
||||
## @param automountServiceAccountToken Mount Service Account token in pod
|
||||
##
|
||||
automountServiceAccountToken: false
|
||||
## @param hostAliases [array] Add deployment host aliases
|
||||
## https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/
|
||||
##
|
||||
hostAliases:
|
||||
## Necessary for apache-exporter to work
|
||||
##
|
||||
- ip: "127.0.0.1"
|
||||
hostnames:
|
||||
- "status.localhost"
|
||||
## @param priorityClassName Apache Server pods' priorityClassName
|
||||
##
|
||||
priorityClassName: ""
|
||||
## @param schedulerName Name of the k8s scheduler (other than default)
|
||||
## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/
|
||||
##
|
||||
schedulerName: ""
|
||||
## Configure Pods Security Context
|
||||
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod
|
||||
## @param podSecurityContext.enabled Enabled Apache Server pods' Security Context
|
||||
## @param podSecurityContext.fsGroupChangePolicy Set filesystem group change policy
|
||||
## @param podSecurityContext.sysctls Set kernel settings using the sysctl interface
|
||||
## @param podSecurityContext.supplementalGroups Set filesystem extra groups
|
||||
## @param podSecurityContext.fsGroup Set Apache Server pod's Security Context fsGroup
|
||||
##
|
||||
podSecurityContext:
|
||||
enabled: true
|
||||
fsGroupChangePolicy: Always
|
||||
sysctls: []
|
||||
supplementalGroups: []
|
||||
fsGroup: 1001
|
||||
## Configure Container Security Context
|
||||
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod
|
||||
## @param containerSecurityContext.enabled Enabled Apache Server containers' Security Context
|
||||
## @param containerSecurityContext.seLinuxOptions [object,nullable] Set SELinux options in container
|
||||
## @param containerSecurityContext.runAsUser Set Apache Server containers' Security Context runAsUser
|
||||
## @param containerSecurityContext.runAsGroup Set Apache Server containers' Security Context runAsGroup
|
||||
## @param containerSecurityContext.runAsNonRoot Set Controller container's Security Context runAsNonRoot
|
||||
## @param containerSecurityContext.privileged Set primary container's Security Context privileged
|
||||
## @param containerSecurityContext.allowPrivilegeEscalation Set primary container's Security Context allowPrivilegeEscalation
|
||||
## @param containerSecurityContext.readOnlyRootFilesystem Set primary container's Security Context readOnlyRootFilesystem
|
||||
## @param containerSecurityContext.capabilities.drop List of capabilities to be dropped
|
||||
## @param containerSecurityContext.seccompProfile.type Set container's Security Context seccomp profile
|
||||
##
|
||||
containerSecurityContext:
|
||||
enabled: true
|
||||
seLinuxOptions: {}
|
||||
runAsUser: 1001
|
||||
runAsGroup: 1001
|
||||
runAsNonRoot: true
|
||||
privileged: false
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
seccompProfile:
|
||||
type: "RuntimeDefault"
|
||||
## @param command Override default container command (useful when using custom images)
|
||||
##
|
||||
command: []
|
||||
## @param args Override default container args (useful when using custom images)
|
||||
##
|
||||
args: []
|
||||
## @param lifecycleHooks for the Apache server container(s) to automate configuration before or after startup
|
||||
##
|
||||
lifecycleHooks: {}
|
||||
## Apache pods' resource requests and limits
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
|
||||
## We usually recommend not to specify default resources and to leave this as a conscious
|
||||
## choice for the user. This also increases chances charts run on environments with little
|
||||
## resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
## lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
## @param resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if resources is set (resources is recommended for production).
|
||||
## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15
|
||||
##
|
||||
resourcesPreset: "nano"
|
||||
## @param resources Set container requests and limits for different resources like CPU or memory (essential for production workloads)
|
||||
## Example:
|
||||
## resources:
|
||||
## requests:
|
||||
## cpu: 2
|
||||
## memory: 512Mi
|
||||
## limits:
|
||||
## cpu: 3
|
||||
## memory: 1024Mi
|
||||
##
|
||||
resources: {}
|
||||
## Configure extra options for containers' liveness and readiness probes
|
||||
## Configure extra options for Apache server containers' liveness, readiness and startup probes
|
||||
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes)
|
||||
## @param startupProbe.enabled Enable startupProbe
|
||||
## @param startupProbe.path Path to access on the HTTP server
|
||||
## @param startupProbe.port Port for startupProbe
|
||||
## @param startupProbe.initialDelaySeconds Initial delay seconds for startupProbe
|
||||
## @param startupProbe.periodSeconds Period seconds for startupProbe
|
||||
## @param startupProbe.timeoutSeconds Timeout seconds for startupProbe
|
||||
## @param startupProbe.failureThreshold Failure threshold for startupProbe
|
||||
## @param startupProbe.successThreshold Success threshold for startupProbe
|
||||
##
|
||||
startupProbe:
|
||||
enabled: false
|
||||
path: "/"
|
||||
port: http
|
||||
initialDelaySeconds: 180
|
||||
periodSeconds: 20
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
successThreshold: 1
|
||||
## @param livenessProbe.enabled Enable liveness probe
|
||||
## @param livenessProbe.port Port for livenessProbe
|
||||
## @param livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe
|
||||
## @param livenessProbe.periodSeconds Period seconds for livenessProbe
|
||||
## @param livenessProbe.timeoutSeconds Timeout seconds for livenessProbe
|
||||
## @param livenessProbe.failureThreshold Failure threshold for livenessProbe
|
||||
## @param livenessProbe.successThreshold Success threshold for livenessProbe
|
||||
##
|
||||
livenessProbe:
|
||||
enabled: true
|
||||
port: http
|
||||
initialDelaySeconds: 180
|
||||
periodSeconds: 20
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
successThreshold: 1
|
||||
## @param readinessProbe.enabled Enable readiness probe
|
||||
## @param readinessProbe.path Path to access on the HTTP server
|
||||
## @param readinessProbe.port Port for readinessProbe
|
||||
## @param readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe
|
||||
## @param readinessProbe.periodSeconds Period seconds for readinessProbe
|
||||
## @param readinessProbe.timeoutSeconds Timeout seconds for readinessProbe
|
||||
## @param readinessProbe.failureThreshold Failure threshold for readinessProbe
|
||||
## @param readinessProbe.successThreshold Success threshold for readinessProbe
|
||||
##
|
||||
readinessProbe:
|
||||
enabled: true
|
||||
path: "/"
|
||||
port: http
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
successThreshold: 1
|
||||
## @param customStartupProbe Custom liveness probe for the Web component
|
||||
##
|
||||
customStartupProbe: {}
|
||||
## @param customLivenessProbe Custom liveness probe for the Web component
|
||||
##
|
||||
customLivenessProbe: {}
|
||||
## @param customReadinessProbe Custom rediness probe for the Web component
|
||||
##
|
||||
customReadinessProbe: {}
|
||||
## @param extraVolumes Array to add extra volumes (evaluated as a template)
|
||||
##
|
||||
extraVolumes: []
|
||||
## @param extraVolumeMounts Array to add extra mounts (normally used with extraVolumes, evaluated as a template)
|
||||
##
|
||||
extraVolumeMounts: []
|
||||
## @param extraEnvVars Array to add extra environment variables
|
||||
##
|
||||
extraEnvVars: []
|
||||
## @param extraEnvVarsCM Name of existing ConfigMap containing extra env vars for Apache server nodes
|
||||
##
|
||||
extraEnvVarsCM: ""
|
||||
## @param extraEnvVarsSecret Name of existing Secret containing extra env vars for Apache server nodes
|
||||
##
|
||||
extraEnvVarsSecret: ""
|
||||
## Apache server container port
|
||||
## @param containerPorts.http Apache server HTTP container port
|
||||
## @param containerPorts.https Apache server HTTPS container port
|
||||
##
|
||||
containerPorts:
|
||||
http: 8080
|
||||
https: 8443
|
||||
## @param initContainers Add additional init containers to the Apache pods
|
||||
## Example:
|
||||
## initContainers:
|
||||
## - name: your-image-name
|
||||
## image: your-image
|
||||
## imagePullPolicy: Always
|
||||
## ports:
|
||||
## - name: portname
|
||||
## containerPort: 1234
|
||||
##
|
||||
initContainers: []
|
||||
## @param sidecars Add additional sidecar containers to the Apache pods
|
||||
## Example:
|
||||
## sidecars:
|
||||
## - name: your-image-name
|
||||
## image: your-image
|
||||
## imagePullPolicy: Always
|
||||
## ports:
|
||||
## - name: portname
|
||||
## containerPort: 1234
|
||||
##
|
||||
sidecars: []
|
||||
## @param updateStrategy.type Apache Server deployment strategy type.
|
||||
## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy
|
||||
## e.g:
|
||||
## updateStrategy:
|
||||
## type: RollingUpdate
|
||||
## rollingUpdate:
|
||||
## maxSurge: 25%
|
||||
## maxUnavailable: 25%
|
||||
##
|
||||
updateStrategy:
|
||||
type: RollingUpdate
|
||||
## @section Other Parameters
|
||||
|
||||
## Apache Pod Disruption Budget configuration
|
||||
## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/
|
||||
## @param pdb.create Enable a Pod Disruption Budget creation
|
||||
## @param pdb.minAvailable Minimum number/percentage of pods that should remain scheduled
|
||||
## @param pdb.maxUnavailable Maximum number/percentage of pods that may be made unavailable
|
||||
##
|
||||
pdb:
|
||||
create: true
|
||||
minAvailable: ""
|
||||
maxUnavailable: ""
|
||||
## Apache Autoscaling parameters
|
||||
## ref: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
|
||||
## @param autoscaling.enabled Enable Horizontal POD autoscaling for Apache
|
||||
## @param autoscaling.minReplicas Minimum number of Apache replicas
|
||||
## @param autoscaling.maxReplicas Maximum number of Apache replicas
|
||||
## @param autoscaling.targetCPU Target CPU utilization percentage
|
||||
## @param autoscaling.targetMemory Target Memory utilization percentage
|
||||
##
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 11
|
||||
targetCPU: 50
|
||||
targetMemory: 50
|
||||
## @section Traffic Exposure Parameters
|
||||
|
||||
## Apache service parameters
|
||||
##
|
||||
service:
|
||||
## @param service.type Apache Service type
|
||||
##
|
||||
type: LoadBalancer
|
||||
## @param service.ports.http Apache service HTTP port
|
||||
## @param service.ports.https Apache service HTTPS port
|
||||
##
|
||||
ports:
|
||||
http: 80
|
||||
https: 443
|
||||
## Node ports to expose
|
||||
## @param service.nodePorts.http Node port for HTTP
|
||||
## @param service.nodePorts.https Node port for HTTPS
|
||||
##
|
||||
nodePorts:
|
||||
http: ""
|
||||
https: ""
|
||||
## @param service.clusterIP Apache service Cluster IP
|
||||
## e.g.:
|
||||
## clusterIP: None
|
||||
##
|
||||
clusterIP: ""
|
||||
## @param service.loadBalancerIP Apache service Load Balancer IP
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer
|
||||
##
|
||||
loadBalancerIP: ""
|
||||
## @param service.loadBalancerSourceRanges Apache service Load Balancer sources
|
||||
## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service
|
||||
## e.g:
|
||||
## loadBalancerSourceRanges:
|
||||
## - 10.10.10.0/24
|
||||
##
|
||||
loadBalancerSourceRanges: []
|
||||
## @param service.annotations Additional custom annotations for Apache service
|
||||
## This can be used to set the LoadBalancer service type to internal only.
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer
|
||||
##
|
||||
annotations: {}
|
||||
## @param service.externalTrafficPolicy Apache service external traffic policy
|
||||
## ref https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip
|
||||
##
|
||||
externalTrafficPolicy: Cluster
|
||||
## @param service.extraPorts Extra ports to expose (normally used with the `sidecar` value)
|
||||
##
|
||||
extraPorts: []
|
||||
## @param service.sessionAffinity Session Affinity for Kubernetes service, can be "None" or "ClientIP"
|
||||
## If "ClientIP", consecutive client requests will be directed to the same mongos Pod
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
|
||||
##
|
||||
sessionAffinity: None
|
||||
## @param service.sessionAffinityConfig Additional settings for the sessionAffinity
|
||||
## sessionAffinityConfig:
|
||||
## clientIP:
|
||||
## timeoutSeconds: 300
|
||||
##
|
||||
sessionAffinityConfig: {}
|
||||
## Network Policies
|
||||
## Ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/
|
||||
##
|
||||
networkPolicy:
|
||||
## @param networkPolicy.enabled Specifies whether a NetworkPolicy should be created
|
||||
##
|
||||
enabled: true
|
||||
## @param networkPolicy.allowExternal Don't require server label for connections
|
||||
## The Policy model to apply. When set to false, only pods with the correct
|
||||
## server label will have network access to the ports server is listening
|
||||
## on. When true, server will accept connections from any source
|
||||
## (with the correct destination port).
|
||||
##
|
||||
allowExternal: true
|
||||
## @param networkPolicy.allowExternalEgress Allow the pod to access any range of port and all destinations.
|
||||
##
|
||||
allowExternalEgress: true
|
||||
## @param networkPolicy.extraIngress [array] Add extra ingress rules to the NetworkPolicy
|
||||
## e.g:
|
||||
## extraIngress:
|
||||
## - ports:
|
||||
## - port: 1234
|
||||
## from:
|
||||
## - podSelector:
|
||||
## - matchLabels:
|
||||
## - role: frontend
|
||||
## - podSelector:
|
||||
## - matchExpressions:
|
||||
## - key: role
|
||||
## operator: In
|
||||
## values:
|
||||
## - frontend
|
||||
extraIngress: []
|
||||
## @param networkPolicy.extraEgress [array] Add extra ingress rules to the NetworkPolicy (ignored if allowExternalEgress=true)
|
||||
## e.g:
|
||||
## extraEgress:
|
||||
## - ports:
|
||||
## - port: 1234
|
||||
## to:
|
||||
## - podSelector:
|
||||
## - matchLabels:
|
||||
## - role: frontend
|
||||
## - podSelector:
|
||||
## - matchExpressions:
|
||||
## - key: role
|
||||
## operator: In
|
||||
## values:
|
||||
## - frontend
|
||||
##
|
||||
extraEgress: []
|
||||
## @param networkPolicy.ingressNSMatchLabels [object] Labels to match to allow traffic from other namespaces
|
||||
## @param networkPolicy.ingressNSPodMatchLabels [object] Pod labels to match to allow traffic from other namespaces
|
||||
##
|
||||
ingressNSMatchLabels: {}
|
||||
ingressNSPodMatchLabels: {}
|
||||
## Configure the ingress resource that allows you to access the Apache installation
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/
|
||||
##
|
||||
ingress:
|
||||
## @param ingress.enabled Enable ingress record generation for Apache
|
||||
##
|
||||
enabled: false
|
||||
## @param ingress.selfSigned Create a TLS secret for this ingress record using self-signed certificates generated by Helm
|
||||
##
|
||||
selfSigned: false
|
||||
## @param ingress.pathType Ingress path type
|
||||
##
|
||||
pathType: ImplementationSpecific
|
||||
## @param ingress.apiVersion Force Ingress API version (automatically detected if not set)
|
||||
##
|
||||
apiVersion: ""
|
||||
## @param ingress.ingressClassName IngressClass that will be be used to implement the Ingress (Kubernetes 1.18+)
|
||||
## IngressClassName is used to reference the IngressClass that should be used to implement this Ingress.
|
||||
## This is supported in Kubernetes 1.18+ and required if you have more than one IngressClass marked as the default for your cluster .
|
||||
## ref: https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/
|
||||
##
|
||||
ingressClassName: ""
|
||||
## @param ingress.hostname Default host for the ingress record
|
||||
##
|
||||
hostname: example.local
|
||||
## @param ingress.path Default path for the ingress record
|
||||
## NOTE: You may need to set this to '/*' in order to use this with ALB ingress controllers
|
||||
##
|
||||
path: /
|
||||
## @param ingress.annotations Additional annotations for the Ingress resource. To enable certificate autogeneration, place here your cert-manager annotations.
|
||||
## For a full list of possible ingress annotations, please see
|
||||
## ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/nginx-configuration/annotations.md
|
||||
## Use this parameter to set the required annotations for cert-manager, see
|
||||
## ref: https://cert-manager.io/docs/usage/ingress/#supported-annotations
|
||||
##
|
||||
## e.g:
|
||||
## annotations:
|
||||
## kubernetes.io/ingress.class: nginx
|
||||
## cert-manager.io/cluster-issuer: cluster-issuer-name
|
||||
##
|
||||
annotations: {}
|
||||
## @param ingress.tls Enable TLS configuration for the host defined at `ingress.hostname` parameter
|
||||
## TLS certificates will be retrieved from a TLS secret with name: `{{- printf "%s-tls" .Values.ingress.hostname }}`
|
||||
## You can:
|
||||
## - Use the `ingress.secrets` parameter to create this TLS secret
|
||||
## - Rely on cert-manager to create it by setting the corresponding annotations
|
||||
## - Rely on Helm to create self-signed certificates by setting `ingress.selfSigned=true`
|
||||
##
|
||||
tls: false
|
||||
## @param ingress.extraHosts An array with additional hostname(s) to be covered with the ingress record
|
||||
## e.g:
|
||||
## extraHosts:
|
||||
## - name: apache.local
|
||||
## path: /
|
||||
##
|
||||
extraHosts: []
|
||||
## @param ingress.extraPaths An array with additional arbitrary paths that may need to be added to the ingress under the main host
|
||||
## e.g:
|
||||
## extraPaths:
|
||||
## - path: /*
|
||||
## backend:
|
||||
## serviceName: ssl-redirect
|
||||
## servicePort: use-annotation
|
||||
##
|
||||
extraPaths: []
|
||||
## @param ingress.extraTls TLS configuration for additional hostname(s) to be covered with this ingress record
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls
|
||||
## e.g:
|
||||
## extraTls:
|
||||
## - hosts:
|
||||
## - apache.local
|
||||
## secretName: apache.local-tls
|
||||
##
|
||||
extraTls: []
|
||||
## @param ingress.secrets Custom TLS certificates as secrets
|
||||
## NOTE: 'key' and 'certificate' are expected in PEM format
|
||||
## NOTE: 'name' should line up with a 'secretName' set further up
|
||||
## If it is not set and you're using cert-manager, this is unneeded, as it will create a secret for you with valid certificates
|
||||
## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created valid for 365 days
|
||||
## It is also possible to create and manage the certificates outside of this helm chart
|
||||
## Please see README.md for more information
|
||||
## e.g:
|
||||
## secrets:
|
||||
## - name: example.local-tls
|
||||
## key: |-
|
||||
## -----BEGIN RSA PRIVATE KEY-----
|
||||
## ...
|
||||
## -----END RSA PRIVATE KEY-----
|
||||
## certificate: |-
|
||||
## -----BEGIN CERTIFICATE-----
|
||||
## ...
|
||||
## -----END CERTIFICATE-----
|
||||
##
|
||||
secrets: []
|
||||
## @param ingress.extraRules Additional rules to be covered with this ingress record
|
||||
## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-rules
|
||||
## e.g:
|
||||
## extraRules:
|
||||
## - host: apache.local
|
||||
## http:
|
||||
## path: /
|
||||
## backend:
|
||||
## service:
|
||||
## name: apache-svc
|
||||
## port:
|
||||
## name: http
|
||||
##
|
||||
extraRules: []
|
||||
## @section Metrics Parameters
|
||||
metrics:
|
||||
## @param metrics.enabled Start a sidecar prometheus exporter to expose Apache metrics
|
||||
##
|
||||
enabled: false
|
||||
## Bitnami Apache Prometheus Exporter image
|
||||
## ref: https://hub.docker.com/r/bitnami/apache-exporter/tags/
|
||||
## @param metrics.image.registry [default: REGISTRY_NAME] Apache Exporter image registry
|
||||
## @param metrics.image.repository [default: REPOSITORY_NAME/apache-exporter] Apache Exporter image repository
|
||||
## @skip metrics.image.tag Apache Exporter image tag (immutable tags are recommended)
|
||||
## @param metrics.image.digest Apache Exporter image digest in the way sha256:aa.... Please note this parameter, if set, will override the tag
|
||||
## @param metrics.image.pullPolicy Apache Exporter image pull policy
|
||||
## @param metrics.image.pullSecrets Apache Exporter image pull secrets
|
||||
## @param metrics.image.debug Apache Exporter image debug mode
|
||||
##
|
||||
image:
|
||||
registry: docker.io
|
||||
repository: bitnami/apache-exporter
|
||||
tag: 1.0.10-debian-12-r55
|
||||
digest: ""
|
||||
pullPolicy: IfNotPresent
|
||||
## Optionally specify an array of imagePullSecrets.
|
||||
## Secrets must be manually created in the namespace.
|
||||
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
|
||||
## e.g:
|
||||
## pullSecrets:
|
||||
## - myRegistryKeySecretName
|
||||
##
|
||||
pullSecrets: []
|
||||
## Enable debug mode
|
||||
##
|
||||
debug: false
|
||||
## @param metrics.scrapeUri Apache Prometheus Exporter scrape_uri
|
||||
## Default scrape_uri is 'http://status.localhost:{{ .Values.containerPorts.http }}/server-status/?auto' if this variable is empty.
|
||||
scrapeUri: ""
|
||||
## @param metrics.podAnnotations [object] Additional custom annotations for Apache exporter service
|
||||
##
|
||||
podAnnotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "9117"
|
||||
## Apache Prometheus exporter resource requests and limits
|
||||
## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
|
||||
## We usually recommend not to specify default resources and to leave this as a conscious
|
||||
## choice for the user. This also increases chances charts run on environments with little
|
||||
## resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||
## lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||
## @param metrics.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, micro, small, medium, large, xlarge, 2xlarge). This is ignored if metrics.resources is set (metrics.resources is recommended for production).
|
||||
## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15
|
||||
##
|
||||
resourcesPreset: "none"
|
||||
## @param metrics.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads)
|
||||
## Example:
|
||||
## resources:
|
||||
## requests:
|
||||
## cpu: 2
|
||||
## memory: 512Mi
|
||||
## limits:
|
||||
## cpu: 3
|
||||
## memory: 1024Mi
|
||||
##
|
||||
resources: {}
|
||||
## @param metrics.containerPort Apache Prometheus Exporter container port
|
||||
##
|
||||
containerPort: 9141
|
||||
## Prometheus exporter service parameters
|
||||
service:
|
||||
## @param metrics.service.port Metrics service port
|
||||
##
|
||||
port: 9117
|
||||
## @param metrics.service.annotations [object] Additional custom annotations for Metrics service
|
||||
##
|
||||
annotations:
|
||||
prometheus.io/scrape: "true"
|
||||
prometheus.io/port: "{{ .Values.metrics.service.port }}"
|
||||
## Prometheus Operator PodMonitor configuration
|
||||
##
|
||||
serviceMonitor:
|
||||
## @param metrics.serviceMonitor.enabled if `true`, creates a Prometheus Operator PodMonitor (also requires `metrics.enabled` to be `true`)
|
||||
##
|
||||
enabled: false
|
||||
## @param metrics.serviceMonitor.namespace Namespace for the PodMonitor Resource (defaults to the Release Namespace)
|
||||
##
|
||||
namespace: ""
|
||||
## @param metrics.serviceMonitor.interval Interval at which metrics should be scraped.
|
||||
## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint
|
||||
## e.g:
|
||||
## interval: 10s
|
||||
##
|
||||
interval: ""
|
||||
## @param metrics.serviceMonitor.scrapeTimeout Timeout after which the scrape is ended
|
||||
## ref: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#endpoint
|
||||
## e.g:
|
||||
## scrapeTimeout: 10s
|
||||
##
|
||||
scrapeTimeout: ""
|
||||
## @param metrics.serviceMonitor.labels Labels that can be used so PodMonitor will be discovered by Prometheus
|
||||
##
|
||||
labels: {}
|
||||
## @param metrics.serviceMonitor.relabelings RelabelConfigs to apply to samples before scraping
|
||||
##
|
||||
relabelings: []
|
||||
## @param metrics.serviceMonitor.metricRelabelings MetricRelabelConfigs to apply to samples before ingestion
|
||||
##
|
||||
metricRelabelings: []
|
||||
## Prometheus Operator PrometheusRule configuration
|
||||
##
|
||||
prometheusRule:
|
||||
## @param metrics.prometheusRule.enabled if `true`, creates a Prometheus Operator PrometheusRule (also requires `metrics.enabled` to be `true` and `metrics.prometheusRule.rules`)
|
||||
##
|
||||
enabled: false
|
||||
## @param metrics.prometheusRule.namespace Namespace for the PrometheusRule Resource (defaults to the Release Namespace)
|
||||
##
|
||||
namespace: ""
|
||||
## @param metrics.prometheusRule.labels Labels that can be used so PrometheusRule will be discovered by Prometheus
|
||||
##
|
||||
labels: {}
|
||||
## @param metrics.prometheusRule.rules Prometheus Rule definitions
|
||||
## - alert: LowInstance
|
||||
## expr: up{service="{{ template "common.names.fullname" . }}"} < 1
|
||||
## for: 1m
|
||||
## labels:
|
||||
## severity: critical
|
||||
## annotations:
|
||||
## description: Service {{ template "common.names.fullname" . }} Apache is down since 1m.
|
||||
## summary: Apache instance is down.
|
||||
##
|
||||
rules: []
|
||||
## Service Account
|
||||
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
|
||||
##
|
||||
serviceAccount:
|
||||
## @param serviceAccount.create Enable creation of ServiceAccount for Apache pod
|
||||
##
|
||||
create: true
|
||||
## @param serviceAccount.name The name of the ServiceAccount to use.
|
||||
## If not set and create is true, a name is generated using the common.names.fullname template
|
||||
##
|
||||
name: ""
|
||||
## @param serviceAccount.automountServiceAccountToken Allows auto mount of ServiceAccountToken on the serviceAccount created
|
||||
## Can be set to false if pods using this serviceAccount do not need to use K8s API
|
||||
##
|
||||
automountServiceAccountToken: false
|
||||
## @param serviceAccount.annotations Additional custom annotations for the ServiceAccount
|
||||
##
|
||||
annotations: {}
|
||||
7
Tests/Fixtures/real-yaml/compose-django.yaml
Normal file
7
Tests/Fixtures/real-yaml/compose-django.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
services:
|
||||
web:
|
||||
build:
|
||||
context: app
|
||||
target: builder
|
||||
ports:
|
||||
- '8000:8000'
|
||||
27
Tests/Fixtures/real-yaml/compose-nginx-nodejs-redis.yaml
Normal file
27
Tests/Fixtures/real-yaml/compose-nginx-nodejs-redis.yaml
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: 'redislabs/redismod'
|
||||
ports:
|
||||
- '6379:6379'
|
||||
web1:
|
||||
restart: on-failure
|
||||
build: ./web
|
||||
hostname: web1
|
||||
ports:
|
||||
- '81:5000'
|
||||
web2:
|
||||
restart: on-failure
|
||||
build: ./web
|
||||
hostname: web2
|
||||
ports:
|
||||
- '82:5000'
|
||||
nginx:
|
||||
build: ./nginx
|
||||
ports:
|
||||
- '80:80'
|
||||
depends_on:
|
||||
- web1
|
||||
- web2
|
||||
|
||||
|
||||
25
Tests/Fixtures/real-yaml/compose-prometheus-grafana.yaml
Normal file
25
Tests/Fixtures/real-yaml/compose-prometheus-grafana.yaml
Normal file
@ -0,0 +1,25 @@
|
||||
services:
|
||||
prometheus:
|
||||
image: prom/prometheus
|
||||
container_name: prometheus
|
||||
command:
|
||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||
ports:
|
||||
- 9090:9090
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./prometheus:/etc/prometheus
|
||||
- prom_data:/prometheus
|
||||
grafana:
|
||||
image: grafana/grafana
|
||||
container_name: grafana
|
||||
ports:
|
||||
- 3000:3000
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_USER=admin
|
||||
- GF_SECURITY_ADMIN_PASSWORD=grafana
|
||||
volumes:
|
||||
- ./grafana:/etc/grafana/provisioning/datasources
|
||||
volumes:
|
||||
prom_data:
|
||||
33
Tests/Fixtures/real-yaml/compose-wordpress-mysql.yaml
Normal file
33
Tests/Fixtures/real-yaml/compose-wordpress-mysql.yaml
Normal file
@ -0,0 +1,33 @@
|
||||
services:
|
||||
db:
|
||||
# We use a mariadb image which supports both amd64 & arm64 architecture
|
||||
image: mariadb:10.6.4-focal
|
||||
# If you really want to use MySQL, uncomment the following line
|
||||
#image: mysql:8.0.27
|
||||
command: '--default-authentication-plugin=mysql_native_password'
|
||||
volumes:
|
||||
- db_data:/var/lib/mysql
|
||||
restart: always
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=somewordpress
|
||||
- MYSQL_DATABASE=wordpress
|
||||
- MYSQL_USER=wordpress
|
||||
- MYSQL_PASSWORD=wordpress
|
||||
expose:
|
||||
- 3306
|
||||
- 33060
|
||||
wordpress:
|
||||
image: wordpress:latest
|
||||
ports:
|
||||
- 80:80
|
||||
restart: always
|
||||
environment:
|
||||
- WORDPRESS_DB_HOST=db
|
||||
- WORDPRESS_DB_USER=wordpress
|
||||
- WORDPRESS_DB_PASSWORD=wordpress
|
||||
- WORDPRESS_DB_NAME=wordpress
|
||||
volumes:
|
||||
db_data:
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
name: All documents script
|
||||
|
||||
# **What it does**: Verifies that the all-documents script works.
|
||||
# **Why we have it**: Code quality and sustainability.
|
||||
# **Who does it impact**: docs-engineering
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/content-render/scripts/all-documents/**'
|
||||
- 'package*.json'
|
||||
- .github/workflows/all-documents.yml
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
all-documents-script:
|
||||
if: github.repository == 'github/docs-internal'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Run all-documents script
|
||||
env:
|
||||
NODE_ENV: production
|
||||
run: |
|
||||
echo "Help..."
|
||||
npm run all-documents -- --help
|
||||
|
||||
echo ""
|
||||
echo "Storing in a file (English only)"
|
||||
npm run all-documents -- -o all-documents.json -l en
|
||||
|
||||
echo ""
|
||||
echo "Look at the first 50 lines of the file..."
|
||||
cat all-documents.json | jq | head -n 50
|
||||
|
||||
# We're essentially expecting it to not crash and fail.
|
||||
@ -0,0 +1,45 @@
|
||||
name: 'Check article-api docs'
|
||||
|
||||
# **What it does**: Makes sure changes to the article api are documented.
|
||||
# **Why we have it**: So what's documented doesn't fall behind
|
||||
# **Who does it impact**: Docs engineering, CGS team
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/article-api/middleware/article.ts'
|
||||
- 'src/article-api/middleware/pagelist.ts'
|
||||
# Self-test
|
||||
- .github/workflows/article-api-docs.yml
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check-content-linter-rules-docs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'github/docs-internal' || github.repository == 'github/docs'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Check that src/article-api/README.md is up-to-date
|
||||
run: npm run generate-article-api-docs
|
||||
|
||||
- name: Fail if it isn't up-to-date
|
||||
run: |
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
git status
|
||||
git diff
|
||||
|
||||
# Some whitespace for the sake of the message below
|
||||
echo ""
|
||||
echo ""
|
||||
|
||||
echo "src/article-api/README.md is out of date."
|
||||
echo "Please run 'npm run generate-article-api-docs' and commit the changes."
|
||||
exit 1;
|
||||
fi
|
||||
@ -0,0 +1,54 @@
|
||||
name: Auto-add ready-for-doc-review label
|
||||
|
||||
# **What it does**: Automatically adds the "ready-for-doc-review" label to DIY docs PRs that contain content or data changes when they are opened in a non-draft state or converted from draft to ready for review.
|
||||
# **Why we have it**: To ensure DIY docs PRs are automatically added to the docs-content review board without requiring manual labeling.
|
||||
# **Who does it impact**: Contributors making content changes and docs-content reviewers.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- ready_for_review
|
||||
paths:
|
||||
- 'content/**'
|
||||
- 'data/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
add-review-label:
|
||||
name: Add ready-for-doc-review label to DIY docs PRs
|
||||
if: github.repository == 'github/docs-internal' && github.event.pull_request.draft == false && github.actor != 'github-openapi-bot' && github.actor != 'docs-bot'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- name: Check team membership
|
||||
id: membership_check
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
try {
|
||||
await github.rest.teams.getMembershipForUserInOrg({
|
||||
org: 'github',
|
||||
team_slug: 'docs',
|
||||
username: context.payload.sender.login,
|
||||
});
|
||||
return true
|
||||
} catch(err) {
|
||||
console.log(err)
|
||||
return false
|
||||
}
|
||||
|
||||
- name: Add ready-for-doc-review label
|
||||
if: steps.membership_check.outputs.result == 'false'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
run: |
|
||||
gh pr edit $PR_URL --add-label ready-for-doc-review
|
||||
@ -0,0 +1,68 @@
|
||||
name: Auto Close Open Source Dependency Updates
|
||||
|
||||
# **What it does**:
|
||||
# - close-external: Automatically close dependabot's pull requests in the open-source repository.
|
||||
# **Why we have it**:
|
||||
# - close-external: To avoid duplicating updates against the internal repository.
|
||||
# **Who does it impact**: It helps docs engineering focus on higher value work.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'package*.json'
|
||||
- 'Gemfile*'
|
||||
- 'Dockerfile'
|
||||
- '.github/workflows/**'
|
||||
pull_request_review:
|
||||
types:
|
||||
- edited
|
||||
- submitted
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
close-external:
|
||||
if: >-
|
||||
${{
|
||||
github.repository == 'github/docs' &&
|
||||
github.event.pull_request.number &&
|
||||
github.event.pull_request.base.ref == 'main' &&
|
||||
github.event.pull_request.user.login == 'dependabot[bot]' &&
|
||||
github.event.pull_request.state == 'open'
|
||||
}}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Close pull request and delete branch
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
run: |
|
||||
gh pr close "$PR_URL" --delete-branch
|
||||
|
||||
- name: Comment on the pull request
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
run: |
|
||||
gh pr comment "$PR_URL" --body "This dependency update will be handled internally by our engineering team."
|
||||
|
||||
# Because we get far too much spam ;_;
|
||||
- name: Lock conversations
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
with:
|
||||
script: |
|
||||
try {
|
||||
await github.rest.issues.lock({
|
||||
...context.repo,
|
||||
issue_number: parseInt(process.env.PR_NUMBER, 10),
|
||||
lock_reason: 'resolved'
|
||||
})
|
||||
console.log('Locked the pull request to prevent spam!')
|
||||
} catch (error) {
|
||||
console.error(`Failed to lock the pull request. Error: ${error}`)
|
||||
throw error
|
||||
}
|
||||
@ -0,0 +1,170 @@
|
||||
name: 'Weekly page benchmark'
|
||||
|
||||
# **What it does**: Benchmarks all pages via the article API, flags errors and slow pages
|
||||
# **Why we have it**: Catch perf regressions and broken pages before users hit them
|
||||
# **Who does it impact**: Docs engineering
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '20 16 * * 1' # Every Monday at 16:20 UTC / 8:20 PST
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
benchmark:
|
||||
if: github.repository == 'github/docs-internal'
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
BENCHMARK_LABEL: benchmark-regression
|
||||
ISSUE_REPO: github/docs-engineering
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
persist-credentials: 'false'
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Start server
|
||||
env:
|
||||
NODE_ENV: production
|
||||
PORT: 4000
|
||||
run: |
|
||||
npm run start-for-ci &
|
||||
sleep 5
|
||||
curl --retry-connrefused --retry 6 -I http://localhost:4000/
|
||||
|
||||
- name: Run benchmark
|
||||
run: |
|
||||
npx tsx src/workflows/benchmark-pages.ts \
|
||||
--versions "free-pro-team@latest,enterprise-cloud@latest,enterprise-server@latest" \
|
||||
--modes article-body \
|
||||
--slow 1000 \
|
||||
--json /tmp/benchmark-results.json | tee /tmp/benchmark-output.txt
|
||||
|
||||
- name: Check results and create issue if needed
|
||||
if: always()
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
run: |
|
||||
echo "Reading benchmark results..."
|
||||
ERRORS=$(jq '.errors | length' /tmp/benchmark-results.json 2>/dev/null || echo "0")
|
||||
SLOW=$(jq '.slow | length' /tmp/benchmark-results.json 2>/dev/null || echo "0")
|
||||
TOTAL=$(jq '.totalRequests' /tmp/benchmark-results.json 2>/dev/null || echo "0")
|
||||
P50=$(jq '.p50' /tmp/benchmark-results.json 2>/dev/null || echo "0")
|
||||
P99=$(jq '.p99' /tmp/benchmark-results.json 2>/dev/null || echo "0")
|
||||
MAX=$(jq '.max' /tmp/benchmark-results.json 2>/dev/null || echo "0")
|
||||
echo "Done reading results: $TOTAL pages, $ERRORS errors, $SLOW slow"
|
||||
|
||||
VERSIONS="free-pro-team@latest, enterprise-cloud@latest, enterprise-server@latest"
|
||||
LANGS="en"
|
||||
|
||||
if [ "$ERRORS" = "0" ] && [ "$SLOW" = "0" ]; then
|
||||
echo "✅ All clear — $TOTAL pages, p50=${P50}ms, p99=${P99}ms, max=${MAX}ms"
|
||||
|
||||
echo "Checking for existing open issue..."
|
||||
existing=$(gh issue list \
|
||||
--repo "$ISSUE_REPO" \
|
||||
--label "$BENCHMARK_LABEL" \
|
||||
--state open \
|
||||
--json number \
|
||||
--jq '.[0].number // empty' 2>/dev/null || true)
|
||||
if [ -n "$existing" ]; then
|
||||
echo "Closing issue #$existing..."
|
||||
gh issue close "$existing" \
|
||||
--repo "$ISSUE_REPO" \
|
||||
--comment "All clear as of $RUN_URL — closing."
|
||||
echo "Done closing issue #$existing"
|
||||
else
|
||||
echo "No existing issue to close"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
PROBLEM_COUNT=$((ERRORS + SLOW))
|
||||
echo "Found $ERRORS errors and $SLOW slow pages ($PROBLEM_COUNT total problems)"
|
||||
|
||||
echo "Ensuring label exists..."
|
||||
gh label create "$BENCHMARK_LABEL" \
|
||||
--repo "$ISSUE_REPO" \
|
||||
--description "Weekly page benchmark found slow or errored pages" \
|
||||
--color "e16f24" 2>/dev/null || true
|
||||
echo "Done ensuring label"
|
||||
|
||||
echo "Building issue body..."
|
||||
BODY_FILE=/tmp/benchmark-issue-body.md
|
||||
{
|
||||
echo "## Weekly page benchmark found issues"
|
||||
echo ""
|
||||
echo "**Run:** $RUN_URL"
|
||||
echo "**Languages:** $LANGS"
|
||||
echo "**Versions:** $VERSIONS"
|
||||
echo "**Total pages:** $TOTAL"
|
||||
echo "**Stats:** p50=${P50}ms · p99=${P99}ms · max=${MAX}ms"
|
||||
echo "**Errors:** $ERRORS"
|
||||
echo "**Slow (≥1000ms):** $SLOW"
|
||||
} > "$BODY_FILE"
|
||||
|
||||
if [ "$ERRORS" -gt 0 ]; then
|
||||
{
|
||||
echo ""
|
||||
echo "### Errors"
|
||||
echo ""
|
||||
echo "| Status | Mode | Path | Error |"
|
||||
echo "|--------|------|------|-------|"
|
||||
jq -r '.errors[] | "| \(.status) | \(.mode) | \(.path) | \(.errorBody // "" | gsub("\\|"; "\\|") | gsub("\r"; " ") | gsub("\n"; " ")) |"' /tmp/benchmark-results.json
|
||||
} >> "$BODY_FILE"
|
||||
fi
|
||||
|
||||
if [ "$SLOW" -gt 0 ]; then
|
||||
{
|
||||
echo ""
|
||||
echo "### Slow pages"
|
||||
echo ""
|
||||
echo "| Time | Mode | Path |"
|
||||
echo "|------|------|------|"
|
||||
jq -r '.slow[] | "| \(.timeMs)ms | \(.mode) | \(.path) |"' /tmp/benchmark-results.json
|
||||
} >> "$BODY_FILE"
|
||||
fi
|
||||
echo "Done building issue body"
|
||||
|
||||
echo "Checking for existing open issue..."
|
||||
existing=$(gh issue list \
|
||||
--repo "$ISSUE_REPO" \
|
||||
--label "$BENCHMARK_LABEL" \
|
||||
--state open \
|
||||
--json number \
|
||||
--jq '.[0].number // empty' 2>/dev/null || true)
|
||||
|
||||
if [ -n "$existing" ]; then
|
||||
echo "Commenting on existing issue #$existing..."
|
||||
gh issue comment "$existing" \
|
||||
--repo "$ISSUE_REPO" \
|
||||
--body-file "$BODY_FILE"
|
||||
echo "Done commenting on issue #$existing"
|
||||
else
|
||||
echo "Creating new issue..."
|
||||
gh issue create \
|
||||
--repo "$ISSUE_REPO" \
|
||||
--label "$BENCHMARK_LABEL" \
|
||||
--title "[Benchmark] ${PROBLEM_COUNT} slow or errored pages detected" \
|
||||
--body-file "$BODY_FILE"
|
||||
echo "Done creating issue"
|
||||
fi
|
||||
|
||||
- uses: ./.github/actions/slack-alert
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
||||
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
|
||||
- uses: ./.github/actions/create-workflow-failure-issue
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
@ -0,0 +1,762 @@
|
||||
name: Changelog agent — draft entry when a qualified PR merges
|
||||
|
||||
# **What it does**: When a PR merges that closes a docs-content issue with a
|
||||
# parent issue, uses an LLM to draft a changelog entry, opens a PR in
|
||||
# github/docs-content, and DMs the author in Slack for review.
|
||||
# **Why we have it**: Automates the changelog drafting process so authors
|
||||
# don't have to remember to write a changelog entry manually.
|
||||
# **Who does it impact**: docs-content team members.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: 'PR number to test with (must be a merged PR)'
|
||||
required: true
|
||||
type: number
|
||||
dry_run:
|
||||
description: 'Dry run — log actions but do not create PR or send Slack DM'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
concurrency:
|
||||
group: changelog-agent-${{ github.event.pull_request.number || github.event.inputs.pr_number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
env:
|
||||
CHANGELOG_FILE: docs-content-docs/docs-content-workflows/changelog-internal.md
|
||||
TARGET_REPO: github/docs-content
|
||||
|
||||
jobs:
|
||||
generate-changelog:
|
||||
if: >-
|
||||
github.repository == 'github/docs-internal' &&
|
||||
(
|
||||
(github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main') ||
|
||||
github.event_name == 'workflow_dispatch'
|
||||
)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Resolve PR data
|
||||
id: resolve_pr
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
let pr;
|
||||
if (context.eventName === 'workflow_dispatch') {
|
||||
const prNumber = parseInt('${{ inputs.pr_number }}', 10);
|
||||
const { data } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber,
|
||||
});
|
||||
pr = data;
|
||||
if (!pr.merged) {
|
||||
core.setFailed(`PR #${prNumber} has not been merged. Cannot test.`);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
pr = context.payload.pull_request;
|
||||
}
|
||||
core.setOutput('pr_number', pr.number.toString());
|
||||
core.setOutput('pr_author', pr.user.login);
|
||||
core.setOutput('pr_title', pr.title);
|
||||
core.setOutput('pr_body', pr.body || '');
|
||||
core.setOutput('pr_url', pr.html_url);
|
||||
|
||||
- name: Check if PR author is in the team
|
||||
id: check_team
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
const author = '${{ steps.resolve_pr.outputs.pr_author }}';
|
||||
|
||||
// Fetch github-to-slack.json from docs-content via API
|
||||
let mapping = {};
|
||||
try {
|
||||
const { data } = await github.rest.repos.getContent({
|
||||
owner: 'github',
|
||||
repo: 'docs-content',
|
||||
path: '.github/github-to-slack.json',
|
||||
});
|
||||
const content = Buffer.from(data.content, 'base64').toString('utf-8');
|
||||
mapping = JSON.parse(content);
|
||||
} catch (err) {
|
||||
core.setFailed(`Could not fetch github-to-slack.json from docs-content: ${err.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove non-user keys (like _comment)
|
||||
const teamMembers = Object.keys(mapping).filter(k => !k.startsWith('_'));
|
||||
|
||||
if (!teamMembers.includes(author)) {
|
||||
core.info(`PR author @${author} is not in the team mapping. Skipping.`);
|
||||
core.setOutput('is_team_member', 'false');
|
||||
return;
|
||||
}
|
||||
|
||||
core.info(`PR author @${author} is a team member. Proceeding.`);
|
||||
core.setOutput('is_team_member', 'true');
|
||||
|
||||
- name: Extract linked docs-content issue
|
||||
if: steps.check_team.outputs.is_team_member == 'true'
|
||||
id: extract_issue
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
env:
|
||||
PR_BODY: ${{ steps.resolve_pr.outputs.pr_body }}
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
const body = process.env.PR_BODY || '';
|
||||
|
||||
// Match closing keywords followed by docs-content issue references.
|
||||
// Supports: closes github/docs-content#123, fixes https://github.com/github/docs-content/issues/123
|
||||
const patterns = [
|
||||
/(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?):?\s+github\/docs-content#(\d+)/gi,
|
||||
/(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?):?\s+https:\/\/github\.com\/github\/docs-content\/issues\/(\d+)/gi,
|
||||
];
|
||||
|
||||
let issueNumber = null;
|
||||
for (const pattern of patterns) {
|
||||
const match = pattern.exec(body);
|
||||
if (match) {
|
||||
issueNumber = parseInt(match[1], 10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!issueNumber) {
|
||||
core.info('No linked docs-content issue found in PR body. Exiting.');
|
||||
core.setOutput('found', 'false');
|
||||
return;
|
||||
}
|
||||
|
||||
core.info(`Found linked docs-content issue: #${issueNumber}`);
|
||||
core.setOutput('found', 'true');
|
||||
core.setOutput('issue_number', issueNumber.toString());
|
||||
|
||||
- name: Check for parent issue
|
||||
if: steps.extract_issue.outputs.found == 'true'
|
||||
id: check_parent
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
const issueNumber = parseInt('${{ steps.extract_issue.outputs.issue_number }}', 10);
|
||||
|
||||
let issue;
|
||||
try {
|
||||
const { data } = await github.rest.issues.get({
|
||||
owner: 'github',
|
||||
repo: 'docs-content',
|
||||
issue_number: issueNumber,
|
||||
});
|
||||
issue = data;
|
||||
} catch (err) {
|
||||
core.info(`Could not fetch docs-content issue #${issueNumber}: ${err.message}. Skipping.`);
|
||||
core.setOutput('has_parent', 'false');
|
||||
return;
|
||||
}
|
||||
|
||||
// Query for parent issue via GraphQL
|
||||
const query = `
|
||||
query($nodeId: ID!) {
|
||||
node(id: $nodeId) {
|
||||
... on Issue {
|
||||
parent {
|
||||
number
|
||||
title
|
||||
body
|
||||
url
|
||||
author { login }
|
||||
assignees(first: 10) {
|
||||
nodes { login }
|
||||
}
|
||||
repository {
|
||||
nameWithOwner
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = await github.graphql(query, { nodeId: issue.node_id });
|
||||
} catch (err) {
|
||||
core.info(`GraphQL parent query failed: ${err.message}. Skipping.`);
|
||||
core.setOutput('has_parent', 'false');
|
||||
return;
|
||||
}
|
||||
|
||||
const parent = result.node?.parent;
|
||||
|
||||
if (!parent) {
|
||||
core.info('docs-content issue has no parent issue. Exiting.');
|
||||
core.setOutput('has_parent', 'false');
|
||||
return;
|
||||
}
|
||||
|
||||
core.info(`Found parent issue: ${parent.repository.nameWithOwner}#${parent.number}`);
|
||||
core.setOutput('has_parent', 'true');
|
||||
core.setOutput('parent_number', parent.number.toString());
|
||||
core.setOutput('parent_title', parent.title);
|
||||
core.setOutput('parent_body', parent.body || '');
|
||||
core.setOutput('parent_url', parent.url);
|
||||
core.setOutput('parent_author', parent.author?.login || '');
|
||||
core.setOutput('parent_assignees', (parent.assignees?.nodes || []).map(a => a.login).join(','));
|
||||
core.setOutput('parent_repo', parent.repository.nameWithOwner);
|
||||
|
||||
// Also store the docs-content issue details
|
||||
core.setOutput('dc_issue_title', issue.title);
|
||||
core.setOutput('dc_issue_body', issue.body || '');
|
||||
|
||||
- name: Gather PR context
|
||||
if: steps.check_parent.outputs.has_parent == 'true'
|
||||
id: gather_context
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
env:
|
||||
PR_TITLE: ${{ steps.resolve_pr.outputs.pr_title }}
|
||||
PR_BODY: ${{ steps.resolve_pr.outputs.pr_body }}
|
||||
PR_URL: ${{ steps.resolve_pr.outputs.pr_url }}
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
const prNumber = parseInt('${{ steps.resolve_pr.outputs.pr_number }}', 10);
|
||||
const prAuthor = '${{ steps.resolve_pr.outputs.pr_author }}';
|
||||
|
||||
// Get approved reviewers (exclude bots and PR author)
|
||||
const { data: reviews } = await github.rest.pulls.listReviews({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber,
|
||||
});
|
||||
|
||||
const approvedReviewers = [...new Set(
|
||||
reviews
|
||||
.filter(r => r.state === 'APPROVED' && r.user.type !== 'Bot' && r.user.login !== prAuthor)
|
||||
.map(r => r.user.login)
|
||||
)];
|
||||
|
||||
// Get changed files (paths only, limit to 50)
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber,
|
||||
per_page: 50,
|
||||
});
|
||||
|
||||
const changedFiles = files.map(f => f.filename);
|
||||
|
||||
core.setOutput('pr_author', prAuthor);
|
||||
core.setOutput('pr_title', process.env.PR_TITLE || '');
|
||||
core.setOutput('pr_body', process.env.PR_BODY || '');
|
||||
core.setOutput('pr_url', process.env.PR_URL || '');
|
||||
core.setOutput('pr_number', prNumber.toString());
|
||||
core.setOutput('approved_reviewers', approvedReviewers.join(','));
|
||||
core.setOutput('changed_files', changedFiles.join('\n'));
|
||||
|
||||
- name: Check for existing changelog PR
|
||||
if: steps.check_parent.outputs.has_parent == 'true'
|
||||
id: check_existing
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
const branchName = `changelog-agent-${{ steps.resolve_pr.outputs.pr_number }}`;
|
||||
const { data: pulls } = await github.rest.pulls.list({
|
||||
owner: 'github',
|
||||
repo: 'docs-content',
|
||||
head: `github:${branchName}`,
|
||||
state: 'open',
|
||||
});
|
||||
|
||||
if (pulls.length > 0) {
|
||||
core.info(`Changelog PR already exists: ${pulls[0].html_url}`);
|
||||
core.setOutput('exists', 'true');
|
||||
core.setOutput('existing_pr_url', pulls[0].html_url);
|
||||
} else {
|
||||
core.setOutput('exists', 'false');
|
||||
}
|
||||
|
||||
- name: Read existing changelog examples
|
||||
if: steps.check_parent.outputs.has_parent == 'true' && steps.check_existing.outputs.exists == 'false'
|
||||
id: read_examples
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
// Fetch changelog-internal.md from docs-content
|
||||
const { data } = await github.rest.repos.getContent({
|
||||
owner: 'github',
|
||||
repo: 'docs-content',
|
||||
path: 'docs-content-docs/docs-content-workflows/changelog-internal.md',
|
||||
});
|
||||
const changelog = Buffer.from(data.content, 'base64').toString('utf-8');
|
||||
|
||||
// Extract the first 3 entries (each starts with **date**)
|
||||
const lines = changelog.split('\n');
|
||||
let count = 0;
|
||||
let examples = [];
|
||||
let capturing = false;
|
||||
for (const line of lines) {
|
||||
if (/^\*\*\d/.test(line)) {
|
||||
count++;
|
||||
if (count > 3) break;
|
||||
capturing = true;
|
||||
}
|
||||
if (capturing) examples.push(line);
|
||||
}
|
||||
|
||||
core.setOutput('examples', examples.join('\n'));
|
||||
|
||||
- name: Set up Node.js
|
||||
if: steps.check_parent.outputs.has_parent == 'true' && steps.check_existing.outputs.exists == 'false'
|
||||
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
|
||||
with:
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Prepare prompts for LLM
|
||||
if: steps.check_parent.outputs.has_parent == 'true' && steps.check_existing.outputs.exists == 'false'
|
||||
id: prepare_prompts
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
env:
|
||||
PR_TITLE: ${{ steps.gather_context.outputs.pr_title }}
|
||||
PR_BODY: ${{ steps.gather_context.outputs.pr_body }}
|
||||
PR_AUTHOR: ${{ steps.gather_context.outputs.pr_author }}
|
||||
CHANGED_FILES: ${{ steps.gather_context.outputs.changed_files }}
|
||||
APPROVED_REVIEWERS: ${{ steps.gather_context.outputs.approved_reviewers }}
|
||||
DC_ISSUE_TITLE: ${{ steps.check_parent.outputs.dc_issue_title }}
|
||||
DC_ISSUE_BODY: ${{ steps.check_parent.outputs.dc_issue_body }}
|
||||
PARENT_TITLE: ${{ steps.check_parent.outputs.parent_title }}
|
||||
PARENT_BODY: ${{ steps.check_parent.outputs.parent_body }}
|
||||
PARENT_AUTHOR: ${{ steps.check_parent.outputs.parent_author }}
|
||||
PARENT_ASSIGNEES: ${{ steps.check_parent.outputs.parent_assignees }}
|
||||
CHANGELOG_EXAMPLES: ${{ steps.read_examples.outputs.examples }}
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
const today = new Date();
|
||||
const dateStr = today.toLocaleDateString('en-GB', {
|
||||
day: 'numeric', month: 'long', year: 'numeric'
|
||||
});
|
||||
|
||||
const systemPrompt = `You are a technical writer for GitHub Docs. You write changelog entries for the internal docs changelog.
|
||||
|
||||
Rules:
|
||||
- Write in plain, clear language suitable for an internal audience of docs team members
|
||||
- Focus on what shipped and its impact on users of docs.github.com
|
||||
- Use present tense or past tense consistently
|
||||
- Include links to relevant docs pages when possible (use full https://docs.github.com/... URLs)
|
||||
- The entry MUST include these sections in order:
|
||||
1. A brief description paragraph of what shipped
|
||||
2. **Anticipated impact**: One or two sentences about who is affected and how
|
||||
3. **Authored by**: @username of the PR author
|
||||
4. **Thanks to**: @usernames of reviewers and stakeholders who helped
|
||||
- Do NOT include any internal issue numbers, PR numbers, or repo references in the description
|
||||
- Do NOT disclose sensitive information
|
||||
- Match the tone and structure of the example entries provided
|
||||
- Output ONLY the changelog entry text (no date header, no <hr> tag — those are added automatically)`;
|
||||
|
||||
const reviewers = process.env.APPROVED_REVIEWERS
|
||||
? process.env.APPROVED_REVIEWERS.split(',').filter(r => r !== process.env.PR_AUTHOR).map(r => `@${r}`).join(', ')
|
||||
: '';
|
||||
const stakeholders = [
|
||||
process.env.PARENT_AUTHOR,
|
||||
...(process.env.PARENT_ASSIGNEES ? process.env.PARENT_ASSIGNEES.split(',') : []),
|
||||
].filter(Boolean).filter(u => u !== process.env.PR_AUTHOR).filter((v, i, a) => a.indexOf(v) === i).map(u => `@${u}`).join(', ');
|
||||
|
||||
const thanksTo = [reviewers, stakeholders].filter(Boolean).join(', ');
|
||||
|
||||
const userPrompt = `Draft a changelog entry for a docs change that just shipped.
|
||||
|
||||
## PR details
|
||||
Title: ${process.env.PR_TITLE}
|
||||
Description: ${process.env.PR_BODY}
|
||||
Author: @${process.env.PR_AUTHOR}
|
||||
Changed files:
|
||||
${process.env.CHANGED_FILES}
|
||||
|
||||
## docs-content issue
|
||||
Title: ${process.env.DC_ISSUE_TITLE}
|
||||
Description: ${process.env.DC_ISSUE_BODY}
|
||||
|
||||
## Parent issue (broader feature/initiative)
|
||||
Title: ${process.env.PARENT_TITLE}
|
||||
Description: ${process.env.PARENT_BODY}
|
||||
|
||||
## Credits
|
||||
Author: @${process.env.PR_AUTHOR}
|
||||
Thanks to: ${thanksTo || 'N/A'}
|
||||
|
||||
## Example entries from the existing changelog (match this style):
|
||||
${process.env.CHANGELOG_EXAMPLES}
|
||||
|
||||
Write the changelog entry now. Include the **Anticipated impact**, **Authored by**, and **Thanks to** sections.`;
|
||||
|
||||
fs.writeFileSync('system-prompt.txt', systemPrompt);
|
||||
fs.writeFileSync('prompt.txt', userPrompt);
|
||||
core.setOutput('date_str', dateStr);
|
||||
|
||||
- name: Generate changelog draft via Copilot
|
||||
if: steps.check_parent.outputs.has_parent == 'true' && steps.check_existing.outputs.exists == 'false'
|
||||
id: generate_draft
|
||||
uses: actions/ai-inference@17ff458cb182449bbb2e43701fcd98f6af8f6570 # v2.1.0
|
||||
with:
|
||||
provider: copilot
|
||||
model: gpt-4.1
|
||||
prompt-file: prompt.txt
|
||||
system-prompt-file: system-prompt.txt
|
||||
max-completion-tokens: 1000
|
||||
temperature: 0.3
|
||||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.DOCS_BOT_PAT_COPILOT }}
|
||||
|
||||
- name: Dry run summary
|
||||
if: steps.generate_draft.outputs.response != '' && inputs.dry_run == true
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
env:
|
||||
PR_AUTHOR: ${{ steps.gather_context.outputs.pr_author }}
|
||||
PR_URL: ${{ steps.gather_context.outputs.pr_url }}
|
||||
PARENT_TITLE: ${{ steps.check_parent.outputs.parent_title }}
|
||||
DRAFT: ${{ steps.generate_draft.outputs.response }}
|
||||
with:
|
||||
script: |
|
||||
core.info('=== DRY RUN — no PR will be created, no Slack DM sent ===');
|
||||
core.info(`PR author: ${process.env.PR_AUTHOR || ''}`);
|
||||
core.info(`Source PR: ${process.env.PR_URL || ''}`);
|
||||
core.info(`Parent issue: ${process.env.PARENT_TITLE || ''}`);
|
||||
core.info('--- Generated changelog draft ---');
|
||||
core.info((process.env.DRAFT || '').replace(/^::/gm, ': :'));
|
||||
core.info('--- End of draft ---');
|
||||
|
||||
- name: Create changelog PR in docs-content
|
||||
if: steps.generate_draft.outputs.response != '' && steps.check_existing.outputs.exists == 'false' && inputs.dry_run != true
|
||||
id: create_pr
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
env:
|
||||
DRAFT: ${{ steps.generate_draft.outputs.response }}
|
||||
DATE_STR: ${{ steps.prepare_prompts.outputs.date_str }}
|
||||
PR_AUTHOR: ${{ steps.gather_context.outputs.pr_author }}
|
||||
PR_URL: ${{ steps.gather_context.outputs.pr_url }}
|
||||
PR_NUMBER: ${{ steps.gather_context.outputs.pr_number }}
|
||||
APPROVED_REVIEWERS: ${{ steps.gather_context.outputs.approved_reviewers }}
|
||||
PARENT_TITLE: ${{ steps.check_parent.outputs.parent_title }}
|
||||
PARENT_URL: ${{ steps.check_parent.outputs.parent_url }}
|
||||
PARENT_AUTHOR: ${{ steps.check_parent.outputs.parent_author }}
|
||||
PARENT_ASSIGNEES: ${{ steps.check_parent.outputs.parent_assignees }}
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
const branchName = `changelog-agent-${{ steps.resolve_pr.outputs.pr_number }}`;
|
||||
const filePath = 'docs-content-docs/docs-content-workflows/changelog-internal.md';
|
||||
|
||||
// Get the current changelog file from docs-content
|
||||
const { data: fileData } = await github.rest.repos.getContent({
|
||||
owner: 'github',
|
||||
repo: 'docs-content',
|
||||
path: filePath,
|
||||
});
|
||||
|
||||
let changelog = Buffer.from(fileData.content, 'base64').toString('utf-8');
|
||||
|
||||
// Build the new entry
|
||||
const entry = `**${process.env.DATE_STR}**\n\n${process.env.DRAFT}\n\n<hr>`;
|
||||
|
||||
// Insert after the first H1 heading so leading frontmatter, comments,
|
||||
// or blank lines do not affect placement.
|
||||
const lines = changelog.split('\n');
|
||||
const headingIndex = lines.findIndex((line) => line.startsWith('# '));
|
||||
|
||||
if (headingIndex === -1) {
|
||||
changelog = `${entry}\n${changelog}`;
|
||||
} else {
|
||||
const beforeAndHeading = lines.slice(0, headingIndex + 1).join('\n');
|
||||
const rest = lines.slice(headingIndex + 1).join('\n');
|
||||
changelog = rest
|
||||
? `${beforeAndHeading}\n\n${entry}\n${rest}`
|
||||
: `${beforeAndHeading}\n\n${entry}`;
|
||||
}
|
||||
|
||||
// Get the default branch SHA for creating a new branch
|
||||
const { data: ref } = await github.rest.git.getRef({
|
||||
owner: 'github',
|
||||
repo: 'docs-content',
|
||||
ref: 'heads/main',
|
||||
});
|
||||
|
||||
// Create the branch in docs-content
|
||||
try {
|
||||
await github.rest.git.createRef({
|
||||
owner: 'github',
|
||||
repo: 'docs-content',
|
||||
ref: `refs/heads/${branchName}`,
|
||||
sha: ref.object.sha,
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.status === 422) {
|
||||
core.info('Branch already exists, will update file on existing branch.');
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch the file from the branch (handles both new and existing branches)
|
||||
const { data: branchFileData } = await github.rest.repos.getContent({
|
||||
owner: 'github',
|
||||
repo: 'docs-content',
|
||||
path: filePath,
|
||||
ref: branchName,
|
||||
});
|
||||
|
||||
// Update the changelog file on the new branch
|
||||
await github.rest.repos.createOrUpdateFileContents({
|
||||
owner: 'github',
|
||||
repo: 'docs-content',
|
||||
path: filePath,
|
||||
message: `Changelog draft for docs-internal PR #${process.env.PR_NUMBER}`,
|
||||
content: Buffer.from(changelog).toString('base64'),
|
||||
sha: branchFileData.sha,
|
||||
branch: branchName,
|
||||
committer: {
|
||||
name: 'github-actions[bot]',
|
||||
email: 'github-actions[bot]@users.noreply.github.com',
|
||||
},
|
||||
});
|
||||
|
||||
// Build credits for the PR body
|
||||
const reviewers = process.env.APPROVED_REVIEWERS
|
||||
? process.env.APPROVED_REVIEWERS.split(',').map(r => `@${r}`).join(', ')
|
||||
: 'None';
|
||||
const parentAuthor = process.env.PARENT_AUTHOR ? `@${process.env.PARENT_AUTHOR}` : 'Unknown';
|
||||
const parentAssignees = process.env.PARENT_ASSIGNEES
|
||||
? process.env.PARENT_ASSIGNEES.split(',').map(a => `@${a}`).join(', ')
|
||||
: 'None';
|
||||
|
||||
const prBody = [
|
||||
'### Automated docs changelog draft',
|
||||
'',
|
||||
`_Generated by the changelog-agent workflow from [docs-internal PR #${process.env.PR_NUMBER}](${process.env.PR_URL})._`,
|
||||
'',
|
||||
'**⚠️ This is an AI-generated draft. Please review carefully before merging.**',
|
||||
'',
|
||||
`**Source PR:** [docs-internal#${process.env.PR_NUMBER}](${process.env.PR_URL})`,
|
||||
`**Parent initiative:** [${process.env.PARENT_TITLE}](${process.env.PARENT_URL})`,
|
||||
'',
|
||||
'#### Credits',
|
||||
`- **Author:** @${process.env.PR_AUTHOR}`,
|
||||
`- **Reviewers:** ${reviewers}`,
|
||||
`- **Parent issue author:** ${parentAuthor}`,
|
||||
`- **Parent issue assignees:** ${parentAssignees}`,
|
||||
'',
|
||||
'#### Review checklist',
|
||||
'- [ ] Entry is accurate and covers what shipped',
|
||||
'- [ ] Content is appropriate for the internal audience',
|
||||
'- [ ] Format is consistent with other changelog entries',
|
||||
'- [ ] No sensitive information disclosed',
|
||||
].join('\n');
|
||||
|
||||
const { data: pullRequest } = await github.rest.pulls.create({
|
||||
owner: 'github',
|
||||
repo: 'docs-content',
|
||||
title: `Changelog draft for docs-internal PR #${process.env.PR_NUMBER}`,
|
||||
body: prBody,
|
||||
head: branchName,
|
||||
base: 'main',
|
||||
draft: true,
|
||||
});
|
||||
|
||||
// Add labels
|
||||
try {
|
||||
await github.rest.issues.addLabels({
|
||||
owner: 'github',
|
||||
repo: 'docs-content',
|
||||
issue_number: pullRequest.number,
|
||||
labels: ['ready-for-doc-review', 'skip FR board', 'llm-generated'],
|
||||
});
|
||||
} catch (err) {
|
||||
core.warning(`Failed to add labels: ${err.message}`);
|
||||
}
|
||||
|
||||
// Assign to PR author
|
||||
try {
|
||||
await github.rest.issues.addAssignees({
|
||||
owner: 'github',
|
||||
repo: 'docs-content',
|
||||
issue_number: pullRequest.number,
|
||||
assignees: [process.env.PR_AUTHOR],
|
||||
});
|
||||
} catch (err) {
|
||||
core.warning(`Failed to assign PR to @${process.env.PR_AUTHOR}: ${err.message}`);
|
||||
}
|
||||
|
||||
core.setOutput('changelog_pr_url', pullRequest.html_url);
|
||||
core.setOutput('changelog_pr_number', pullRequest.number.toString());
|
||||
|
||||
- name: Notify author via Slack DM
|
||||
if: steps.create_pr.outputs.changelog_pr_url != '' && inputs.dry_run != true
|
||||
id: slack_notify
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
env:
|
||||
SLACK_TOKEN: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
PR_AUTHOR: ${{ steps.gather_context.outputs.pr_author }}
|
||||
CHANGELOG_PR_URL: ${{ steps.create_pr.outputs.changelog_pr_url }}
|
||||
PR_URL: ${{ steps.gather_context.outputs.pr_url }}
|
||||
APPROVED_REVIEWERS: ${{ steps.gather_context.outputs.approved_reviewers }}
|
||||
PARENT_TITLE: ${{ steps.check_parent.outputs.parent_title }}
|
||||
PARENT_AUTHOR: ${{ steps.check_parent.outputs.parent_author }}
|
||||
PARENT_ASSIGNEES: ${{ steps.check_parent.outputs.parent_assignees }}
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
const author = process.env.PR_AUTHOR;
|
||||
const changelogPrUrl = process.env.CHANGELOG_PR_URL;
|
||||
|
||||
// Fetch GitHub-to-Slack mapping from docs-content
|
||||
let slackMapping = {};
|
||||
try {
|
||||
const { data } = await github.rest.repos.getContent({
|
||||
owner: 'github',
|
||||
repo: 'docs-content',
|
||||
path: '.github/github-to-slack.json',
|
||||
});
|
||||
const content = Buffer.from(data.content, 'base64').toString('utf-8');
|
||||
slackMapping = JSON.parse(content);
|
||||
} catch (err) {
|
||||
core.warning(`Could not fetch github-to-slack.json: ${err.message}`);
|
||||
}
|
||||
|
||||
const slackUserId = slackMapping[author];
|
||||
|
||||
// Build credits summary for the DM
|
||||
const reviewers = process.env.APPROVED_REVIEWERS
|
||||
? process.env.APPROVED_REVIEWERS.split(',').join(', ')
|
||||
: 'none';
|
||||
const stakeholders = [
|
||||
process.env.PARENT_AUTHOR,
|
||||
...(process.env.PARENT_ASSIGNEES ? process.env.PARENT_ASSIGNEES.split(',') : []),
|
||||
].filter(Boolean).filter((v, i, a) => a.indexOf(v) === i).join(', ');
|
||||
|
||||
const slackMessage = [
|
||||
`👋 Hi! A changelog draft has been created for your merged PR:`,
|
||||
``,
|
||||
`📝 *Changelog PR:* ${changelogPrUrl}`,
|
||||
`🔗 *Source PR:* ${process.env.PR_URL}`,
|
||||
`🎯 *Parent initiative:* ${process.env.PARENT_TITLE}`,
|
||||
``,
|
||||
`*Reviewers to thank:* ${reviewers || 'none'}`,
|
||||
`*Stakeholders to thank:* ${stakeholders || 'none'}`,
|
||||
``,
|
||||
`Please review the draft changelog entry and merge or close the PR. The entry is AI-generated, so double-check accuracy and tone.`,
|
||||
].join('\n');
|
||||
|
||||
if (slackUserId) {
|
||||
try {
|
||||
const response = await fetch('https://slack.com/api/chat.postMessage', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${process.env.SLACK_TOKEN}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
channel: slackUserId,
|
||||
text: slackMessage,
|
||||
}),
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
if (result.ok) {
|
||||
core.info(`Slack DM sent to ${author} (${slackUserId})`);
|
||||
core.setOutput('notified_via', 'slack');
|
||||
return;
|
||||
} else {
|
||||
core.warning(`Slack API error: ${result.error}`);
|
||||
}
|
||||
} catch (err) {
|
||||
core.warning(`Slack DM failed: ${err.message}`);
|
||||
}
|
||||
} else {
|
||||
core.warning(`No Slack mapping found for GitHub user: ${author}`);
|
||||
}
|
||||
|
||||
// Fallback: post a GitHub comment on the source PR
|
||||
core.info('Falling back to GitHub comment notification.');
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: parseInt('${{ steps.resolve_pr.outputs.pr_number }}', 10),
|
||||
body: [
|
||||
`👋 @${author} — A changelog draft has been created for this PR!`,
|
||||
``,
|
||||
`📝 **Changelog PR:** ${changelogPrUrl}`,
|
||||
``,
|
||||
`Please review the draft entry and merge or close it. The entry is AI-generated, so double-check accuracy and tone.`,
|
||||
``,
|
||||
`**Reviewers to thank:** ${reviewers || 'none'}`,
|
||||
`**Stakeholders to thank:** ${stakeholders || 'none'}`,
|
||||
].join('\n'),
|
||||
});
|
||||
core.setOutput('notified_via', 'github_comment');
|
||||
|
||||
- name: Post agent marker comment
|
||||
if: steps.create_pr.outputs.changelog_pr_url != '' && inputs.dry_run != true
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
const changelogPrUrl = '${{ steps.create_pr.outputs.changelog_pr_url }}';
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: parseInt('${{ steps.resolve_pr.outputs.pr_number }}', 10),
|
||||
body: `<!-- changelog-agent-handled -->\n🤖 A changelog draft PR has been automatically created in docs-content: ${changelogPrUrl}`,
|
||||
});
|
||||
|
||||
- name: Send Slack failure alert
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_CHANNEL_ID: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
||||
SLACK_TOKEN: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
WORKFLOW_NAME: ${{ github.workflow }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
RUN_ID: ${{ github.run_id }}
|
||||
SERVER_URL: ${{ github.server_url }}
|
||||
run: |
|
||||
curl -sS -X POST https://slack.com/api/chat.postMessage \
|
||||
-H "Authorization: Bearer ${SLACK_TOKEN}" \
|
||||
-H "Content-Type: application/json; charset=utf-8" \
|
||||
--data "$(cat <<EOF
|
||||
{
|
||||
"channel": "${SLACK_CHANNEL_ID}",
|
||||
"text": ":warning: Workflow failure in ${REPOSITORY}",
|
||||
"blocks": [
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": ":warning: *${WORKFLOW_NAME}* failed in *${REPOSITORY}*"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "<${SERVER_URL}/${REPOSITORY}/actions/runs/${RUN_ID}|View workflow run>"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
)"
|
||||
@ -0,0 +1,66 @@
|
||||
name: Changelog prompt when a PR is closed
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
comment-on-pr:
|
||||
# This workflow should only run on the 'github/docs-internal' repository because it posts changelog instructions
|
||||
# and links that are specific to the internal documentation process and resources.
|
||||
# It also only runs if PR is merged into the main branch.
|
||||
if: github.repository == 'github/docs-internal' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check if PR author is in docs-content team
|
||||
id: check_team
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
try {
|
||||
const pr = context.payload.pull_request;
|
||||
await github.rest.teams.getMembershipForUserInOrg({
|
||||
org: 'github',
|
||||
team_slug: 'docs-content',
|
||||
username: pr.user.login,
|
||||
});
|
||||
core.exportVariable('CONTINUE_WORKFLOW', 'true');
|
||||
} catch(err) {
|
||||
core.info("Workflow triggered by a merged PR, but the PR author is not a member of the docs-content team.");
|
||||
core.exportVariable('CONTINUE_WORKFLOW', 'false');
|
||||
}
|
||||
|
||||
- name: Post changelog instructions comment
|
||||
|
||||
if: env.CONTINUE_WORKFLOW == 'true'
|
||||
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
// Get PR author username
|
||||
const pr = context.payload.pull_request;
|
||||
const prAuthor = pr.user.login;
|
||||
|
||||
// Compose the comment body with readable YAML and correct formatting
|
||||
const commentBody =
|
||||
"👋 @" + prAuthor +
|
||||
" - Did this PR add noteworthy changes to the GitHub docs? If so, you might want to publicize this by adding an entry to " +
|
||||
"the [Docs changelog](https://github.com/github/docs-internal/blob/main/CHANGELOG.md).\n\n" +
|
||||
"To do this, type `/changelog` in a new comment on this PR and complete the fields.\n\n" +
|
||||
"A message will be posted to the **#docs-changelog** channel and a PR will be raised to update the [CHANGELOG.md](https://github.com/github/docs-internal/blob/main/CHANGELOG.md) file.";
|
||||
|
||||
// Post the comment
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: commentBody
|
||||
});
|
||||
@ -0,0 +1,82 @@
|
||||
name: Check for Spammy Issues
|
||||
|
||||
# **What it does**: This action closes low value pull requests in the open-source repository.
|
||||
# **Why we have it**: We get lots of spam in the open-source repository.
|
||||
# **Who does it impact**: Open-source contributors.
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
spammy-title-check:
|
||||
name: Remove issues with spammy titles
|
||||
if: github.repository == 'github/docs'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
|
||||
const issue = context.payload.issue
|
||||
const owner = 'github'
|
||||
const repo = 'docs'
|
||||
|
||||
const titleWordCount = issue.title.trim().split(' ').length
|
||||
const titleWordCountMin = 3
|
||||
|
||||
try {
|
||||
await github.rest.teams.getMembershipForUserInOrg({
|
||||
org: 'github',
|
||||
team_slug: 'employees',
|
||||
username: context.payload.sender.login,
|
||||
});
|
||||
|
||||
// Do not perform this workflow with GitHub employees. This return
|
||||
// statement only gets hit if the user is a GitHub employee
|
||||
return
|
||||
} catch (err) {
|
||||
// An error will be thrown if the user is not a GitHub employee
|
||||
// If a user is not a GitHub employee, we should check to see if title has at least the minimum required number of words in it and if it does, we can exit the workflow
|
||||
|
||||
if (titleWordCount >= titleWordCountMin) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Assuming the user is not a GitHub employee and the issue title
|
||||
// does not contain the minimum number of words required, proceed.
|
||||
//
|
||||
|
||||
// Close the issue and add the invalid label
|
||||
await github.rest.issues.update({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: issue.number,
|
||||
labels: ['invalid'],
|
||||
state: 'closed'
|
||||
});
|
||||
|
||||
// Comment on the issue
|
||||
await github.rest.issues.createComment({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
issue_number: issue.number,
|
||||
body: `This issue may have been opened accidentally. I'm going to close it now, but feel free to open a new issue with a more descriptive title!`
|
||||
});
|
||||
|
||||
// Add the issue to the Done column on the triage board
|
||||
try {
|
||||
await github.rest.projects.createCard({
|
||||
column_id: 11167427,
|
||||
content_id: context.payload.issue.id,
|
||||
content_type: "Issue"
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
name: Close bad repo-sync PRs
|
||||
|
||||
# **What it does**:
|
||||
# Closes and PR from `repo-sync` to `main` that wasn't created by a Hubber.
|
||||
# **Why we have it**:
|
||||
# Unfortunately, a lot of PRs in github/docs are created by people who
|
||||
# shouldn't be creating such PRs. We bot our bots to own it.
|
||||
# **Who does it impact**: Open-source.
|
||||
|
||||
on:
|
||||
# Necessary in lieu of `pull_request` so that PRs opened from forks can be closed if they try to push to a repo sync branch.
|
||||
pull_request_target:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
close-invalid-repo-sync-pr:
|
||||
if: ${{ github.repository == 'github/docs' && github.event.pull_request.base.ref == 'main' && github.event.pull_request.head.ref == 'repo-sync' }}
|
||||
name: Close if invalid repo-sync PR author
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Close pull request if unwanted
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
const { owner, repo } = context.repo
|
||||
const prCreator = context.actor
|
||||
const prNumber = context.issue.number
|
||||
|
||||
try {
|
||||
await github.rest.teams.getMembershipForUserInOrg({
|
||||
org: 'github',
|
||||
team_slug: 'employees',
|
||||
username: prCreator
|
||||
})
|
||||
|
||||
// If the PR creator is a GitHub employee, stop now
|
||||
console.log("PR creator is a GitHub employee")
|
||||
return
|
||||
} catch (err) {
|
||||
// An error will be thrown if the user is not a GitHub employee.
|
||||
// That said, we still want to proceed anyway!
|
||||
}
|
||||
|
||||
// Close the PR and add the invalid label
|
||||
await github.rest.issues.update({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: prNumber,
|
||||
labels: ['invalid'],
|
||||
state: 'closed'
|
||||
})
|
||||
|
||||
// Comment on the PR
|
||||
await github.rest.issues.createComment({
|
||||
owner,
|
||||
repo,
|
||||
issue_number: prNumber,
|
||||
body: "Please leave this `repo-sync` branch to the robots!\n\nI'm going to close this pull request now, but feel free to open a new issue in the repository!"
|
||||
})
|
||||
@ -0,0 +1,48 @@
|
||||
name: Close issue/PR on adding invalid label
|
||||
|
||||
# **What it does**: This action closes invalid pull requests in the open-source repository.
|
||||
# **Why we have it**: We get lots of spam in the open-source repository.
|
||||
# **Who does it impact**: Open-source contributors.
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
# Needed in lieu of `pull_request` so that PRs from a fork can be
|
||||
# closed when marked as invalid.
|
||||
pull_request_target:
|
||||
types: [labeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
close-on-adding-invalid-label:
|
||||
if: github.repository == 'github/docs' && github.event.label.name == 'invalid'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Close issue
|
||||
if: ${{ github.event_name == 'issues' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ISSUE_URL: ${{ github.event.issue.html_url }}
|
||||
run: gh issue close "$ISSUE_URL"
|
||||
|
||||
- name: Close PR
|
||||
if: ${{ github.event_name == 'pull_request_target' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
run: gh pr close "$PR_URL"
|
||||
|
||||
- name: Check out repo
|
||||
if: ${{ failure() && github.event_name != 'pull_request_target' }}
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- uses: ./.github/actions/slack-alert
|
||||
if: ${{ failure() && github.event_name != 'pull_request_target' }}
|
||||
with:
|
||||
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
||||
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
@ -0,0 +1,48 @@
|
||||
name: CodeQL analysis
|
||||
|
||||
# **What it does**: This runs CodeQL on our repository.
|
||||
# **Why we have it**: Security scanning.
|
||||
# **Who does it impact**: Docs engineering.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
# This is so that when CodeQL runs on a pull request, it can compare
|
||||
# against the state of the base branch.
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
# This allows a subsequently queued workflow run to interrupt previous runs
|
||||
concurrency:
|
||||
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository == 'github/docs-internal' || github.repository == 'github/docs'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: github/codeql-action/init@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7
|
||||
with:
|
||||
languages: javascript # comma separated list of values from {go, python, javascript, java, cpp, csharp, ruby}
|
||||
- uses: github/codeql-action/analyze@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7
|
||||
continue-on-error: true
|
||||
|
||||
- uses: ./.github/actions/slack-alert
|
||||
if: ${{ failure() && github.event_name != 'pull_request' }}
|
||||
with:
|
||||
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
||||
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
|
||||
- uses: ./.github/actions/create-workflow-failure-issue
|
||||
if: ${{ failure() && github.event_name != 'pull_request' }}
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
@ -0,0 +1,33 @@
|
||||
# This workflow provides information when a contributor edits a release note file
|
||||
|
||||
name: Comment on release note changes
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
paths:
|
||||
- data/release-notes/enterprise-server/**
|
||||
- .github/workflows/comment-release-note-info.yml
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
# Do not add this comment on PRs created by the bot during the standard patch release process
|
||||
# or in the github/docs repository
|
||||
if: github.event.pull_request.user.login != 'release-controller[bot]' && github.repository == 'github/docs-internal'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body: |
|
||||
Thank you for updating our GitHub Enterprise Server release notes. Please request a technical review for your changes. Once the technical review is complete, a member of the `docs-content-enterprise` team will review your changes.
|
||||
|
||||
- If the change is urgent, post in `#docs-content-enterprise` on Slack.
|
||||
- Review the [style guide for release notes](https://docs.github.com/en/contributing/style-guide-and-content-model/style-guide#release-notes).
|
||||
- If you're updating or adding a note, add a datestamp in the format `[Updated: YYYY-MM-DD]`.
|
||||
- If you're removing a note, add an [Errata](https://docs.github.com/en/contributing/style-guide-and-content-model/style-guide#errata) section with details of the change.
|
||||
@ -0,0 +1,91 @@
|
||||
name: Confirm internal staff meant to post in public
|
||||
|
||||
# **What it does**: If a GitHub staff makes an issue/pull request in the open-source repo, creates an issue in the internal one to verify intent.
|
||||
# **Why we have it**: We don't want GitHub staff accidentally making issues/pull requests in the wrong repository.
|
||||
# **Who does it impact**: GitHub staff.
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
- transferred
|
||||
# Required in lieu of `pull_request` so that this workflow can query users in org to determine membership.
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check-team-membership:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
if: github.repository == 'github/docs' && github.actor != 'docs-bot'
|
||||
steps:
|
||||
- id: membership_check
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3
|
||||
env:
|
||||
TEAM_CONTENT_REPO: ${{ secrets.TEAM_CONTENT_REPO }}
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
// Only perform this action with GitHub employees
|
||||
try {
|
||||
await github.rest.teams.getMembershipForUserInOrg({
|
||||
org: 'github',
|
||||
team_slug: 'employees',
|
||||
username: context.payload.sender.login,
|
||||
});
|
||||
} catch(err) {
|
||||
// An error will be thrown if the user is not a GitHub employee
|
||||
// If a user is not a GitHub employee, we should stop here and
|
||||
// Not send a notification
|
||||
return
|
||||
}
|
||||
|
||||
// Don't perform this action with Docs team members
|
||||
try {
|
||||
await github.rest.teams.getMembershipForUserInOrg({
|
||||
org: 'github',
|
||||
team_slug: 'docs',
|
||||
username: context.payload.sender.login,
|
||||
});
|
||||
// If the user is a Docs team member, we should stop here and not send
|
||||
// a notification
|
||||
return
|
||||
} catch(err) {
|
||||
// An error will be thrown if the user is not a Docs team member
|
||||
// If a user is not a Docs team member we should continue and send
|
||||
// the notification
|
||||
}
|
||||
|
||||
const issueNo = context.number || context.issue.number
|
||||
|
||||
// Create an issue in our private repo
|
||||
await github.rest.issues.create({
|
||||
owner: 'github',
|
||||
repo: process.env.TEAM_CONTENT_REPO,
|
||||
title: `@${context.payload.sender.login} confirm that \#${issueNo} should be in the public github/docs repo`,
|
||||
body: `@${context.payload.sender.login} opened https://github.com/github/docs/issues/${issueNo} publicly in the github/docs repo, instead of the private github/${process.env.TEAM_CONTENT_REPO} repo.\n\n@${context.payload.sender.login}, please confirm that this belongs in the public repo and that no sensitive information was disclosed by commenting below and closing the issue.\n\nIf this was not intentional and sensitive information was shared, please delete https://github.com/github/docs/issues/${issueNo} and notify us in the \#docs-open-source channel.\n\nThanks!`,
|
||||
labels: ['OS confirmation', 'skip FR board'],
|
||||
});
|
||||
|
||||
core.setOutput('did_warn', 'true')
|
||||
|
||||
- name: Send Slack notification if a GitHub employee who isn't on the docs team opens an issue in public
|
||||
if: ${{ steps.membership_check.outputs.did_warn && github.repository == 'github/docs' }}
|
||||
uses: someimportantcompany/github-actions-slack-message@a975b440de2bcef178d451cc70d4c1161b5a30cd
|
||||
with:
|
||||
channel: ${{ secrets.DOCS_OPEN_SOURCE_SLACK_CHANNEL_ID }}
|
||||
bot-token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
text: <@${{github.actor}}> opened https://github.com/github/docs/issues/${{ github.event.number || github.event.issue.number }} publicly on the github/docs repo instead of a private repo. They have been notified via a new issue in the private repo to confirm this was intentional.
|
||||
|
||||
- name: Check out repo
|
||||
if: ${{ failure() && github.event_name != 'pull_request_target' }}
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: ./.github/actions/slack-alert
|
||||
if: ${{ failure() && github.event_name != 'pull_request_target' }}
|
||||
with:
|
||||
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
||||
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
@ -0,0 +1,55 @@
|
||||
name: 'Content Lint Markdown'
|
||||
|
||||
# **What it does**: Lints our content markdown to ensure the content matches the specified styleguide.
|
||||
# **Why we have it**: We want some level of consistency to our content markdown files.
|
||||
# **Who does it impact**: Docs content writers.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: The branch containing the changes we want to lint.
|
||||
required: true
|
||||
type: string
|
||||
default: main
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint-content:
|
||||
if: github.repository == 'github/docs-internal' || github.repository == 'github/docs'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
# Fetch 2 commits so tj-actions/changed-files can diff without extra API calls
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Set up Node and dependencies
|
||||
uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Get changed content/data files
|
||||
id: changed_files
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files: |
|
||||
content/**
|
||||
data/**
|
||||
|
||||
- name: Print content linter annotations if changed content/data files
|
||||
if: steps.changed_files.outputs.any_modified == 'true'
|
||||
env:
|
||||
CHANGED_FILES: ${{ steps.changed_files.outputs.all_modified_files }}
|
||||
# If there are errors, using `--print-annotations` will make it
|
||||
# so it does *not* exit non-zero.
|
||||
# This is so that all warnings and errors are printed.
|
||||
run: npm run lint-content -- --print-annotations --paths $CHANGED_FILES
|
||||
|
||||
- name: Run content linter if changed content/data files
|
||||
if: steps.changed_files.outputs.any_modified == 'true'
|
||||
env:
|
||||
CHANGED_FILES: ${{ steps.changed_files.outputs.all_modified_files }}
|
||||
run: npm run lint-content -- --errors-only --paths $CHANGED_FILES
|
||||
@ -0,0 +1,48 @@
|
||||
name: 'Check content-linter rules docs'
|
||||
|
||||
# **What it does**: Makes sure the content-linter-rules.md is up-to-date.
|
||||
# **Why we have it**: So what's automated doesn't fall behind
|
||||
# **Who does it impact**: Docs content.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/content-linter/**'
|
||||
# In case imported markdownlint rules are updated
|
||||
- package-lock.json
|
||||
# In case manual changes are made to the content-linter-rules.md file
|
||||
- data/reusables/contributing/content-linter-rules.md
|
||||
# Self-test
|
||||
- .github/workflows/content-linter-rules-docs.yml
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check-content-linter-rules-docs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'github/docs-internal' || github.repository == 'github/docs'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Check that content-linter-rules.md is up-to-date
|
||||
run: npm run generate-content-linter-docs
|
||||
|
||||
- name: Fail if it isn't up-to-date
|
||||
run: |
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
git status
|
||||
git diff
|
||||
|
||||
# Some whitespace for the sake of the message below
|
||||
echo ""
|
||||
echo ""
|
||||
|
||||
echo "content-linter-rules.md is out of date."
|
||||
echo "Please run 'npm run generate-content-linter-docs' and commit the changes."
|
||||
exit 1;
|
||||
fi
|
||||
@ -0,0 +1,191 @@
|
||||
name: 'Content pipelines: Update content'
|
||||
|
||||
# **What it does**: On a schedule, runs the content pipeline update script for each
|
||||
# configured entry. The script clones each source repo, detects changes, and
|
||||
# runs a Copilot agent to update content articles. The workflow handles
|
||||
# branching, committing, and opening PRs.
|
||||
# **Why we have it**: Keeps reference documentation in sync with upstream source
|
||||
# docs without storing copies of those source docs in this repository.
|
||||
# **Who does it impact**: Docs content writers, docs engineering.
|
||||
#
|
||||
# To add a new entry, add it to src/content-pipelines/config.yml and to the matrix
|
||||
# `include` list below (only `id` is needed). The update logic lives in
|
||||
# src/content-pipelines/scripts/update.ts, which reads config.yml for all other
|
||||
# values. Run locally: npx tsx src/content-pipelines/scripts/update.ts --help
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '20 16 * * 1-5' # Mon-Fri at 16:20 UTC
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
HUSKY: 0
|
||||
|
||||
jobs:
|
||||
update:
|
||||
if: github.repository == 'github/docs-internal'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Each entry only needs `id`. Everything else (source-repo,
|
||||
# source-path, target-articles, etc.) is read from
|
||||
# src/content-pipelines/config.yml by the update script.
|
||||
- id: copilot-cli
|
||||
# - id: mcp-server
|
||||
|
||||
steps:
|
||||
- name: Checkout docs-internal
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Install Copilot CLI
|
||||
run: npm install -g @github/copilot@prerelease
|
||||
|
||||
- name: Derive branch name
|
||||
id: branch
|
||||
run: echo "update_branch=docs/content-pipeline-${{ matrix.id }}-update" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Check for existing PR
|
||||
id: check-pr
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
UPDATE_BRANCH: ${{ steps.branch.outputs.update_branch }}
|
||||
run: |
|
||||
PR_NUMBER=$(gh pr list --head "$UPDATE_BRANCH" --state open --json number --jq '.[0].number // empty' 2>/dev/null || echo "")
|
||||
echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Setup branch
|
||||
id: setup-branch
|
||||
env:
|
||||
UPDATE_BRANCH: ${{ steps.branch.outputs.update_branch }}
|
||||
PR_NUMBER: ${{ steps.check-pr.outputs.pr_number }}
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
if git ls-remote --exit-code --heads origin "$UPDATE_BRANCH" > /dev/null 2>&1; then
|
||||
git fetch --unshallow origin "$UPDATE_BRANCH" main 2>/dev/null || git fetch origin "$UPDATE_BRANCH" main
|
||||
git checkout "$UPDATE_BRANCH"
|
||||
git merge origin/main --no-edit || {
|
||||
echo "Merge conflict with main — resetting branch to main"
|
||||
git merge --abort 2>/dev/null || true
|
||||
git checkout -f main
|
||||
git branch -D "$UPDATE_BRANCH"
|
||||
if [ -z "$PR_NUMBER" ]; then
|
||||
git push origin --delete "$UPDATE_BRANCH" || true
|
||||
else
|
||||
echo "Skipping remote branch delete — PR #$PR_NUMBER is open"
|
||||
echo "force_push=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
git checkout -b "$UPDATE_BRANCH"
|
||||
}
|
||||
else
|
||||
git checkout -b "$UPDATE_BRANCH"
|
||||
fi
|
||||
|
||||
- name: Run content pipeline update script
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.DOCS_BOT_PAT_COPILOT }}
|
||||
run: npx tsx src/content-pipelines/scripts/update.ts --id "${{ matrix.id }}"
|
||||
|
||||
- name: Commit changes
|
||||
id: commit
|
||||
env:
|
||||
ID: ${{ matrix.id }}
|
||||
run: |
|
||||
git add content/ data/
|
||||
if git diff --cached --quiet; then
|
||||
echo "has_changes=false" >> "$GITHUB_OUTPUT"
|
||||
echo "No documentation changes to commit"
|
||||
else
|
||||
git add "src/content-pipelines/state/${ID}.sha"
|
||||
git commit -m "docs: update ${ID} content from source docs" \
|
||||
-m "Updated by the content-pipeline-update agent (${ID}) via GitHub Actions." \
|
||||
-m "Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
echo "has_changes=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Push changes
|
||||
if: steps.commit.outputs.has_changes == 'true'
|
||||
env:
|
||||
UPDATE_BRANCH: ${{ steps.branch.outputs.update_branch }}
|
||||
FORCE_PUSH: ${{ steps.setup-branch.outputs.force_push }}
|
||||
run: |
|
||||
if [ "$FORCE_PUSH" = "true" ]; then
|
||||
echo "Force-pushing to align branch after merge conflict reset"
|
||||
git push --force-with-lease origin "$UPDATE_BRANCH"
|
||||
else
|
||||
git push origin "$UPDATE_BRANCH"
|
||||
fi
|
||||
|
||||
- name: Read source repo info from config
|
||||
id: source-info
|
||||
env:
|
||||
PIPELINE_ID: ${{ matrix.id }}
|
||||
run: |
|
||||
SOURCE_REPO=$(yq -r ".[\"${PIPELINE_ID}\"].\"source-repo\"" src/content-pipelines/config.yml)
|
||||
SOURCE_PATH=$(yq -r ".[\"${PIPELINE_ID}\"].\"source-path\"" src/content-pipelines/config.yml)
|
||||
echo "source_repo=$SOURCE_REPO" >> "$GITHUB_OUTPUT"
|
||||
echo "source_path=$SOURCE_PATH" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Create or update PR
|
||||
if: steps.commit.outputs.has_changes == 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
UPDATE_BRANCH: ${{ steps.branch.outputs.update_branch }}
|
||||
PIPELINE_ID: ${{ matrix.id }}
|
||||
SOURCE_REPO: ${{ steps.source-info.outputs.source_repo }}
|
||||
SOURCE_PATH: ${{ steps.source-info.outputs.source_path }}
|
||||
run: |
|
||||
PR_NUMBER="${{ steps.check-pr.outputs.pr_number }}"
|
||||
PR_TITLE="docs: update ${PIPELINE_ID} content from source docs"
|
||||
SOURCE_LINK="See the [upstream repo](https://github.com/${SOURCE_REPO}/tree/main/${SOURCE_PATH}) for changes that triggered this update."
|
||||
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
echo "PR #$PR_NUMBER already exists"
|
||||
|
||||
echo "Ensuring PR #$PR_NUMBER is marked ready for review"
|
||||
gh pr ready "$PR_NUMBER" || echo "Unable to mark PR #$PR_NUMBER as ready (it may already be ready)"
|
||||
else
|
||||
echo "Creating new PR"
|
||||
|
||||
PR_BODY="_GitHub Copilot generated this pull request._"$'\n\n'
|
||||
PR_BODY+="> [!NOTE]"$'\n'
|
||||
PR_BODY+="> This PR is **automatically generated** by the [content pipeline update workflow](${{ github.server_url }}/${{ github.repository }}/actions/workflows/content-pipelines.yml). Each run adds a new commit with any documentation changes detected."$'\n\n'
|
||||
PR_BODY+="## What this does"$'\n\n'
|
||||
PR_BODY+="Runs the \`content-pipeline-update\` agent (${PIPELINE_ID}) against the latest source docs and updates official articles under \`content/\` that have fallen out of sync."$'\n\n'
|
||||
PR_BODY+="## Source changes"$'\n\n'
|
||||
PR_BODY+="${SOURCE_LINK}"$'\n\n'
|
||||
PR_BODY+="## Review"$'\n\n'
|
||||
PR_BODY+="* Review each commit for accuracy — the agent uses AI, so spot-check important changes"$'\n'
|
||||
PR_BODY+="* To adjust agent behavior, see [Modifying results](${{ github.server_url }}/${{ github.repository }}/blob/main/src/content-pipelines/README.md#modifying-results)"$'\n'
|
||||
PR_BODY+="* Once satisfied, merge to keep docs up to date"$'\n'
|
||||
PR_BODY+="* A new PR will be created on the next run if there are further changes"
|
||||
|
||||
gh pr create \
|
||||
--title "$PR_TITLE" \
|
||||
--body "$PR_BODY" \
|
||||
--base main \
|
||||
--head "$UPDATE_BRANCH" \
|
||||
--label "workflow-generated,content-pipeline-update,ready-for-doc-review,skip FR board"
|
||||
fi
|
||||
|
||||
- uses: ./.github/actions/slack-alert
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
||||
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
|
||||
- uses: ./.github/actions/create-workflow-failure-issue
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
@ -0,0 +1,53 @@
|
||||
# Copilot cloud agent setup steps
|
||||
#
|
||||
# This is a special-name workflow recognized by Copilot cloud agent.
|
||||
# When a cloud agent session starts (via GitHub issue assignment or the
|
||||
# Copilot UI), these steps run first to bootstrap the development
|
||||
# environment before the agent begins working.
|
||||
#
|
||||
# The workflow_dispatch trigger allows manual testing of the setup steps.
|
||||
# This is NOT a regular CI workflow — it does not run on push or PR events.
|
||||
#
|
||||
# See also:
|
||||
# .github/copilot-instructions.md — always-on agent instructions
|
||||
# .github/instructions/ — contextual instruction files
|
||||
# .github/prompts/ — on-demand prompt files (e.g. /code-review)
|
||||
|
||||
name: 'Copilot Setup Steps'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
copilot-setup-steps:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'github/docs-internal' || github.repository == 'github/docs'
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
env:
|
||||
ELASTICSEARCH_URL: http://localhost:9200/
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
# Search and language test suites require a running Elasticsearch instance.
|
||||
- uses: ./.github/actions/setup-elasticsearch
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
|
||||
# docs-internal has early-access content that must be fetched separately.
|
||||
- uses: ./.github/actions/get-docs-early-access
|
||||
if: ${{ github.repository == 'github/docs-internal' }}
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
|
||||
# Many test suites depend on Next.js build artifacts.
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
# Populate Elasticsearch with fixture data so search/language tests work.
|
||||
- name: Index fixtures into the local Elasticsearch
|
||||
run: npm run index-test-fixtures
|
||||
@ -0,0 +1,81 @@
|
||||
name: Copy to API/events issue to docs-content
|
||||
|
||||
# **What it does**: Copies an issue in the open source repo to the docs-content repo, comments on and closes the original issue
|
||||
# **Why we have it**: OpenAPI/GraphQL schema updates cannot be made in the open source repo. Instead, we copy the issue to an internal issue (we do not transfer so that the issue does not disappear for the contributor) and close the original issue.
|
||||
# **Who does it impact**: Open source and docs-content maintainers
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- labeled
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
transfer-issue:
|
||||
name: Transfer issue
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.label.name == 'fix-internally' && github.repository == 'github/docs'
|
||||
steps:
|
||||
- name: Check if this run was triggered by a member of the docs team
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3
|
||||
id: triggered-by-member
|
||||
with:
|
||||
github-token: ${{secrets.DOCS_BOT_PAT_BASE}}
|
||||
result-encoding: string
|
||||
script: |
|
||||
const triggerer_login = context.payload.sender.login
|
||||
const teamMembers = await github.request(
|
||||
`/orgs/github/teams/docs/members?per_page=100`
|
||||
)
|
||||
const logins = teamMembers.data.map(member => member.login)
|
||||
if (logins.includes(triggerer_login)) {
|
||||
console.log(`This workflow was triggered by ${triggerer_login} (on the docs team).`)
|
||||
return 'true'
|
||||
}
|
||||
console.log(`This workflow was triggered by ${triggerer_login} (not on the docs team), so no action will be taken.`)
|
||||
return 'false'
|
||||
|
||||
- name: Exit if not triggered by a docs team member
|
||||
if: steps.triggered-by-member.outputs.result == 'false'
|
||||
run: |
|
||||
echo Aborting. This workflow must be triggered by a member of the docs team.
|
||||
exit 1
|
||||
|
||||
- name: Create an issue in the docs-content repo
|
||||
run: |
|
||||
new_issue_url="$(gh issue create --title "$ISSUE_TITLE" --body "$ISSUE_BODY" --repo github/docs-content --label "workflow-generated")"
|
||||
echo 'NEW_ISSUE='$new_issue_url >> $GITHUB_ENV
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.DOCS_BOT_PAT_BASE}}
|
||||
ISSUE_TITLE: ${{ github.event.issue.title }}
|
||||
ISSUE_BODY: ${{ github.event.issue.body }}
|
||||
|
||||
- name: Comment on the old issue
|
||||
run: gh issue comment $OLD_ISSUE --body "Thank you for opening this issue! Updates to this documentation must be made internally. I have copied your issue to an internal issue, so I will close this issue."
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.DOCS_BOT_PAT_BASE}}
|
||||
OLD_ISSUE: ${{ github.event.issue.html_url }}
|
||||
|
||||
- name: Close the old issue
|
||||
run: gh issue close $OLD_ISSUE
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.DOCS_BOT_PAT_BASE}}
|
||||
OLD_ISSUE: ${{ github.event.issue.html_url }}
|
||||
|
||||
- name: Comment on the new issue
|
||||
run: gh issue comment $NEW_ISSUE --body "This issue was originally opened in the open source repo as $OLD_ISSUE"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.DOCS_BOT_PAT_BASE}}
|
||||
NEW_ISSUE: ${{ env.NEW_ISSUE }}
|
||||
OLD_ISSUE: ${{ github.event.issue.html_url }}
|
||||
|
||||
- name: Check out repo
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' && github.repository == 'github/docs-internal' }}
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: ./.github/actions/slack-alert
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' && github.repository == 'github/docs-internal' }}
|
||||
with:
|
||||
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
||||
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
@ -0,0 +1,44 @@
|
||||
name: Count translation corruptions
|
||||
|
||||
# **What it does**: Generates a summary of Liquid corruptions per language.
|
||||
# **Why we have it**: For insights into the state of translations and things we can do to fix them
|
||||
# **Who does it impact**: Engineering
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- src/languages/scripts/count-translation-corruptions.ts
|
||||
- src/languages/lib/correct-translation-content.ts
|
||||
- .github/workflows/count-translation-corruptions.yml
|
||||
- .github/actions/node-npm-setup/action.yml
|
||||
- .github/actions/clone-translations/action.yml
|
||||
- 'package**.json'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
count-translation-corruptions:
|
||||
if: github.repository == 'github/docs-internal'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout English repo
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
# Using a PAT is necessary so that the new commit will trigger the
|
||||
# CI in the PR. (Events from GITHUB_TOKEN don't trigger new workflows.)
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
|
||||
# It's important because translations are often a bit behind.
|
||||
# So if a translation is a bit behind, it might still be referencing
|
||||
# an asset even though none of the English content does.
|
||||
- name: Clone all translations
|
||||
uses: ./.github/actions/clone-translations
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Run count
|
||||
run: npm run count-translation-corruptions
|
||||
@ -0,0 +1,171 @@
|
||||
name: Create a PR to add an entry to the CHANGELOG.md file in this repo
|
||||
|
||||
# **What it does**: If a member of the github org posts a changelog comment, it creates a PR to update the CHANGELOG.md file.
|
||||
# **Why we have it**: This surfaces docs changelog details publicly.
|
||||
# **Who does it impact**: GitHub users and staff.
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
CHANGELOG_FILE: CHANGELOG.md
|
||||
CHANGELOG_FILE_URL: https://github.com/github/docs-internal/blob/main/CHANGELOG.md
|
||||
|
||||
jobs:
|
||||
docs-changelog-pr:
|
||||
if: ${{ github.repository == 'github/docs-internal' && github.event.issue.pull_request }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- name: 'Ensure ${{ env.CHANGELOG_FILE }} exists'
|
||||
run: |
|
||||
if [ ! -f ${{ env.CHANGELOG_FILE }} ]; then
|
||||
echo "${{ env.CHANGELOG_FILE }} is missing at the root of the repository."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Check that the user belongs to the github org
|
||||
id: hubber_check
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
try {
|
||||
await github.rest.teams.getMembershipForUserInOrg({
|
||||
org: 'github',
|
||||
team_slug: 'employees',
|
||||
username: context.payload.sender.login,
|
||||
});
|
||||
core.exportVariable('CONTINUE_WORKFLOW', 'true');
|
||||
} catch(err) {
|
||||
core.info("Workflow triggered by a comment, but the commenter is not a Hubber. Exiting.");
|
||||
core.exportVariable('CONTINUE_WORKFLOW', 'false');
|
||||
}
|
||||
|
||||
- name: Check if comment starts with '## Changelog summary'
|
||||
if: env.CONTINUE_WORKFLOW == 'true'
|
||||
id: check_summary
|
||||
env:
|
||||
COMMENT_BODY: ${{ github.event.comment.body }}
|
||||
run: |
|
||||
# Get the first line of the comment and trim the leading/trailing whitespace:
|
||||
FIRST_LINE=$(printf "%s\n" "$COMMENT_BODY" | head -n1 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||
if [[ "$FIRST_LINE" != '## Changelog summary' ]]; then
|
||||
echo "FIRST_LINE=|$FIRST_LINE|"
|
||||
echo "The pull request comment is not a changelog summary. Exiting."
|
||||
echo "CONTINUE_WORKFLOW=false" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Create changelog text
|
||||
if: env.CONTINUE_WORKFLOW == 'true'
|
||||
id: create_text
|
||||
env:
|
||||
COMMENT_BODY: ${{ github.event.comment.body }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
DATE=$(date +"**%-d %B %Y**")
|
||||
BODY="$(printf "%s\n" "$COMMENT_BODY" | tail -n +2)"
|
||||
CHANGELOG_TEXT="$(printf "%s\n" "$BODY" | awk '/^:writing_hand:/{exit} {print}')"
|
||||
{
|
||||
echo "$DATE"
|
||||
echo -e "$CHANGELOG_TEXT\n<hr>"
|
||||
} > changelog_entry.txt
|
||||
|
||||
- name: Set up git
|
||||
if: env.CONTINUE_WORKFLOW == 'true'
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Prepare branch
|
||||
if: env.CONTINUE_WORKFLOW == 'true'
|
||||
run: |
|
||||
BRANCH="changelog-update-$(date +%s)"
|
||||
echo "BRANCH=$BRANCH" >> $GITHUB_ENV
|
||||
git checkout -b "$BRANCH"
|
||||
|
||||
# Insert new changelog entry after the first heading, as follows:
|
||||
# Print the first line of the existing CHANGELOG.md file into a `tmp` file, followed by an empty line.
|
||||
# Then, print the contents of `changelog_entry.txt` into the `tmp` file.
|
||||
# Then, print the rest of the existing CHANGELOG.md file into the `tmp` file.
|
||||
# Finally, replace the existing CHANGELOG.md file with the `tmp` file.
|
||||
awk 'NR==1{print; print ""; while ((getline line < "changelog_entry.txt") > 0) print line; next}1' CHANGELOG.md > tmp && mv tmp CHANGELOG.md
|
||||
|
||||
git add CHANGELOG.md
|
||||
git commit -m "Update changelog for $(head -n1 changelog_entry.txt)"
|
||||
git push origin "$BRANCH"
|
||||
|
||||
- name: Create a pull request
|
||||
if: env.CONTINUE_WORKFLOW == 'true'
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3
|
||||
id: create_pull_request
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
const { data: pullRequest } = await github.rest.pulls.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
title: `Update docs changelog (for PR #${context.payload.issue.number})`,
|
||||
body: `### Automated docs changelog update\n\n**Purpose:** Update the <code>[${{ env.CHANGELOG_FILE }}](${{ env.CHANGELOG_FILE_URL }})</code> file with details of a recent docs change.\n\nThis PR is an automated update, generated by the <code>create-changelog-pr.yml</code> Actions workflow as a result of a "Changelog summary" comment being added to [PR #${context.payload.issue.number}](${context.payload.issue.html_url}).\n\n**Notes for reviewer**:\n- This change to the <code>[${{ env.CHANGELOG_FILE }}](${{ env.CHANGELOG_FILE_URL }})</code> file will be synced to the public docs site, so make sure that the content of the entry is appropriate for public consumption. If the content is wholly inappropriate for public consumption, then this PR can be closed.\n- Make sure the format of this changelog entry is consistent with the other entries in the file.\n\n<details><summary>Original PR comment posted by @${context.payload.comment.user.login}, using the <code>/changelog</code> slash command:</summary>\n\n${context.payload.comment.body}</details>`,
|
||||
head: process.env.BRANCH,
|
||||
base: 'main'
|
||||
});
|
||||
|
||||
core.setOutput('pull-request-number', pullRequest.number);
|
||||
core.setOutput('pull-request-url', pullRequest.html_url);
|
||||
|
||||
- name: Add 'ready-for-doc-review' and 'skip FR board' labels to PR
|
||||
if: env.CONTINUE_WORKFLOW == 'true'
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3
|
||||
env:
|
||||
# Get the number of the PR that was just created:
|
||||
PULL_REQUEST_NUMBER: ${{ steps.create_pull_request.outputs.pull-request-number }}
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: Number(process.env.PULL_REQUEST_NUMBER),
|
||||
labels: ['ready-for-doc-review','skip FR board']
|
||||
});
|
||||
|
||||
- name: Assign PR to commenter
|
||||
if: env.CONTINUE_WORKFLOW == 'true'
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3
|
||||
env:
|
||||
# Reuse the PR number captured earlier
|
||||
PULL_REQUEST_NUMBER: ${{ steps.create_pull_request.outputs.pull-request-number }}
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
try {
|
||||
const username = context.payload.comment.user.login;
|
||||
await github.rest.issues.addAssignees({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: Number(process.env.PULL_REQUEST_NUMBER),
|
||||
assignees: [username]
|
||||
});
|
||||
} catch (err) {
|
||||
core.info(`Failed to assign PR to @${context.payload.comment.user.login}: ${err.message}`);
|
||||
}
|
||||
|
||||
- uses: ./.github/actions/slack-alert
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
||||
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
|
||||
- uses: ./.github/actions/create-workflow-failure-issue
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
@ -0,0 +1,168 @@
|
||||
name: Delete orphan translation files
|
||||
|
||||
# **What it does**:
|
||||
# Compares content & data files left in each translation that aren't
|
||||
# in docs-internal. Then creates a PR to delete these files.
|
||||
# **Why we have it**:
|
||||
# When Juno dumps to each translation repo it can not account for the
|
||||
# fact that files in docs-internal get moved or deleted. So the
|
||||
# sum total of files constantly grows.
|
||||
# This leads to excess files in each translation repo that are not
|
||||
# ever used but has to be put into every production build.
|
||||
# **Who does it impact**: Docs engineering
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '20 16 * * 1' # Run every Monday at 16:20 UTC / 8:20 PST
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
delete-orphan-translation-files:
|
||||
if: github.repository == 'github/docs-internal'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- language: zh
|
||||
language_dir: translations/zh-cn
|
||||
language_repo: github/docs-internal.zh-cn
|
||||
|
||||
- language: es
|
||||
language_dir: translations/es-es
|
||||
language_repo: github/docs-internal.es-es
|
||||
|
||||
- language: pt
|
||||
language_dir: translations/pt-br
|
||||
language_repo: github/docs-internal.pt-br
|
||||
|
||||
- language: ru
|
||||
language_dir: translations/ru-ru
|
||||
language_repo: github/docs-internal.ru-ru
|
||||
|
||||
- language: ja
|
||||
language_dir: translations/ja-jp
|
||||
language_repo: github/docs-internal.ja-jp
|
||||
|
||||
- language: fr
|
||||
language_dir: translations/fr-fr
|
||||
language_repo: github/docs-internal.fr-fr
|
||||
|
||||
- language: de
|
||||
language_dir: translations/de-de
|
||||
language_repo: github/docs-internal.de-de
|
||||
|
||||
- language: ko
|
||||
language_dir: translations/ko-kr
|
||||
language_repo: github/docs-internal.ko-kr
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- name: Checkout the language-specific repo
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
repository: ${{ matrix.language_repo }}
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
path: ${{ matrix.language_dir }}
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Delete orphan files
|
||||
run: |
|
||||
npm run delete-orphan-translation-files -- ${{ matrix.language_dir }}
|
||||
|
||||
- name: Debug deleted files
|
||||
working-directory: ${{ matrix.language_dir }}
|
||||
run: git status
|
||||
|
||||
- name: Git config
|
||||
working-directory: ${{ matrix.language_dir }}
|
||||
run: |
|
||||
git config --global user.name "docs-bot"
|
||||
git config --global user.email "77750099+docs-bot@users.noreply.github.com"
|
||||
|
||||
- name: Git commit and push, create and merge PR
|
||||
working-directory: ${{ matrix.language_dir }}
|
||||
env:
|
||||
# Needed for gh
|
||||
GH_TOKEN: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
run: |
|
||||
# If nothing to commit, exit now. It's fine. No orphans.
|
||||
changes=$(git diff --name-only | wc -l)
|
||||
untracked=$(git status --untracked-files --short | wc -l)
|
||||
if [[ $changes -eq 0 ]] && [[ $untracked -eq 0 ]]; then
|
||||
echo "There are no changes to commit or untracked files. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Create a general retry function that retries and sleeps
|
||||
retry_command() {
|
||||
local max_attempts=3
|
||||
local attempt=1
|
||||
|
||||
while [ $attempt -le $max_attempts ]; do
|
||||
echo "Attempt $attempt: $@"
|
||||
"$@" && return 0
|
||||
((attempt++))
|
||||
sleep 3 # You can adjust the sleep duration as needed
|
||||
done
|
||||
|
||||
echo "Max attempts reached. Command failed after $max_attempts attempts."
|
||||
return 1
|
||||
}
|
||||
|
||||
git status
|
||||
current_timestamp=$(date '+%Y-%m-%d-%H%M%S')
|
||||
branch_name="delete-orphan-files-$current_timestamp"
|
||||
git checkout -b "$branch_name"
|
||||
current_daystamp=$(date '+%Y-%m-%d')
|
||||
git commit -a -m "Delete orphan files ($current_daystamp)"
|
||||
git push origin "$branch_name"
|
||||
|
||||
# Create PR
|
||||
echo "Creating pull request..."
|
||||
gh pr create \
|
||||
--title "Delete orphan files ($current_daystamp)" \
|
||||
--body '👋 humans. This PR was generated from docs-internal/.github/workflows/delete-orphan-translation-files.yml.
|
||||
' \
|
||||
--repo "${{ matrix.language_repo }}" \
|
||||
--label "workflow-generated" \
|
||||
--head=$branch_name
|
||||
echo "Merge created PR..."
|
||||
# Prefer enabling auto-merge so the PR waits for any required
|
||||
# checks before merging. If auto-merge can't be enabled — usually
|
||||
# because all required checks completed before this step ran and
|
||||
# the PR is already immediately mergeable — fall back to a direct
|
||||
# merge. GitHub returns one of these misleading errors in that
|
||||
# case: "Branch does not have required protected branch rules",
|
||||
# "Pull request is in unstable status", or "Pull request is not
|
||||
# in a mergeable state".
|
||||
auto_merge_err=$(mktemp)
|
||||
trap 'rm -f "$auto_merge_err"' EXIT
|
||||
if retry_command gh pr merge --merge --auto --delete-branch "$branch_name" 2>"$auto_merge_err"; then
|
||||
:
|
||||
else
|
||||
cat "$auto_merge_err"
|
||||
if grep -qE "does not have required protected branch rules|unstable status|Pull request is not in a mergeable state" "$auto_merge_err"; then
|
||||
echo "Auto-merge unavailable; PR appears immediately mergeable. Falling back to direct merge."
|
||||
retry_command gh pr merge --merge --delete-branch "$branch_name"
|
||||
else
|
||||
echo "Auto-merge failed with an unexpected error."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
- uses: ./.github/actions/slack-alert
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
||||
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
|
||||
- uses: ./.github/actions/create-workflow-failure-issue
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
@ -0,0 +1,54 @@
|
||||
name: Add docs-reviewers request to the docs-content review board
|
||||
|
||||
# **What it does**: Adds PRs in github/github and github/audit-log-allowlists that requested a review from docs-reviewers to the docs-content review board
|
||||
# **Why we have it**: To catch docs-reviewers requests in github/audit-log-allowlists
|
||||
# **Who does it impact**: docs-content maintainers
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '20 16 * * 1-5' # Run Mon-Fri at 16:20 UTC / 8:20 PST
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
add-requests-to-board:
|
||||
name: Add requests to board
|
||||
if: ${{ github.repository == 'github/docs-internal' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out repo content
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
|
||||
with:
|
||||
node-version-file: 'package.json'
|
||||
cache: npm
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run script for audit-log-allowlists
|
||||
run: |
|
||||
npm run fr-add-docs-reviewers-requests
|
||||
env:
|
||||
TOKEN: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
PROJECT_NUMBER: 2936
|
||||
ORGANIZATION: 'github'
|
||||
REPO: 'audit-log-allowlists'
|
||||
REVIEWER: 'docs-reviewers'
|
||||
FEATURE: 'Audit log event descriptions'
|
||||
|
||||
- uses: ./.github/actions/slack-alert
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
||||
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
|
||||
- uses: ./.github/actions/create-workflow-failure-issue
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
@ -0,0 +1,66 @@
|
||||
name: Don't delete assets
|
||||
|
||||
# **What it does**:
|
||||
# If the PR (against main) involves deletion of assets, if any of
|
||||
# them are deletions or renames, post a comment, and ultimately
|
||||
# fail the check.
|
||||
# **Why we have it**:
|
||||
# If you delete the reference to an image, the English content is fine
|
||||
# because it no longer tries to serve an image that doesn't exist.
|
||||
# But this is not the case for translations.
|
||||
# **Who does it impact**: Docs content.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'assets/**'
|
||||
- '.github/workflows/dont-delete-assets.yml'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
dont-delete-assets:
|
||||
# It's 'docs-bot' that creates those PR from "Delete orphaned assets"
|
||||
if: github.event.pull_request.user.login != 'docs-bot' && (github.repository == 'github/docs-internal' || github.repository == 'github/docs')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Get comment markdown
|
||||
id: comment
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: npm run deleted-assets-pr-comment
|
||||
|
||||
- name: Find possible previous comment
|
||||
if: ${{ steps.comment.outputs.markdown != '' }}
|
||||
uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad
|
||||
id: findComment
|
||||
with:
|
||||
issue-number: ${{ github.event.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: '<!-- DELETED_ASSETS -->'
|
||||
|
||||
- name: Update comment
|
||||
if: ${{ steps.comment.outputs.markdown != '' }}
|
||||
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9
|
||||
with:
|
||||
comment-id: ${{ steps.findComment.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.number }}
|
||||
body: ${{ steps.comment.outputs.markdown }}
|
||||
edit-mode: replace
|
||||
|
||||
- name: Ultimately fail the workflow for attention
|
||||
if: ${{ steps.comment.outputs.markdown != '' }}
|
||||
run: |
|
||||
echo "More than 1 asset image was deleted as part of this PR."
|
||||
echo "See posted PR commented about how to get them back."
|
||||
exit 1
|
||||
@ -0,0 +1,66 @@
|
||||
name: Don't delete features
|
||||
|
||||
# **What it does**:
|
||||
# If the PR (against main) involves deletion of features, if any of
|
||||
# them are deletions or renames, post a comment, and ultimately
|
||||
# fail the check.
|
||||
# **Why we have it**:
|
||||
# If you delete the reference to an image, the English content is fine
|
||||
# because it no longer tries to use the feature that doesn't exist.
|
||||
# But this is not the case for translations.
|
||||
# **Who does it impact**: Docs content.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'data/features/**'
|
||||
- .github/workflows/dont-delete-features.yml
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
dont-delete-features:
|
||||
# It's 'docs-bot' that creates those PR from "Delete orphaned features"
|
||||
if: github.event.pull_request.user.login != 'docs-bot' && (github.repository == 'github/docs-internal' || github.repository == 'github/docs')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Get comment markdown
|
||||
id: comment
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: npm run deleted-features-pr-comment
|
||||
|
||||
- name: Find possible previous comment
|
||||
if: ${{ steps.comment.outputs.markdown != '' }}
|
||||
uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad
|
||||
id: findComment
|
||||
with:
|
||||
issue-number: ${{ github.event.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: '<!-- DELETED_FEATURES -->'
|
||||
|
||||
- name: Update comment
|
||||
if: ${{ steps.comment.outputs.markdown != '' }}
|
||||
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9
|
||||
with:
|
||||
comment-id: ${{ steps.findComment.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.number }}
|
||||
body: ${{ steps.comment.outputs.markdown }}
|
||||
edit-mode: replace
|
||||
|
||||
- name: Ultimately fail the workflow for attention
|
||||
if: ${{ steps.comment.outputs.markdown != '' }}
|
||||
run: |
|
||||
echo "More than 1 feature was deleted as part of this PR."
|
||||
echo "See posted PR commented about how to get them back."
|
||||
exit 1
|
||||
@ -0,0 +1,81 @@
|
||||
name: Enterprise date updater
|
||||
|
||||
# **What it does**: Runs on a schedule to update
|
||||
# src/ghes-releases/lib/enterprise-dates.json.
|
||||
# **Why we have it**: The src/ghes-releases/lib/enterprise-dates.json
|
||||
# file needs to be up-to-date for the
|
||||
# Used to display deprecation banner dates and as a reference
|
||||
# for all past server release numbers.
|
||||
# **Who does it impact**: Docs engineering, docs content.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '20 16 * * 1' # Run every Monday at 16:20 UTC / 8:20 PST
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
open_enterprise_issue:
|
||||
name: Enterprise date updater
|
||||
if: github.repository == 'github/docs-internal'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository code
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Run src/ghes-releases/scripts/update-enterprise-dates.ts
|
||||
run: npm run update-enterprise-dates
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
|
||||
- name: Create pull request
|
||||
id: create-pull-request
|
||||
uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # pin @v8.0.0
|
||||
env:
|
||||
# Disable pre-commit hooks; they don't play nicely here
|
||||
HUSKY: '0'
|
||||
with:
|
||||
# need to use a token with repo and workflow scopes for this step
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
commit-message: '🤖 ran src/ghes-releases/scripts/update-enterprise-dates.ts'
|
||||
title: 🤖 src/ghes-releases/lib/enterprise-dates.json update
|
||||
body:
|
||||
"Hello! The GitHub Enterprise Server release dates have changed.\n\n
|
||||
If CI passes, this PR will be auto-merged. :green_heart:\n\n
|
||||
If CI does not pass or other problems arise, contact #docs-engineering on slack.\n\nThis PR was 🤖-crafted by `.github/workflows/enterprise-dates.yml`. 🧶"
|
||||
branch: enterprise-server-dates-update
|
||||
delete-branch: true
|
||||
|
||||
- name: Enable GitHub auto-merge
|
||||
if: ${{ steps.create-pull-request.outputs.pull-request-number }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
AUTOMERGE_PR_NUMBER: ${{ steps.create-pull-request.outputs.pull-request-number }}
|
||||
run: npm run enable-automerge
|
||||
|
||||
- if: ${{ failure() }}
|
||||
name: Delete remote branch (if previous steps failed)
|
||||
run: git push origin --delete enterprise-server-dates-update
|
||||
|
||||
- if: ${{ steps.create-pull-request.outputs.pull-request-number }}
|
||||
name: Approve
|
||||
uses: juliangruber/approve-pull-request-action@dcc4effb325c0b503408619918d56e40653dcc91
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
number: ${{ steps.create-pull-request.outputs.pull-request-number }}
|
||||
|
||||
- uses: ./.github/actions/slack-alert
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
||||
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
|
||||
- uses: ./.github/actions/create-workflow-failure-issue
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
@ -0,0 +1,45 @@
|
||||
name: Open Enterprise release or deprecation issue
|
||||
|
||||
# **What it does**: Checks if there is an Enterprise release or deprecation upcoming, and if so, opens an issue with the tasks to be completed.
|
||||
# **Why we have it**: GHES releases and deprecations run on a predictable schedule, so we can automate some of the project management aspects.
|
||||
# **Who does it impact**: Docs engineering, docs content.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '20 16 * * 1' # Run every Monday at 16:20 UTC / 8:20 PST
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
open_enterprise_issue:
|
||||
name: Open Enterprise issue
|
||||
if: github.repository == 'github/docs-internal'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository code
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Create an enterprise release issue
|
||||
run: npm run create-enterprise-issue -- release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
|
||||
- name: Create an enterprise deprecation issue
|
||||
run: npm run create-enterprise-issue -- deprecation
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
|
||||
- uses: ./.github/actions/slack-alert
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
|
||||
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
|
||||
|
||||
- uses: ./.github/actions/create-workflow-failure-issue
|
||||
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
@ -0,0 +1,25 @@
|
||||
name: Expertise Required label message
|
||||
|
||||
# **What it does**: Adds a bot comment stating a certain level of expertise is required to a docs-content issue when the `contributor-expertise-required` label is applied
|
||||
# **Why we have it**: We need a method to surface a message denoting if an issue requires a certain level of expertise in order to be resolved
|
||||
# **Who does it impact**: Open Source and Hubbers
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- labeled
|
||||
|
||||
jobs:
|
||||
job:
|
||||
name: Comment on issue with expertise required message
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
if: github.event.label.name == 'contributor-expertise-required' && github.repository == 'github/docs'
|
||||
steps:
|
||||
- name: Comment on issue
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
issue: ${{ github.event.issue.html_url }}
|
||||
run: |
|
||||
gh issue comment $issue --body 'Addressing this issue will require additional expertise from the contributor. Please make sure to review the issue carefully before opening a PR and ask any questions you might have in the issue.'
|
||||
@ -0,0 +1,78 @@
|
||||
name: Feedback prompt for non-Docs team contributors when a PR is closed
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
comment-on-pr:
|
||||
# This workflow should only run on the 'github/docs-internal' repository because it posts a feedback request
|
||||
# to non-Docs team contributors when their PR is merged into the main branch.
|
||||
# The feedback request asks contributors to leave feedback on their contributing experience in Slack.
|
||||
if: github.repository == 'github/docs-internal' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check if PR author is in docs-content team
|
||||
id: check_team
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
try {
|
||||
const pr = context.payload.pull_request;
|
||||
await github.rest.teams.getMembershipForUserInOrg({
|
||||
org: 'github',
|
||||
team_slug: 'docs-content',
|
||||
username: pr.user.login,
|
||||
});
|
||||
// Author is in the team. Do nothing!
|
||||
} catch(err) {
|
||||
// Author not in team
|
||||
core.exportVariable('NON_DOCS_HUBBER', 'true');
|
||||
}
|
||||
|
||||
- name: Post changelog instructions comment
|
||||
|
||||
if: env.NON_DOCS_HUBBER == 'true'
|
||||
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
github-token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const prAuthor = pr.user.login;
|
||||
const assignees = (pr.assignees ?? [])
|
||||
.filter(a => a.login.toLowerCase() !== "copilot")
|
||||
.map(a => "@" + a.login)
|
||||
.join(" ");
|
||||
|
||||
let commentBody;
|
||||
if (assignees) {
|
||||
commentBody =
|
||||
"👋 " + assignees +
|
||||
" - Thanks for your contribution! " +
|
||||
"If you think something could be improved about the contributor experience, please post in `#docs-contributor-feedback` on Slack.";
|
||||
} else if (prAuthor.toLowerCase() !== "copilot") {
|
||||
commentBody =
|
||||
"👋 @" + prAuthor +
|
||||
" - Thanks for your contribution! " +
|
||||
"If you think something could be improved about the contributor experience, please post in `#docs-contributor-feedback` on Slack.";
|
||||
} else {
|
||||
// nobody to mention!
|
||||
commentBody =
|
||||
"👋 Thanks for your contribution! " +
|
||||
"If you think something could be improved about the contributor experience, please post in `#docs-contributor-feedback` on Slack.";
|
||||
}
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: commentBody
|
||||
});
|
||||
@ -0,0 +1,56 @@
|
||||
name: Add maintenance PRs to the docs-content FR project v2
|
||||
|
||||
# **What it does**: Adds docs-internal pull requests authored by docs-bot to the docs-content FR project v2
|
||||
# **Why we have it**: So we don't lose track of maintenance pull requests for docs-content to review
|
||||
# **Who does it impact**: Docs content
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- reopened
|
||||
- opened
|
||||
- ready_for_review
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
repository-projects: write
|
||||
|
||||
jobs:
|
||||
first-responder-triage-pr:
|
||||
name: Add maintenance PR to FR project v2
|
||||
if: github.repository == 'github/docs-internal' && github.event.pull_request.draft == false && github.event.pull_request.user.id == 77750099 && github.event.pull_request.head.ref != 'repo-sync' && !contains(github.event.pull_request.labels.*.name, 'skip FR board')
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
# Add to the FR project
|
||||
# and set type to "Maintenance"
|
||||
# and set date to now
|
||||
- name: Triage to docs-content FR project
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
PROJECT_NUMBER: 11672
|
||||
PROJECT_ID: PVT_kwDNJr_OAGNkBg
|
||||
TYPE_FIELD_ID: PVTSSF_lADNJr_OAGNkBs4D-Nyn
|
||||
DATE_FIELD_ID: PVTF_lADNJr_OAGNkBs4D-N1h
|
||||
TYPE_FIELD_VALUE: 3f142cf2
|
||||
run: |
|
||||
echo "Adding item to project..."
|
||||
|
||||
ITEM_ID=$(gh project item-add $PROJECT_NUMBER --owner github --url $PR_URL --format json | jq .id)
|
||||
|
||||
echo "Editing type..."
|
||||
|
||||
gh project item-edit --project-id $PROJECT_ID --id $ITEM_ID --field-id $TYPE_FIELD_ID --single-select-option-id $TYPE_FIELD_VALUE
|
||||
|
||||
echo "Editing date..."
|
||||
|
||||
DATE=$(date '+%Y-%m-%d')
|
||||
|
||||
gh project item-edit --project-id $PROJECT_ID --id $ITEM_ID --field-id $DATE_FIELD_ID --date $DATE
|
||||
|
||||
echo "done editing"
|
||||
@ -0,0 +1,262 @@
|
||||
name: Generate code scanning query lists
|
||||
|
||||
# **What it does**: This workflow is currently run manually approximately every two weeks as part
|
||||
# of the release process for the CodeQL CLI. We hope to automate this in the future
|
||||
# When run, this workflow generates updated query lists with data from the codeql
|
||||
# repository, and creates a pull request if there are updates.
|
||||
# **Why we have it**: So we can automate CodeQL query tables and show code scanning users the built in queries.
|
||||
# **Who does it impact**: Anyone making CodeQL query suite changes in `github/codeql`, and wanting to get them published on the docs site.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
SOURCE_BRANCH:
|
||||
description: 'Branch to pull the source files from in the codeql repo (for example codeql-cli-2.x.x).'
|
||||
type: string
|
||||
required: true
|
||||
default: 'main'
|
||||
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/generate-code-scanning-query-lists.yml
|
||||
- src/codeql-queries/scripts/generate-code-scanning-query-list.ts
|
||||
- src/codeql-queries/scripts/generate-code-quality-query-list.ts
|
||||
- .github/actions/install-cocofix/action.yml
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
generate-security-query-lists:
|
||||
if: github.repository == 'github/docs-internal'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository code
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Checkout codeql repo
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
repository: github/codeql
|
||||
path: codeql
|
||||
ref: ${{ inputs.SOURCE_BRANCH || 'main' }}
|
||||
|
||||
- name: Get the codeql SHA being synced
|
||||
id: codeql
|
||||
shell: bash
|
||||
run: |
|
||||
cd codeql
|
||||
OPENAPI_COMMIT_SHA=$(git rev-parse HEAD)
|
||||
echo "OPENAPI_COMMIT_SHA=$OPENAPI_COMMIT_SHA" >> $GITHUB_OUTPUT
|
||||
echo "Copied files from github/codeql repo. Commit SHA: $OPENAPI_COMMIT_SHA"
|
||||
|
||||
- name: Download CodeQL CLI
|
||||
# Look under the `codeql` directory, as this is where we checked out the `github/codeql` repo
|
||||
uses: ./codeql/.github/actions/fetch-codeql
|
||||
|
||||
- name: Test CodeQL CLI Download
|
||||
shell: bash
|
||||
run: codeql --version
|
||||
|
||||
# "Server for running multiple commands while avoiding repeated JVM initialization."
|
||||
# Having started this should speed up the execution of the various
|
||||
# CLI calls of the executable.
|
||||
- name: Start CodeQL CLI server in the background
|
||||
shell: bash
|
||||
run: |
|
||||
codeql execute cli-server &
|
||||
sleep 3
|
||||
codeql --version
|
||||
|
||||
- uses: ./.github/actions/install-cocofix
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
|
||||
- name: Build code scanning security query lists
|
||||
shell: bash
|
||||
run: |
|
||||
for lang in "actions" "cpp" "csharp" "go" "java" "javascript" "python" "ruby" "rust" "swift"; do
|
||||
echo "Generating code scanning query list for $lang"
|
||||
npm run generate-code-scanning-query-list -- \
|
||||
--verbose \
|
||||
--codeql-path codeql \
|
||||
--codeql-dir codeql \
|
||||
-o data/reusables/code-scanning/codeql-query-tables/$lang.md \
|
||||
$lang
|
||||
done
|
||||
|
||||
- name: Upload security query lists
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: security-query-lists
|
||||
path: data/reusables/code-scanning/codeql-query-tables/
|
||||
|
||||
generate-quality-query-lists:
|
||||
if: github.repository == 'github/docs-internal'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository code
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- name: Checkout codeql repo
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
repository: github/codeql
|
||||
path: codeql
|
||||
ref: ${{ inputs.SOURCE_BRANCH || 'main' }}
|
||||
|
||||
- name: Get the codeql SHA being synced
|
||||
id: codeql
|
||||
shell: bash
|
||||
run: |
|
||||
cd codeql
|
||||
OPENAPI_COMMIT_SHA=$(git rev-parse HEAD)
|
||||
echo "OPENAPI_COMMIT_SHA=$OPENAPI_COMMIT_SHA" >> $GITHUB_OUTPUT
|
||||
echo "Copied files from github/codeql repo. Commit SHA: $OPENAPI_COMMIT_SHA"
|
||||
|
||||
- name: Download CodeQL CLI
|
||||
# Look under the `codeql` directory, as this is where we checked out the `github/codeql` repo
|
||||
uses: ./codeql/.github/actions/fetch-codeql
|
||||
|
||||
- name: Test CodeQL CLI Download
|
||||
shell: bash
|
||||
run: codeql --version
|
||||
|
||||
# "Server for running multiple commands while avoiding repeated JVM initialization."
|
||||
# Having started this should speed up the execution of the various
|
||||
# CLI calls of the executable.
|
||||
- name: Start CodeQL CLI server in the background
|
||||
shell: bash
|
||||
run: |
|
||||
codeql execute cli-server &
|
||||
sleep 3
|
||||
codeql --version
|
||||
|
||||
- name: Build code quality query lists
|
||||
shell: bash
|
||||
run: |
|
||||
for lang in "csharp" "go" "java" "javascript" "python" "ruby"; do
|
||||
echo "Generating code quality query list for $lang"
|
||||
npm run generate-code-quality-query-list -- \
|
||||
--verbose \
|
||||
--codeql-path codeql \
|
||||
--codeql-dir codeql \
|
||||
-o data/reusables/code-quality/codeql-query-tables/$lang.md \
|
||||
$lang
|
||||
done
|
||||
|
||||
- name: Upload quality query lists
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: quality-query-lists
|
||||
path: data/reusables/code-quality/codeql-query-tables/
|
||||
|
||||
create-pull-request:
|
||||
if: github.repository == 'github/docs-internal'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
needs: [generate-security-query-lists, generate-quality-query-lists]
|
||||
steps:
|
||||
- name: Checkout repository code
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- name: Checkout codeql repo
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
repository: github/codeql
|
||||
path: codeql
|
||||
ref: ${{ inputs.SOURCE_BRANCH || 'main' }}
|
||||
|
||||
- name: Get the codeql SHA being synced
|
||||
id: codeql
|
||||
shell: bash
|
||||
run: |
|
||||
cd codeql
|
||||
OPENAPI_COMMIT_SHA=$(git rev-parse HEAD)
|
||||
echo "OPENAPI_COMMIT_SHA=$OPENAPI_COMMIT_SHA" >> $GITHUB_OUTPUT
|
||||
echo "Copied files from github/codeql repo. Commit SHA: $OPENAPI_COMMIT_SHA"
|
||||
|
||||
- name: Download security query lists
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
with:
|
||||
name: security-query-lists
|
||||
path: data/reusables/code-scanning/codeql-query-tables/
|
||||
|
||||
- name: Download quality query lists
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
with:
|
||||
name: quality-query-lists
|
||||
path: data/reusables/code-quality/codeql-query-tables/
|
||||
|
||||
- name: Insight into diff
|
||||
shell: bash
|
||||
run: |
|
||||
git diff
|
||||
|
||||
- name: Create pull request
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
DRY_RUN: ${{ github.event_name == 'pull_request'}}
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
# When we started, we downloaded the CodeQL CLI here in this workflow.
|
||||
# We have no intention of checking that in but we also don't want
|
||||
# `git status ...` to show it as an untracked file.
|
||||
rm -fr ./codeql
|
||||
|
||||
# If nothing to commit, exit now. It's fine. No orphans.
|
||||
changes=$(git diff --name-only | wc -l)
|
||||
untracked=$(git status --untracked-files --short | wc -l)
|
||||
if [[ $changes -eq 0 ]] && [[ $untracked -eq 0 ]]; then
|
||||
echo "There are no changes to commit after running the generation and conversion scripts. Exiting..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git config --global user.name "docs-bot"
|
||||
git config --global user.email "77750099+docs-bot@users.noreply.github.com"
|
||||
|
||||
branchname=codeql-query-tables-${{ steps.codeql.outputs.OPENAPI_COMMIT_SHA }}
|
||||
|
||||
# Exit if the branch already exists. Since the actions/checkout fetch-depth is 1,
|
||||
# it doesn't "know" about branches locally, so we need to manually list them.
|
||||
branchExists=$(git ls-remote --heads origin refs/heads/$branchname | wc -l)
|
||||
|
||||
# When run on a pull_request, we're just testing the tooling.
|
||||
# Exit before it actually pushes the possible changes.
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "Dry-run mode when run in a pull request"
|
||||
echo "See the 'Insight into diff' step for the changes it would create PR about."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ $branchExists -ne 0 ]; then
|
||||
echo "Branch $branchname already exists in the remote repository."
|
||||
exit 0
|
||||
else
|
||||
git checkout -b $branchname
|
||||
fi
|
||||
|
||||
git add data/reusables/code-scanning/codeql-query-tables
|
||||
git add data/reusables/code-quality/codeql-query-tables
|
||||
git commit -m "Update CodeQL query tables"
|
||||
git push -u origin $branchname
|
||||
|
||||
echo "Creating pull request..."
|
||||
gh pr create \
|
||||
--title "Update CodeQL query tables" \
|
||||
--repo github/docs-internal \
|
||||
--label "codeql-query-tables,skip FR board,ready-for-doc-review,workflow-generated" \
|
||||
--body '👋 humans. This PR updates the **CodeQL query table reusables** with the latest changes in preparation for the next **CodeQL CLI** release. (Synced from codeql@${{ steps.codeql.outputs.OPENAPI_COMMIT_SHA }})
|
||||
|
||||
|
||||
No action is required from the first responder for the Docs content team. This PR is automatically added to the Docs content review board. Any writer can review this by checking that the PR looks sensible. If CI does not pass or other problems arise, contact #docs-engineering on slack.
|
||||
|
||||
|
||||
When the DRI for the CodeQL CLI release is ready to publish, they will ask us to merge this PR in #docs-content.'
|
||||
31
Tests/Fixtures/real-yaml/github-actions-node.yml
Normal file
31
Tests/Fixtures/real-yaml/github-actions-node.yml
Normal file
@ -0,0 +1,31 @@
|
||||
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
|
||||
|
||||
name: Node.js CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.x, 20.x, 22.x]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
- run: npm ci
|
||||
- run: npm run build --if-present
|
||||
- run: npm test
|
||||
173
Tests/Fixtures/real-yaml/github-docs-test-workflow.yml
Normal file
173
Tests/Fixtures/real-yaml/github-docs-test-workflow.yml
Normal file
@ -0,0 +1,173 @@
|
||||
name: Test
|
||||
|
||||
# **What it does**: Runs our tests.
|
||||
# **Why we have it**: We want our tests to pass before merging code.
|
||||
# **Who does it impact**: Docs engineering, open-source engineering contributors.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
merge_group:
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
# This allows a subsequently queued workflow run to interrupt previous runs
|
||||
concurrency:
|
||||
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
# Setting this will activate the vitest tests that depend on actually
|
||||
# sending real search queries to Elasticsearch
|
||||
ELASTICSEARCH_URL: http://localhost:9200/
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: ${{ matrix.name }}
|
||||
if: github.repository == 'github/docs-internal' || github.repository == 'github/docs'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Note that *if you add* to this, remember to also add that
|
||||
# to the **required checks** in the branch protection rules.
|
||||
name:
|
||||
# src/ directory
|
||||
- archives
|
||||
- article-api
|
||||
- assets
|
||||
- audit-logs
|
||||
- automated-pipelines
|
||||
# - bookmarklets
|
||||
# - code-scanning
|
||||
# - codeql-cli
|
||||
- color-schemes
|
||||
- content-linter
|
||||
- content-render
|
||||
- data-directory
|
||||
# - dev-toc
|
||||
- early-access
|
||||
- events
|
||||
- fixtures
|
||||
- frame
|
||||
- github-apps
|
||||
- graphql
|
||||
- landings
|
||||
- languages
|
||||
# - links
|
||||
- observability
|
||||
# - open-source
|
||||
# - pages
|
||||
- products
|
||||
- redirects
|
||||
- release-notes
|
||||
- rest
|
||||
- search
|
||||
- secret-scanning
|
||||
- shielding
|
||||
# - tests
|
||||
# - tools
|
||||
- versions
|
||||
- webhooks
|
||||
- workflows
|
||||
|
||||
# The languages suite only runs on docs-internal
|
||||
isPrivateRepo:
|
||||
- ${{ github.repository == 'github/docs-internal' }}
|
||||
exclude:
|
||||
- name: languages
|
||||
isPrivateRepo: false
|
||||
|
||||
steps:
|
||||
# Each of these ifs needs to be repeated at each step to make sure the required check still runs
|
||||
# Even if if doesn't do anything
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
# Fetch 2 commits so tj-actions/changed-files can diff without extra API calls
|
||||
fetch-depth: 2
|
||||
|
||||
- uses: ./.github/actions/setup-elasticsearch
|
||||
if: ${{ matrix.name == 'search' || matrix.name == 'languages' }}
|
||||
|
||||
- uses: ./.github/actions/node-npm-setup
|
||||
|
||||
- uses: ./.github/actions/get-docs-early-access
|
||||
if: ${{ github.repository == 'github/docs-internal' }}
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
|
||||
- name: Check the test fixture data (if applicable)
|
||||
if: ${{ matrix.name == 'fixtures' }}
|
||||
run: npm run copy-fixture-data -- --check
|
||||
|
||||
# This keeps our fixture content/data in check
|
||||
- name: Check the test fixture content (if applicable)
|
||||
if: ${{ matrix.name == 'fixtures' }}
|
||||
env:
|
||||
ROOT: src/fixtures/fixtures
|
||||
run: |
|
||||
# If either of these fail, it means our fixture content's internal
|
||||
# links can and should be updated.
|
||||
npm run update-internal-links -- --dry-run --check --strict \
|
||||
src/fixtures/fixtures/content \
|
||||
--exclude src/fixtures/fixtures/content/get-started/foo/typo-autotitling.md \
|
||||
--exclude src/fixtures/fixtures/content/get-started/foo/anchor-autotitling.md
|
||||
npm run update-internal-links -- --dry-run --check --strict \
|
||||
src/fixtures/fixtures/data
|
||||
|
||||
- name: Clone all translations
|
||||
if: ${{ matrix.name == 'languages' }}
|
||||
uses: ./.github/actions/clone-translations
|
||||
with:
|
||||
token: ${{ secrets.DOCS_BOT_PAT_BASE }}
|
||||
|
||||
- name: Gather files changed
|
||||
if: ${{ matrix.name == 'content-linter' }}
|
||||
id: changed_files
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
|
||||
- name: Write changed files to diff file
|
||||
if: ${{ matrix.name == 'content-linter' }}
|
||||
run: echo "${{ steps.changed_files.outputs.all_modified_files }}" > get_diff_files.txt
|
||||
|
||||
- uses: ./.github/actions/cache-nextjs
|
||||
|
||||
- name: Run build script
|
||||
run: npm run build
|
||||
|
||||
- uses: ./.github/actions/warmup-remotejson-cache
|
||||
# Only the 'routing' tests include end-to-end tests about
|
||||
# archived enterprise server URLs.
|
||||
if: ${{ matrix.name == 'redirects' }}
|
||||
|
||||
- uses: ./.github/actions/precompute-pageinfo
|
||||
# Only the 'pageinfo' tests include end-to-end tests about this.
|
||||
if: ${{ matrix.name == 'article-api' }}
|
||||
env:
|
||||
ROOT: src/fixtures/fixtures
|
||||
|
||||
- name: Index fixtures into the local Elasticsearch
|
||||
# For the sake of saving time, only run this step if the group
|
||||
# is one that will run tests against an Elasticsearch on localhost.
|
||||
if: ${{ matrix.name == 'search' || matrix.name == 'languages' }}
|
||||
run: npm run index-test-fixtures
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
DIFF_FILE: get_diff_files.txt
|
||||
CHANGELOG_CACHE_FILE_PATH: src/fixtures/fixtures/changelog-feed.json
|
||||
# By default, when `process.env.NODE_ENV === 'test'` it forces the
|
||||
# tests run only in English. The exception is the
|
||||
# `languages` suite which needs all languages to be set up.
|
||||
ENABLED_LANGUAGES: ${{ matrix.name == 'languages' && 'all' || '' }}
|
||||
ROOT: ${{ (matrix.name == 'fixtures' || matrix.name == 'article-api' || matrix.name == 'landings' ) && 'src/fixtures/fixtures' || '' }}
|
||||
TRANSLATIONS_FIXTURE_ROOT: ${{ (matrix.name == 'fixtures' || matrix.name == 'article-api') && 'src/fixtures/fixtures/translations' || '' }}
|
||||
# Enable debug logging when "Re-run jobs with debug logging" is used in GitHub Actions UI
|
||||
# This will output additional timing and path information to help diagnose timeout issues
|
||||
RUNNER_DEBUG: ${{ runner.debug }}
|
||||
VITEST_FLAGS: ${{ matrix.name == 'article-api' && '--no-file-parallelism --maxWorkers=1' || '' }}
|
||||
run: npm test -- $VITEST_FLAGS src/${{ matrix.name }}/tests/
|
||||
@ -0,0 +1,288 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: jenkins-operator
|
||||
---
|
||||
# permissions to do leader election.
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: leader-election-role
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
- coordination.k8s.io
|
||||
resources:
|
||||
- configmaps
|
||||
- leases
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- events
|
||||
verbs:
|
||||
- create
|
||||
- patch
|
||||
---
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: jenkins-operator
|
||||
rules:
|
||||
- apiGroups:
|
||||
- apps
|
||||
resources:
|
||||
- daemonsets
|
||||
- deployments
|
||||
- replicasets
|
||||
- statefulsets
|
||||
verbs:
|
||||
- '*'
|
||||
- apiGroups:
|
||||
- apps
|
||||
- jenkins-operator
|
||||
resources:
|
||||
- deployments/finalizers
|
||||
verbs:
|
||||
- update
|
||||
- apiGroups:
|
||||
- build.openshift.io
|
||||
resources:
|
||||
- buildconfigs
|
||||
- builds
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
- secrets
|
||||
- services
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
- list
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- events
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- persistentvolumeclaims
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
- pods/exec
|
||||
verbs:
|
||||
- '*'
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods/log
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods/portforward
|
||||
verbs:
|
||||
- create
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- serviceaccounts
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
- list
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- image.openshift.io
|
||||
resources:
|
||||
- imagestreams
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- jenkins.io
|
||||
resources:
|
||||
- jenkins/finalizers
|
||||
verbs:
|
||||
- update
|
||||
- apiGroups:
|
||||
- jenkins.io
|
||||
resources:
|
||||
- jenkins/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- jenkins.io
|
||||
resources:
|
||||
- '*'
|
||||
verbs:
|
||||
- '*'
|
||||
- apiGroups:
|
||||
- rbac.authorization.k8s.io
|
||||
resources:
|
||||
- rolebindings
|
||||
- roles
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
- list
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- "route.openshift.io"
|
||||
resources:
|
||||
- routes
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
- list
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- "image.openshift.io"
|
||||
resources:
|
||||
- imagestreams
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- "build.openshift.io"
|
||||
resources:
|
||||
- builds
|
||||
- buildconfigs
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: leader-election-rolebinding
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: leader-election-role
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: jenkins-operator
|
||||
---
|
||||
kind: RoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: jenkins-operator
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: jenkins-operator
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: jenkins-operator
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: jenkins-operator
|
||||
labels:
|
||||
app.kubernetes.io/name: jenkins-operator
|
||||
helm.sh/chart: jenkins-operator-0.9.0-beta1
|
||||
app.kubernetes.io/version: "0.9.0-beta1"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: jenkins-operator
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: jenkins-operator
|
||||
spec:
|
||||
serviceAccountName: jenkins-operator
|
||||
containers:
|
||||
- name: jenkins-operator
|
||||
image: quay.io/jenkins-kubernetes-operator/operator:v0.9.0-beta2
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
protocol: TCP
|
||||
command:
|
||||
- /manager
|
||||
args:
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: 8081
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 20
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /readyz
|
||||
port: 8081
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
env:
|
||||
- name: WATCH_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
- name: POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: OPERATOR_NAME
|
||||
value: "jenkins-operator"
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 120Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 120Mi
|
||||
19
Tests/Fixtures/real-yaml/kubernetes-website-deployment.yaml
Normal file
19
Tests/Fixtures/real-yaml/kubernetes-website-deployment.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
replicas: 2 # tells deployment to run 2 pods matching the template
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.14.2
|
||||
ports:
|
||||
- containerPort: 80
|
||||
170
Tests/Fixtures/real-yaml/openapi-api-with-examples.yaml
Normal file
170
Tests/Fixtures/real-yaml/openapi-api-with-examples.yaml
Normal file
@ -0,0 +1,170 @@
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
title: Simple API overview
|
||||
version: 2.0.0
|
||||
paths:
|
||||
/:
|
||||
get:
|
||||
operationId: listVersionsv2
|
||||
summary: List API versions
|
||||
responses:
|
||||
'200':
|
||||
description: |-
|
||||
200 response
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
foo:
|
||||
value:
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"status": "CURRENT",
|
||||
"updated": "2011-01-21T11:33:21Z",
|
||||
"id": "v2.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://127.0.0.1:8774/v2/",
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"status": "EXPERIMENTAL",
|
||||
"updated": "2013-07-23T11:33:21Z",
|
||||
"id": "v3.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://127.0.0.1:8774/v3/",
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
'300':
|
||||
description: |-
|
||||
300 response
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
foo:
|
||||
value: |
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"status": "CURRENT",
|
||||
"updated": "2011-01-21T11:33:21Z",
|
||||
"id": "v2.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://127.0.0.1:8774/v2/",
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"status": "EXPERIMENTAL",
|
||||
"updated": "2013-07-23T11:33:21Z",
|
||||
"id": "v3.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://127.0.0.1:8774/v3/",
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
/v2:
|
||||
get:
|
||||
operationId: getVersionDetailsv2
|
||||
summary: Show API version details
|
||||
responses:
|
||||
'200':
|
||||
description: |-
|
||||
200 response
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
foo:
|
||||
value:
|
||||
{
|
||||
"version": {
|
||||
"status": "CURRENT",
|
||||
"updated": "2011-01-21T11:33:21Z",
|
||||
"media-types": [
|
||||
{
|
||||
"base": "application/xml",
|
||||
"type": "application/vnd.openstack.compute+xml;version=2"
|
||||
},
|
||||
{
|
||||
"base": "application/json",
|
||||
"type": "application/vnd.openstack.compute+json;version=2"
|
||||
}
|
||||
],
|
||||
"id": "v2.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://127.0.0.1:8774/v2/",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://docs.openstack.org/api/openstack-compute/2/os-compute-devguide-2.pdf",
|
||||
"type": "application/pdf",
|
||||
"rel": "describedby"
|
||||
},
|
||||
{
|
||||
"href": "http://docs.openstack.org/api/openstack-compute/2/wadl/os-compute-2.wadl",
|
||||
"type": "application/vnd.sun.wadl+xml",
|
||||
"rel": "describedby"
|
||||
},
|
||||
{
|
||||
"href": "http://docs.openstack.org/api/openstack-compute/2/wadl/os-compute-2.wadl",
|
||||
"type": "application/vnd.sun.wadl+xml",
|
||||
"rel": "describedby"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
'203':
|
||||
description: |-
|
||||
203 response
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
foo:
|
||||
value:
|
||||
{
|
||||
"version": {
|
||||
"status": "CURRENT",
|
||||
"updated": "2011-01-21T11:33:21Z",
|
||||
"media-types": [
|
||||
{
|
||||
"base": "application/xml",
|
||||
"type": "application/vnd.openstack.compute+xml;version=2"
|
||||
},
|
||||
{
|
||||
"base": "application/json",
|
||||
"type": "application/vnd.openstack.compute+json;version=2"
|
||||
}
|
||||
],
|
||||
"id": "v2.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "http://23.253.228.211:8774/v2/",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "http://docs.openstack.org/api/openstack-compute/2/os-compute-devguide-2.pdf",
|
||||
"type": "application/pdf",
|
||||
"rel": "describedby"
|
||||
},
|
||||
{
|
||||
"href": "http://docs.openstack.org/api/openstack-compute/2/wadl/os-compute-2.wadl",
|
||||
"type": "application/vnd.sun.wadl+xml",
|
||||
"rel": "describedby"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
61
Tests/Fixtures/real-yaml/openapi-callback-example.yaml
Normal file
61
Tests/Fixtures/real-yaml/openapi-callback-example.yaml
Normal file
@ -0,0 +1,61 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: Callback Example
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/streams:
|
||||
post:
|
||||
description: subscribes a client to receive out-of-band data
|
||||
parameters:
|
||||
- name: callbackUrl
|
||||
in: query
|
||||
required: true
|
||||
description: |
|
||||
the location where data will be sent. Must be network accessible
|
||||
by the source server
|
||||
schema:
|
||||
type: string
|
||||
format: uri
|
||||
example: https://tonys-server.com
|
||||
responses:
|
||||
'201':
|
||||
description: subscription successfully created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
description: subscription information
|
||||
required:
|
||||
- subscriptionId
|
||||
properties:
|
||||
subscriptionId:
|
||||
description: this unique identifier allows management of the subscription
|
||||
type: string
|
||||
example: 2531329f-fb09-4ef7-887e-84e648214436
|
||||
callbacks:
|
||||
# the name `onData` is a convenience locator
|
||||
onData:
|
||||
# when data is sent, it will be sent to the `callbackUrl` provided
|
||||
# when making the subscription PLUS the suffix `/data`
|
||||
'{$request.query.callbackUrl}/data':
|
||||
post:
|
||||
requestBody:
|
||||
description: subscription payload
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
userData:
|
||||
type: string
|
||||
responses:
|
||||
'202':
|
||||
description: |
|
||||
Your server implementation should return this HTTP status code
|
||||
if the data was received successfully
|
||||
'204':
|
||||
description: |
|
||||
Your server should return this HTTP status code if no longer interested
|
||||
in further updates
|
||||
203
Tests/Fixtures/real-yaml/openapi-link-example.yaml
Normal file
203
Tests/Fixtures/real-yaml/openapi-link-example.yaml
Normal file
@ -0,0 +1,203 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: Link Example
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/2.0/users/{username}:
|
||||
get:
|
||||
operationId: getUserByName
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: The User
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/user'
|
||||
links:
|
||||
userRepositories:
|
||||
$ref: '#/components/links/UserRepositories'
|
||||
/2.0/repositories/{username}:
|
||||
get:
|
||||
operationId: getRepositoriesByOwner
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: repositories owned by the supplied user
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/repository'
|
||||
links:
|
||||
userRepository:
|
||||
$ref: '#/components/links/UserRepository'
|
||||
/2.0/repositories/{username}/{slug}:
|
||||
get:
|
||||
operationId: getRepository
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: slug
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: The repository
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/repository'
|
||||
links:
|
||||
repositoryPullRequests:
|
||||
$ref: '#/components/links/RepositoryPullRequests'
|
||||
/2.0/repositories/{username}/{slug}/pullrequests:
|
||||
get:
|
||||
operationId: getPullRequestsByRepository
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: slug
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: state
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- open
|
||||
- merged
|
||||
- declined
|
||||
responses:
|
||||
'200':
|
||||
description: an array of pull request objects
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/pullrequest'
|
||||
/2.0/repositories/{username}/{slug}/pullrequests/{pid}:
|
||||
get:
|
||||
operationId: getPullRequestsById
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: slug
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: pid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: a pull request object
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/pullrequest'
|
||||
links:
|
||||
pullRequestMerge:
|
||||
$ref: '#/components/links/PullRequestMerge'
|
||||
/2.0/repositories/{username}/{slug}/pullrequests/{pid}/merge:
|
||||
post:
|
||||
operationId: mergePullRequest
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: slug
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: pid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'204':
|
||||
description: the PR was successfully merged
|
||||
components:
|
||||
links:
|
||||
UserRepositories:
|
||||
# returns array of '#/components/schemas/repository'
|
||||
operationId: getRepositoriesByOwner
|
||||
parameters:
|
||||
username: $response.body#/username
|
||||
UserRepository:
|
||||
# returns '#/components/schemas/repository'
|
||||
operationId: getRepository
|
||||
parameters:
|
||||
username: $response.body#/owner/username
|
||||
slug: $response.body#/slug
|
||||
RepositoryPullRequests:
|
||||
# returns '#/components/schemas/pullrequest'
|
||||
operationId: getPullRequestsByRepository
|
||||
parameters:
|
||||
username: $response.body#/owner/username
|
||||
slug: $response.body#/slug
|
||||
PullRequestMerge:
|
||||
# executes /2.0/repositories/{username}/{slug}/pullrequests/{pid}/merge
|
||||
operationId: mergePullRequest
|
||||
parameters:
|
||||
username: $response.body#/author/username
|
||||
slug: $response.body#/repository/slug
|
||||
pid: $response.body#/id
|
||||
schemas:
|
||||
user:
|
||||
type: object
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
uuid:
|
||||
type: string
|
||||
repository:
|
||||
type: object
|
||||
properties:
|
||||
slug:
|
||||
type: string
|
||||
owner:
|
||||
$ref: '#/components/schemas/user'
|
||||
pullrequest:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
title:
|
||||
type: string
|
||||
repository:
|
||||
$ref: '#/components/schemas/repository'
|
||||
author:
|
||||
$ref: '#/components/schemas/user'
|
||||
158
Tests/Fixtures/real-yaml/openapi-petstore-expanded.yaml
Normal file
158
Tests/Fixtures/real-yaml/openapi-petstore-expanded.yaml
Normal file
@ -0,0 +1,158 @@
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
version: 1.0.0
|
||||
title: Swagger Petstore
|
||||
description: A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification
|
||||
termsOfService: http://swagger.io/terms/
|
||||
contact:
|
||||
name: Swagger API Team
|
||||
email: apiteam@swagger.io
|
||||
url: http://swagger.io
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
servers:
|
||||
- url: https://petstore.swagger.io/v2
|
||||
paths:
|
||||
/pets:
|
||||
get:
|
||||
description: |
|
||||
Returns all pets from the system that the user has access to
|
||||
Nam sed condimentum est. Maecenas tempor sagittis sapien, nec rhoncus sem sagittis sit amet. Aenean at gravida augue, ac iaculis sem. Curabitur odio lorem, ornare eget elementum nec, cursus id lectus. Duis mi turpis, pulvinar ac eros ac, tincidunt varius justo. In hac habitasse platea dictumst. Integer at adipiscing ante, a sagittis ligula. Aenean pharetra tempor ante molestie imperdiet. Vivamus id aliquam diam. Cras quis velit non tortor eleifend sagittis. Praesent at enim pharetra urna volutpat venenatis eget eget mauris. In eleifend fermentum facilisis. Praesent enim enim, gravida ac sodales sed, placerat id erat. Suspendisse lacus dolor, consectetur non augue vel, vehicula interdum libero. Morbi euismod sagittis libero sed lacinia.
|
||||
|
||||
Sed tempus felis lobortis leo pulvinar rutrum. Nam mattis velit nisl, eu condimentum ligula luctus nec. Phasellus semper velit eget aliquet faucibus. In a mattis elit. Phasellus vel urna viverra, condimentum lorem id, rhoncus nibh. Ut pellentesque posuere elementum. Sed a varius odio. Morbi rhoncus ligula libero, vel eleifend nunc tristique vitae. Fusce et sem dui. Aenean nec scelerisque tortor. Fusce malesuada accumsan magna vel tempus. Quisque mollis felis eu dolor tristique, sit amet auctor felis gravida. Sed libero lorem, molestie sed nisl in, accumsan tempor nisi. Fusce sollicitudin massa ut lacinia mattis. Sed vel eleifend lorem. Pellentesque vitae felis pretium, pulvinar elit eu, euismod sapien.
|
||||
operationId: findPets
|
||||
parameters:
|
||||
- name: tags
|
||||
in: query
|
||||
description: tags to filter by
|
||||
required: false
|
||||
style: form
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
- name: limit
|
||||
in: query
|
||||
description: maximum number of results to return
|
||||
required: false
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
responses:
|
||||
'200':
|
||||
description: pet response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
post:
|
||||
description: Creates a new pet in the store. Duplicates are allowed
|
||||
operationId: addPet
|
||||
requestBody:
|
||||
description: Pet to add to the store
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NewPet'
|
||||
responses:
|
||||
'200':
|
||||
description: pet response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
/pets/{id}:
|
||||
get:
|
||||
description: Returns a user based on a single ID, if the user does not have access to the pet
|
||||
operationId: find pet by id
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
description: ID of pet to fetch
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
responses:
|
||||
'200':
|
||||
description: pet response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Pet'
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
delete:
|
||||
description: deletes a single pet based on the ID supplied
|
||||
operationId: deletePet
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
description: ID of pet to delete
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
responses:
|
||||
'204':
|
||||
description: pet deleted
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
components:
|
||||
schemas:
|
||||
Pet:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/NewPet'
|
||||
- type: object
|
||||
required:
|
||||
- id
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
NewPet:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
tag:
|
||||
type: string
|
||||
|
||||
Error:
|
||||
type: object
|
||||
required:
|
||||
- code
|
||||
- message
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
format: int32
|
||||
message:
|
||||
type: string
|
||||
210
Tests/Fixtures/real-yaml/openapi-uspto.yaml
Normal file
210
Tests/Fixtures/real-yaml/openapi-uspto.yaml
Normal file
@ -0,0 +1,210 @@
|
||||
openapi: 3.0.1
|
||||
servers:
|
||||
- url: '{scheme}://developer.uspto.gov/ds-api'
|
||||
variables:
|
||||
scheme:
|
||||
description: 'The Data Set API is accessible via https and http'
|
||||
enum:
|
||||
- 'https'
|
||||
- 'http'
|
||||
default: 'https'
|
||||
info:
|
||||
description: >-
|
||||
The Data Set API (DSAPI) allows the public users to discover and search
|
||||
USPTO exported data sets. This is a generic API that allows USPTO users to
|
||||
make any CSV based data files searchable through API. With the help of GET
|
||||
call, it returns the list of data fields that are searchable. With the help
|
||||
of POST call, data can be fetched based on the filters on the field names.
|
||||
Please note that POST call is used to search the actual data. The reason for
|
||||
the POST call is that it allows users to specify any complex search criteria
|
||||
without worry about the GET size limitations as well as encoding of the
|
||||
input parameters.
|
||||
version: 1.0.0
|
||||
title: USPTO Data Set API
|
||||
contact:
|
||||
name: Open Data Portal
|
||||
url: 'https://developer.uspto.gov'
|
||||
email: developer@uspto.gov
|
||||
tags:
|
||||
- name: metadata
|
||||
description: Find out about the data sets
|
||||
- name: search
|
||||
description: Search a data set
|
||||
paths:
|
||||
/:
|
||||
get:
|
||||
tags:
|
||||
- metadata
|
||||
operationId: list-data-sets
|
||||
summary: List available data sets
|
||||
responses:
|
||||
'200':
|
||||
description: Returns a list of data sets
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/dataSetList'
|
||||
example:
|
||||
{
|
||||
"total": 2,
|
||||
"apis": [
|
||||
{
|
||||
"apiKey": "oa_citations",
|
||||
"apiVersionNumber": "v1",
|
||||
"apiUrl": "https://developer.uspto.gov/ds-api/oa_citations/v1/fields",
|
||||
"apiDocumentationUrl": "https://developer.uspto.gov/ds-api-docs/index.html?url=https://developer.uspto.gov/ds-api/swagger/docs/oa_citations.json"
|
||||
},
|
||||
{
|
||||
"apiKey": "cancer_moonshot",
|
||||
"apiVersionNumber": "v1",
|
||||
"apiUrl": "https://developer.uspto.gov/ds-api/cancer_moonshot/v1/fields",
|
||||
"apiDocumentationUrl": "https://developer.uspto.gov/ds-api-docs/index.html?url=https://developer.uspto.gov/ds-api/swagger/docs/cancer_moonshot.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
/{dataset}/{version}/fields:
|
||||
get:
|
||||
tags:
|
||||
- metadata
|
||||
summary: >-
|
||||
Provides the general information about the API and the list of fields
|
||||
that can be used to query the dataset.
|
||||
description: >-
|
||||
This GET API returns the list of all the searchable field names that are
|
||||
in the oa_citations. Please see the 'fields' attribute which returns an
|
||||
array of field names. Each field or a combination of fields can be
|
||||
searched using the syntax options shown below.
|
||||
operationId: list-searchable-fields
|
||||
parameters:
|
||||
- name: dataset
|
||||
in: path
|
||||
description: 'Name of the dataset.'
|
||||
required: true
|
||||
example: "oa_citations"
|
||||
schema:
|
||||
type: string
|
||||
- name: version
|
||||
in: path
|
||||
description: Version of the dataset.
|
||||
required: true
|
||||
example: "v1"
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: >-
|
||||
The dataset API for the given version is found and it is accessible
|
||||
to consume.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
'404':
|
||||
description: >-
|
||||
The combination of dataset name and version is not found in the
|
||||
system or it is not published yet to be consumed by public.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
/{dataset}/{version}/records:
|
||||
post:
|
||||
tags:
|
||||
- search
|
||||
summary: >-
|
||||
Provides search capability for the data set with the given search
|
||||
criteria.
|
||||
description: >-
|
||||
This API is based on Solr/Lucene Search. The data is indexed using
|
||||
SOLR. This GET API returns the list of all the searchable field names
|
||||
that are in the Solr Index. Please see the 'fields' attribute which
|
||||
returns an array of field names. Each field or a combination of fields
|
||||
can be searched using the Solr/Lucene Syntax. Please refer
|
||||
https://lucene.apache.org/core/3_6_2/queryparsersyntax.html#Overview for
|
||||
the query syntax. List of field names that are searchable can be
|
||||
determined using above GET api.
|
||||
operationId: perform-search
|
||||
parameters:
|
||||
- name: version
|
||||
in: path
|
||||
description: Version of the dataset.
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
default: v1
|
||||
- name: dataset
|
||||
in: path
|
||||
description: 'Name of the dataset. In this case, the default value is oa_citations'
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
default: oa_citations
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: object
|
||||
'404':
|
||||
description: No matching record found for the given criteria.
|
||||
requestBody:
|
||||
content:
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
criteria:
|
||||
description: >-
|
||||
Uses Lucene Query Syntax in the format of
|
||||
propertyName:value, propertyName:[num1 TO num2] and date
|
||||
range format: propertyName:[yyyyMMdd TO yyyyMMdd]. In the
|
||||
response please see the 'docs' element which has the list of
|
||||
record objects. Each record structure would consist of all
|
||||
the fields and their corresponding values.
|
||||
type: string
|
||||
default: '*:*'
|
||||
start:
|
||||
description: Starting record number. Default value is 0.
|
||||
type: integer
|
||||
default: 0
|
||||
rows:
|
||||
description: >-
|
||||
Specify number of rows to be returned. If you run the search
|
||||
with default values, in the response you will see 'numFound'
|
||||
attribute which will tell the number of records available in
|
||||
the dataset.
|
||||
type: integer
|
||||
default: 100
|
||||
required:
|
||||
- criteria
|
||||
components:
|
||||
schemas:
|
||||
dataSetList:
|
||||
type: object
|
||||
properties:
|
||||
total:
|
||||
type: integer
|
||||
apis:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
apiKey:
|
||||
type: string
|
||||
description: To be used as a dataset parameter value
|
||||
apiVersionNumber:
|
||||
type: string
|
||||
description: To be used as a version parameter value
|
||||
apiUrl:
|
||||
type: string
|
||||
format: uriref
|
||||
description: "The URL describing the dataset's fields"
|
||||
apiDocumentationUrl:
|
||||
type: string
|
||||
format: uriref
|
||||
description: A URL to the API console for each API
|
||||
24
Tests/Fixtures/real-yaml/starter-workflows-ci-ada-yml.yml
Normal file
24
Tests/Fixtures/real-yaml/starter-workflows-ci-ada-yml.yml
Normal file
@ -0,0 +1,24 @@
|
||||
name: Ada (GNAT)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up GNAT toolchain
|
||||
run: >
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install gnat gprbuild
|
||||
|
||||
- name: Build
|
||||
run: gprbuild -j0 -p
|
||||
@ -0,0 +1,26 @@
|
||||
name: Android CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: set up JDK 11
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '11'
|
||||
distribution: 'temurin'
|
||||
cache: gradle
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
||||
25
Tests/Fixtures/real-yaml/starter-workflows-ci-ant-yml.yml
Normal file
25
Tests/Fixtures/real-yaml/starter-workflows-ci-ant-yml.yml
Normal file
@ -0,0 +1,25 @@
|
||||
# This workflow will build a Java project with Ant
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-ant
|
||||
|
||||
name: Java CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '11'
|
||||
distribution: 'temurin'
|
||||
- name: Build with Ant
|
||||
run: ant -noinput -buildfile build.xml
|
||||
36
Tests/Fixtures/real-yaml/starter-workflows-ci-blank-yml.yml
Normal file
36
Tests/Fixtures/real-yaml/starter-workflows-ci-blank-yml.yml
Normal file
@ -0,0 +1,36 @@
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
|
||||
name: CI
|
||||
|
||||
# Controls when the workflow will run
|
||||
on:
|
||||
# Triggers the workflow on push or pull request events but only for the $default-branch branch
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
# This workflow contains a single job called "build"
|
||||
build:
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# Runs a single command using the runners shell
|
||||
- name: Run a one-line script
|
||||
run: echo Hello, world!
|
||||
|
||||
# Runs a set of commands using the runners shell
|
||||
- name: Run a multi-line script
|
||||
run: |
|
||||
echo Add other actions to build,
|
||||
echo test, and deploy your project.
|
||||
23
Tests/Fixtures/real-yaml/starter-workflows-ci-c-cpp-yml.yml
Normal file
23
Tests/Fixtures/real-yaml/starter-workflows-ci-c-cpp-yml.yml
Normal file
@ -0,0 +1,23 @@
|
||||
name: C/C++ CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: configure
|
||||
run: ./configure
|
||||
- name: make
|
||||
run: make
|
||||
- name: make check
|
||||
run: make check
|
||||
- name: make distcheck
|
||||
run: make distcheck
|
||||
@ -0,0 +1,19 @@
|
||||
name: Clojure CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: lein deps
|
||||
- name: Run tests
|
||||
run: lein test
|
||||
@ -0,0 +1,75 @@
|
||||
# This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform.
|
||||
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml
|
||||
name: CMake on multiple platforms
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable.
|
||||
fail-fast: false
|
||||
|
||||
# Set up a matrix to run the following 3 configurations:
|
||||
# 1. <Windows, Release, latest MSVC compiler toolchain on the default runner image, default generator>
|
||||
# 2. <Linux, Release, latest GCC compiler toolchain on the default runner image, default generator>
|
||||
# 3. <Linux, Release, latest Clang compiler toolchain on the default runner image, default generator>
|
||||
#
|
||||
# To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list.
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
build_type: [Release]
|
||||
c_compiler: [gcc, clang, cl]
|
||||
include:
|
||||
- os: windows-latest
|
||||
c_compiler: cl
|
||||
cpp_compiler: cl
|
||||
- os: ubuntu-latest
|
||||
c_compiler: gcc
|
||||
cpp_compiler: g++
|
||||
- os: ubuntu-latest
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
exclude:
|
||||
- os: windows-latest
|
||||
c_compiler: gcc
|
||||
- os: windows-latest
|
||||
c_compiler: clang
|
||||
- os: ubuntu-latest
|
||||
c_compiler: cl
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set reusable strings
|
||||
# Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file.
|
||||
id: strings
|
||||
shell: bash
|
||||
run: |
|
||||
echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||
run: >
|
||||
cmake -B ${{ steps.strings.outputs.build-output-dir }}
|
||||
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
|
||||
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||
-S ${{ github.workspace }}
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
|
||||
run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }}
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{ steps.strings.outputs.build-output-dir }}
|
||||
# Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
|
||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||
run: ctest --build-config ${{ matrix.build_type }}
|
||||
@ -0,0 +1,39 @@
|
||||
# This starter workflow is for a CMake project running on a single platform. There is a different starter workflow if you need cross-platform coverage.
|
||||
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml
|
||||
name: CMake on a single platform
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
|
||||
# You can convert this to a matrix build if you need cross-platform coverage.
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{github.workspace}}/build
|
||||
# Execute tests defined by the CMake configuration.
|
||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||
run: ctest -C ${{env.BUILD_TYPE}}
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
name: Crystal CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: crystallang/crystal
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install dependencies
|
||||
run: shards install
|
||||
- name: Run tests
|
||||
run: crystal spec
|
||||
32
Tests/Fixtures/real-yaml/starter-workflows-ci-d-yml.yml
Normal file
32
Tests/Fixtures/real-yaml/starter-workflows-ci-d-yml.yml
Normal file
@ -0,0 +1,32 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
name: D
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dlang-community/setup-dlang@4c99aa991ce7d19dd3064de0a4f2f6b2f152e2d7
|
||||
|
||||
- name: 'Build & Test'
|
||||
run: |
|
||||
# Build the project, with its main file included, without unittests
|
||||
dub build --compiler=$DC
|
||||
# Build and run tests, as defined by `unittest` configuration
|
||||
# In this mode, `mainSourceFile` is excluded and `version (unittest)` are included
|
||||
# See https://dub.pm/package-format-json.html#configurations
|
||||
dub test --compiler=$DC
|
||||
42
Tests/Fixtures/real-yaml/starter-workflows-ci-dart-yml.yml
Normal file
42
Tests/Fixtures/real-yaml/starter-workflows-ci-dart-yml.yml
Normal file
@ -0,0 +1,42 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
name: Dart
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# Note: This workflow uses the latest stable version of the Dart SDK.
|
||||
# You can specify other versions if desired, see documentation here:
|
||||
# https://github.com/dart-lang/setup-dart/blob/main/README.md
|
||||
# - uses: dart-lang/setup-dart@v1
|
||||
- uses: dart-lang/setup-dart@9a04e6d73cca37bd455e0608d7e5092f881fd603
|
||||
|
||||
- name: Install dependencies
|
||||
run: dart pub get
|
||||
|
||||
# Uncomment this step to verify the use of 'dart format' on each commit.
|
||||
# - name: Verify formatting
|
||||
# run: dart format --output=none --set-exit-if-changed .
|
||||
|
||||
# Consider passing '--fatal-infos' for slightly stricter analysis.
|
||||
- name: Analyze project source
|
||||
run: dart analyze
|
||||
|
||||
# Your project will need to have tests in test/ and a dependency on
|
||||
# package:test for this step to succeed. Note that Flutter projects will
|
||||
# want to change this to 'flutter test'.
|
||||
- name: Run tests
|
||||
run: dart test
|
||||
@ -0,0 +1,38 @@
|
||||
# This workflow will trigger Datadog Synthetic tests within your Datadog organisation
|
||||
# For more information on running Synthetic tests within your GitHub workflows see: https://docs.datadoghq.com/synthetics/cicd_integrations/github_actions/
|
||||
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
# To get started:
|
||||
|
||||
# 1. Add your Datadog API (DD_API_KEY) and Application Key (DD_APP_KEY) as secrets to your GitHub repository. For more information, see: https://docs.datadoghq.com/account_management/api-app-keys/.
|
||||
# 2. Start using the action within your workflow
|
||||
|
||||
name: Run Datadog Synthetic tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# Run Synthetic tests within your GitHub workflow.
|
||||
# For additional configuration options visit the action within the marketplace: https://github.com/marketplace/actions/datadog-synthetics-ci
|
||||
- name: Run Datadog Synthetic tests
|
||||
uses: DataDog/synthetics-ci-github-action@87b505388a22005bb8013481e3f73a367b9a53eb # v1.4.0
|
||||
with:
|
||||
api_key: ${{secrets.DD_API_KEY}}
|
||||
app_key: ${{secrets.DD_APP_KEY}}
|
||||
test_search_query: 'tag:e2e-tests' #Modify this tag to suit your tagging strategy
|
||||
|
||||
|
||||
42
Tests/Fixtures/real-yaml/starter-workflows-ci-deno-yml.yml
Normal file
42
Tests/Fixtures/real-yaml/starter-workflows-ci-deno-yml.yml
Normal file
@ -0,0 +1,42 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
# This workflow will install Deno then run `deno lint` and `deno test`.
|
||||
# For more information see: https://github.com/denoland/setup-deno
|
||||
|
||||
name: Deno
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [$default-branch]
|
||||
pull_request:
|
||||
branches: [$default-branch]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Setup repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Deno
|
||||
# uses: denoland/setup-deno@v1
|
||||
uses: denoland/setup-deno@61fe2df320078202e33d7d5ad347e7dcfa0e8f31 # v1.1.2
|
||||
with:
|
||||
deno-version: v1.x
|
||||
|
||||
# Uncomment this step to verify the use of 'deno fmt' on each commit.
|
||||
# - name: Verify formatting
|
||||
# run: deno fmt --check
|
||||
|
||||
- name: Run linter
|
||||
run: deno lint
|
||||
|
||||
- name: Run tests
|
||||
run: deno test -A
|
||||
30
Tests/Fixtures/real-yaml/starter-workflows-ci-django-yml.yml
Normal file
30
Tests/Fixtures/real-yaml/starter-workflows-ci-django-yml.yml
Normal file
@ -0,0 +1,30 @@
|
||||
name: Django CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
max-parallel: 4
|
||||
matrix:
|
||||
python-version: [3.7, 3.8, 3.9]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
- name: Run Tests
|
||||
run: |
|
||||
python manage.py test
|
||||
@ -0,0 +1,18 @@
|
||||
name: Docker Image CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build the Docker image
|
||||
run: docker build . --file Dockerfile --tag my-image-name:$(date +%s)
|
||||
@ -0,0 +1,98 @@
|
||||
name: Docker
|
||||
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: $cron-daily
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
# Publish semver tags as releases.
|
||||
tags: [ 'v*.*.*' ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
env:
|
||||
# Use docker.io for Docker Hub if empty
|
||||
REGISTRY: ghcr.io
|
||||
# github.repository as <account>/<repo>
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
# This is used to complete the identity challenge
|
||||
# with sigstore/fulcio when running outside of PRs.
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Install the cosign tool except on PR
|
||||
# https://github.com/sigstore/cosign-installer
|
||||
- name: Install cosign
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 #v3.5.0
|
||||
with:
|
||||
cosign-release: 'v2.2.4'
|
||||
|
||||
# Set up BuildKit Docker container builder to be able to build
|
||||
# multi-platform images and export cache
|
||||
# https://github.com/docker/setup-buildx-action
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
|
||||
# Login against a Docker registry except on PR
|
||||
# https://github.com/docker/login-action
|
||||
- name: Log into registry ${{ env.REGISTRY }}
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Extract metadata (tags, labels) for Docker
|
||||
# https://github.com/docker/metadata-action
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
|
||||
# Build and push Docker image with Buildx (don't push on PR)
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push Docker image
|
||||
id: build-and-push
|
||||
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
# Sign the resulting Docker image digest except on PRs.
|
||||
# This will only write to the public Rekor transparency log when the Docker
|
||||
# repository is public to avoid leaking data. If you would like to publish
|
||||
# transparency data even for private images, pass --force to cosign below.
|
||||
# https://github.com/sigstore/cosign
|
||||
- name: Sign the published Docker image
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
env:
|
||||
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
|
||||
TAGS: ${{ steps.meta.outputs.tags }}
|
||||
DIGEST: ${{ steps.build-and-push.outputs.digest }}
|
||||
# This step uses the identity token to provision an ephemeral certificate
|
||||
# against the sigstore community Fulcio instance.
|
||||
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
|
||||
@ -0,0 +1,115 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
# This workflow will build, test, sign and package a WPF or Windows Forms desktop application
|
||||
# built on .NET Core.
|
||||
# To learn how to migrate your existing application to .NET Core,
|
||||
# refer to https://docs.microsoft.com/en-us/dotnet/desktop-wpf/migration/convert-project-from-net-framework
|
||||
#
|
||||
# To configure this workflow:
|
||||
#
|
||||
# 1. Configure environment variables
|
||||
# GitHub sets default environment variables for every workflow run.
|
||||
# Replace the variables relative to your project in the "env" section below.
|
||||
#
|
||||
# 2. Signing
|
||||
# Generate a signing certificate in the Windows Application
|
||||
# Packaging Project or add an existing signing certificate to the project.
|
||||
# Next, use PowerShell to encode the .pfx file using Base64 encoding
|
||||
# by running the following Powershell script to generate the output string:
|
||||
#
|
||||
# $pfx_cert = Get-Content '.\SigningCertificate.pfx' -Encoding Byte
|
||||
# [System.Convert]::ToBase64String($pfx_cert) | Out-File 'SigningCertificate_Encoded.txt'
|
||||
#
|
||||
# Open the output file, SigningCertificate_Encoded.txt, and copy the
|
||||
# string inside. Then, add the string to the repo as a GitHub secret
|
||||
# and name it "Base64_Encoded_Pfx."
|
||||
# For more information on how to configure your signing certificate for
|
||||
# this workflow, refer to https://github.com/microsoft/github-actions-for-desktop-apps#signing
|
||||
#
|
||||
# Finally, add the signing certificate password to the repo as a secret and name it "Pfx_Key".
|
||||
# See "Build the Windows Application Packaging project" below to see how the secret is used.
|
||||
#
|
||||
# For more information on GitHub Actions, refer to https://github.com/features/actions
|
||||
# For a complete CI/CD sample to get started with GitHub Action workflows for Desktop Applications,
|
||||
# refer to https://github.com/microsoft/github-actions-for-desktop-apps
|
||||
|
||||
name: .NET Core Desktop
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
configuration: [Debug, Release]
|
||||
|
||||
runs-on: windows-latest # For a list of available runner types, refer to
|
||||
# https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on
|
||||
|
||||
env:
|
||||
Solution_Name: your-solution-name # Replace with your solution name, i.e. MyWpfApp.sln.
|
||||
Test_Project_Path: your-test-project-path # Replace with the path to your test project, i.e. MyWpfApp.Tests\MyWpfApp.Tests.csproj.
|
||||
Wap_Project_Directory: your-wap-project-directory-name # Replace with the Wap project directory relative to the solution, i.e. MyWpfApp.Package.
|
||||
Wap_Project_Path: your-wap-project-path # Replace with the path to your Wap project, i.e. MyWpf.App.Package\MyWpfApp.Package.wapproj.
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# Install the .NET Core workload
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
|
||||
# Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
|
||||
- name: Setup MSBuild.exe
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
|
||||
# Execute all unit tests in the solution
|
||||
- name: Execute unit tests
|
||||
run: dotnet test
|
||||
|
||||
# Restore the application to populate the obj folder with RuntimeIdentifiers
|
||||
- name: Restore the application
|
||||
run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration
|
||||
env:
|
||||
Configuration: ${{ matrix.configuration }}
|
||||
|
||||
# Decode the base 64 encoded pfx and save the Signing_Certificate
|
||||
- name: Decode the pfx
|
||||
run: |
|
||||
$pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.Base64_Encoded_Pfx }}")
|
||||
$certificatePath = Join-Path -Path $env:Wap_Project_Directory -ChildPath GitHubActionsWorkflow.pfx
|
||||
[IO.File]::WriteAllBytes("$certificatePath", $pfx_cert_byte)
|
||||
|
||||
# Create the app package by building and packaging the Windows Application Packaging project
|
||||
- name: Create the app package
|
||||
run: msbuild $env:Wap_Project_Path /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:Appx_Package_Build_Mode /p:AppxBundle=$env:Appx_Bundle /p:PackageCertificateKeyFile=GitHubActionsWorkflow.pfx /p:PackageCertificatePassword=${{ secrets.Pfx_Key }}
|
||||
env:
|
||||
Appx_Bundle: Always
|
||||
Appx_Bundle_Platforms: x86|x64
|
||||
Appx_Package_Build_Mode: StoreUpload
|
||||
Configuration: ${{ matrix.configuration }}
|
||||
|
||||
# Remove the pfx
|
||||
- name: Remove the pfx
|
||||
run: Remove-Item -path $env:Wap_Project_Directory\GitHubActionsWorkflow.pfx
|
||||
|
||||
# Upload the MSIX package: https://github.com/marketplace/actions/upload-a-build-artifact
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: MSIX Package
|
||||
path: ${{ env.Wap_Project_Directory }}\AppPackages
|
||||
28
Tests/Fixtures/real-yaml/starter-workflows-ci-dotnet-yml.yml
Normal file
28
Tests/Fixtures/real-yaml/starter-workflows-ci-dotnet-yml.yml
Normal file
@ -0,0 +1,28 @@
|
||||
# This workflow will build a .NET project
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
|
||||
|
||||
name: .NET
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
- name: Build
|
||||
run: dotnet build --no-restore
|
||||
- name: Test
|
||||
run: dotnet test --no-build --verbosity normal
|
||||
39
Tests/Fixtures/real-yaml/starter-workflows-ci-elixir-yml.yml
Normal file
39
Tests/Fixtures/real-yaml/starter-workflows-ci-elixir-yml.yml
Normal file
@ -0,0 +1,39 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
name: Elixir CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
name: Build and test
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Elixir
|
||||
uses: erlef/setup-beam@61e01a43a562a89bfc54c7f9a378ff67b03e4a21 # v1.16.0
|
||||
with:
|
||||
elixir-version: '1.15.2' # [Required] Define the Elixir version
|
||||
otp-version: '26.0' # [Required] Define the Erlang/OTP version
|
||||
- name: Restore dependencies cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: deps
|
||||
key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }}
|
||||
restore-keys: ${{ runner.os }}-mix-
|
||||
- name: Install dependencies
|
||||
run: mix deps.get
|
||||
- name: Run tests
|
||||
run: mix test
|
||||
26
Tests/Fixtures/real-yaml/starter-workflows-ci-erlang-yml.yml
Normal file
26
Tests/Fixtures/real-yaml/starter-workflows-ci-erlang-yml.yml
Normal file
@ -0,0 +1,26 @@
|
||||
name: Erlang CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ $default-branch ]
|
||||
pull_request:
|
||||
branches: [ $default-branch ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: erlang:22.0.7
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Compile
|
||||
run: rebar3 compile
|
||||
- name: Run tests
|
||||
run: rebar3 do eunit, ct
|
||||
@ -0,0 +1,19 @@
|
||||
apiVersion: admissionregistration.k8s.io/v1
|
||||
kind: ValidatingAdmissionPolicy
|
||||
metadata:
|
||||
name: "deploy-replica-policy.example.com"
|
||||
spec:
|
||||
paramKind:
|
||||
apiVersion: rules.example.com/v1
|
||||
kind: ReplicaLimit
|
||||
matchConstraints:
|
||||
resourceRules:
|
||||
- apiGroups: ["apps"]
|
||||
apiVersions: ["v1"]
|
||||
operations: ["CREATE", "UPDATE"]
|
||||
resources: ["deployments"]
|
||||
validations:
|
||||
- expression: "object.spec.replicas <= params.maxReplicas"
|
||||
messageExpression: "'object.spec.replicas must be no greater than ' + string(params.maxReplicas)"
|
||||
reason: Invalid
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user